< August 2010 | September 2010 | October 2010 >

September 30, 2010

隣接兄弟セレクタ

CSS2 から導入された隣接兄弟セレクタだけど、IE でも 7 以降はサポートされてるみたいです。例えばこんな。

ul#menu > li { display: inline; margin: 0; padding: .5em 1em; }
ul#menu > li + li { border-left: 1px solid black; }

id="menu" の <ul> の子要素である <li> に隣接している <li> にのみ左ボーダーを指定しています。これを以下のような HTML に適用した結果を示します。

<ul id="menu">
    <li>トップページ</li>
    <li>事業内容</li>
    <li>会社概要</li>
    <li>お問い合わせ</li>
    <li>サイトマップ</li>
</ul>

結果 (Firefox 3.6.10 で表示したもの)

adjacent_sibling_selectors.png

1 番目の <li> は <li> に隣接していないので、左ボーダーがありません。2 番目以降にのみ左ボーダーが適用されています。

サンプル

September 29, 2010

Google AJAX Feed API を使ってみる

Google AJAX Feed API ってライブラリがあるみたいです。これを使えば公開されているフィードに Javascript でアクセスすることができ、他ドメインのフィードも取得できちゃいます。

ためしにはてなアンテナのフィードを取得して表示してみました。

<script type="text/javascript" src="http://frog.raindrop.jp/scripts/xmlight.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="http://www.google.com/jsapi?key=YOUR_AJAX_API_KEY"></script>
<script type="text/javascript">
//<![CDATA[
// Google AJAX FEED API Version 1 を読み込む
google.load ("feeds", "1");
// AJAX Feed API のサンプルでは google.setOnLoadCallback でコールバックをバインドしてるけど
// jQuery と一緒に使用する場合は document.ready で実行したらよいと思う
$(function ()
{
    // RSS フィードの URI を指定して google.feeds.Feed を生成
    var feed = new google.feeds.Feed ("http://a.hatena.ne.jp/ba-raindrop/rss");
    // 読み込み件数を指定
    feed.setNumEntries (10);
    // フィード取得時に呼び出すコールバックを指定して load を呼び出す
    feed.load (function (result)
        {
            // 処理結果を判断する
            if (result.error)
                return;
            // 表示用の HTML の構築には自作の簡易 XML ビルダ/パーサを使用しています
            var list = jp.raindrop.frog.xmlight.create ("dl");
            // result.feed.entries を列挙
            for (var i = 0; i < result.feed.entries.length; i ++)
            {
                var entry = result.feed.entries[i];
                list.addChild ('dt').addText (entry.title);
                var memberList = list.addChild ('dd').addChild ('dl');
                // entries の各要素のメンバを列挙
                for (var member in entry)
                {
                    if (member === 'categories')
                        continue;    // categories は配列なので後で列挙
                    memberList.addChild ('dt').addText (member);
                    memberList.addChild ('dd').addText (entry[member]);
                }
                // categories を列挙
                memberList.addChild ('dt').addText ('categories');
                var categoryList = memberList.addChild ('dd').addChild ('ul');
                for (var j = 0; j < entry.categories.length; j ++)
                    categoryList.addChild ('li').addText (entry.categories [j]);
            }
            $(document.body).append (list.toString ());
        });
});
//]]>
</script>

サンプルを見る

September 27, 2010

連想配列の列挙

PHP
<?php
// foreach は便利
$array = array ("year" => 2010, "month" => 9, "day" => 27);
foreach ($array as $key => $value)
    echo "$key: $value\n";

// こうすると perl っぽい
while (list ($key, $value) = each ($array))
    echo "$key: $value\n";
?>
Perl
# たとえば、keys が返すキーの配列を foreach で列挙
%hash = ("year" => 2010, "month" => 9, "day" => 27);
foreach $key (keys %hash1)
    print "$key: $hash{$key}\n";

# 順番を確定したければキーをソートするといい
foreach $key (sort keys %hash1)
    print "$key: $hash{$key}\n";

# たとえばキーと値を each で列挙
while (($key, $value) = each (%hash1))
    print "$key: $value\n";

for と foreach

PHP の for
for ($i = 0; $i < 10; $i ++)
    echo "$i\n";
Perl の for
for ($i = 0; $i < 10; $i ++)
    print "$i\n";
Javascript の for
for (var i = 0; i < 10; i ++)
    document.writeln (i);
PHP の foreach
$array1 = array ("foo", "bar", "baz");
foreach ($array1 as $value)
    echo "$value\n";

$array2 = array ("year" => 2010, "month" => 9, "day" => 27);
foreach ($array1 as $key => $value)
    echo "$key: $value\n";
Perl の foreach
@array1 = ("foo", "bar", "baz");
foreach $value (@array1)
    print "$value\n";

%hash1 = ("year" => 2010, "month" => 9, "day" => 27);
foreach $key (keys %hash1)
    print "$key: $hash1{$key}\n";

# 実は for と foreach は同様に使える。インタプリタが文脈で判断するので。
@array2 = qw (apple peach banana);
for $value (@array2)
    print "$value\n";
Javascript の for ( in )
// for ( in ) を配列で使用した場合は添字を列挙
var array = ["foo", "bar", "baz"];
for (var index in array)
    document.writeln (array [index]);

// 連想配列で使用した場合はキーを列挙
var hash = {year: 2010, month: 9, day: 27};
for (var key in hash)
    document.writeln (key + ': ' + hash [key]);

September 22, 2010

最後の要素の後のカンマの件

識別子、文字列または数がありません。 で、ECMA でも新しい仕様では最後のカンマを許容することになってるらしいって結論になったけど、じゃあ JSON はどうよ ? と思って調べてみた。

object
{}
{ members }
members
pair
pair , members
pair
string : value
array
[]
[ elements ]
elements
value
value , elements
value
string
number
object
array
true
false
null

JSON では、最後の要素の後ろにカンマがあってはダメみたいです。配列でも同じ。
Standard ECMA-262 3rd Edition のサブセットってなってるから当然かな。

続きを読む...

September 21, 2010

識別子、文字列または数がありません。

Firefox や Chrome では正常に動作する Javascript が、IE では「識別子、文字列または数がありません。」というエラーになることが。さっぱり意味が分かんなくて調べてみたんですけど、結構あちこちのブログで取り上げられています。IE ではオブジェクトリテラルの最後のメンバの後ろにカンマがある場合に出るみたいです。

var person = {
    lastName: '鈴木',
    firstName: '一郎',
    age: 25,  // ←ここにカンマがあるとエラー
    };

C 言語などで、配列を中括弧で初期化する場合に最後の要素の後ろにもカンマを付けることが認められているので、ついついこのケースでもカンマを入れたくなってしまうんですが、意識して付けないようにした方がよさそうです。

ちなみに、WSH で実行するときも同じエラーになります。当然か。

ECMA の仕様ではどうなってるのかな…。

続きを読む...

September 16, 2010

関数内の this が参照するもの

あー、これはちょっと、今まで誤解してたかも。 this は実行時に評価されるんですね。
function Foo ()
{
    var _getx = function () { return this.x; };

    this.x = 'apple';
    this.getX = _getx;
    this.getBar = function () { return { x: 'banana', getX: _getx}; };
}

var foo = new Foo ();
alert (foo.getX ());    // 'apple'

var bar = foo.getBar ();
alert (bar.getX ());    // 'banana'
続きを読む...

September 15, 2010

簡易 XML ビルダ/パーサ

ブログのデザイン変更に伴い、jQuery で DOM を生成する部分が増えました。引数に渡す HTML ソースを作成するのに、文字列を + 演算子で連結していくと何が何やら…。ソースを見やすくしたくて、簡易的な XML ビルダ を作成してみました。"簡易" ってつけたら何を公開してもいいのか!という声が聞こえてきそうですが、でも実際このブログのあちこちでこのモジュールを活用しています。

一応、xml を渡すとパースもできますが、引用符のネストなんかにうまく対応できていません。誤りを検出するようには作ってないので、少々間違った xml を渡しても適当に解析してしまいます。なんちゃってです。

var jp;
if (!jp) jp = {};
if (!jp.raindrop) jp.raindrop = {};
if (!jp.raindrop.frog) jp.raindrop.frog = {};
jp.raindrop.frog.xmlight || (function () {

    function Element (name)
    {
        var _name = name;
        this.name = function () { return _name; };
        this.children = new Elements ();
        this.attributes = {};
        this.attr = function ()
            {
                if (!arguments.length)
                    return this.attributes;
                if (arguments.length == 1)
                    return this.attributes[arguments[0]];
                this.attributes[arguments[0]] = arguments[1];
                return this;
            }
        this.wrap = function (name) { var elem = new Element (name); elem.children.append (this); return elem; };
        this.toString = function ()
            {
                var s = '<' + _name;
                for (var key in this.attributes)
                    s += ' ' + key + '="' + this.attributes[key] + '"';
                var c = this.children.toString ();
                if (c.length)
                    s += '>' + c + '</' + _name + '>';
                else
                    s += ' />';
                return s;
            }
    };

    function TextNode (text) { this.toString = function () { return text; }; };

    function Elements ()
    {
        var _inner = [];
        this.add = function (name) { return this.append (new Element (name)); };
        this.append = function (elem) { _inner.push (elem); return elem; };
        this.addText = function (text) { return this.append (new TextNode (text)); };
        this.remove = function (elem)
            {
                var index = -1;
                for (var i = 0; i < _inner.length; i++)
                {
                    if (elem == _inner [i])
                    {
                        index = i;
                        break;
                    }
                }

                if (index < 0)
                    return;

                _inner.splice (index, 1);
            };
        this.insert = function (index, elem) { _inner.splice (index, 0, elem); return elem; };
        this.insertText = function (index, text) { return this.insert (index, new TextNode (text)); }
        this.item = function (index) { return _inner[index]; };
        this.wrap = function (name)
            {
                var elem = new Element (name);
                for (var i = 0; i < _inner.length; i ++)
                    elem.children.append (_inner[i]); 
                return elem;
            };
        this.length = function () { return _inner.length; };
        this.toString = function ()
            {
                var s = "";
                for (var i = 0; i < _inner.length; i ++)
                    s += _inner[i].toString ();
                return s;
            };
    }

    var _parse = function (str)
        {
            var elements = new Elements ();
            _parseElements (str, elements);
            return elements;
        };

    var _parseElements = function (str, elements)
        {
            var regex = /<((?:(\w+):)?(\w+))([^>]*)(?:\/|>(.*)<\/\1)>/g;
            var match = [];
            while (match = regex.exec (str))
            {
                var element = elements.add (match[1]);
                _parseAttributes (match[4], element);
                if (match.length > 5)
                    _parseElements (match[5], element.children);
            }
        };

    var _parseAttributes = function (str, element)
        {
            var regex = /((?:(\w+):)?(\w+))=(["'])(.*?)(\4)/g;
            var match = [];
            while (match = regex.exec (str))
            {
                element.attributes [match[1]] = match[5];
            }
        };

    jp.raindrop.frog.xmlight = {
        create: function (name) { return new Element (name); },
        parse: function (str) { var c = new Elements (); _parseElements (str, c); return c; }
        };
}());
続きを読む...

September 14, 2010

MySQL の比較演算時の型変換

MySQL で、別々の型同士の比較の際には REAL に変換される。
MySQL :: MySQL 5.1 リファレンスマニュアル :: 11.1.2 式評価でのタイプ変換

  • 一方か両方の引数が NULL の場合、比較の結果は、NULL-safe <=> 等値比較演算子以外は、NULL になります。NULL <=> NULL の場合、結果は true です。
  • 比較の演算の両方の引数がストリングの場合、それらはストリングとして比較されます。
  • 両方の引数が整数の場合、それらは整数として比較されます。
  • 16 進値が数字として比較されない場合は、バイナリ ストリングとして扱われます。
  • 引数の一方が TIMESTAMP または DATETIME カラムで、他の引数が定数の場合、定数は比較が行われる前に、タイムスタンプに変換されます。これは、ODBC により適合させるためです。これは IN() への引数には適用されませんのでご注意ください! 念のため、比較の際は常に完全な日付時刻、日付、または時刻ストリングを使用してください。
  • 他のすべてのケースでは、引数は浮動少数点 ( 実 ) 数として比較されます。