« 2007年01月 | メイン | 2007年03月 »

2007年02月 アーカイブ

2007年02月02日

スパムとの小さな戦い

このブログは私にとって二つ目のブログになる。前回のものも同じURLで公開していたのだが、いくつかの理由で更新が途絶えていた。そのうちの一つは、BlogEditorを開発する理由にもなった「ソースと通常の文章を同じエントリーに記述する煩わしさ」だ。
他の理由として、スパムコメントとスパムトラックバックの多さがあった。あまりの多さに、新規エントリーよりもスパム削除に時間がかかってしまうまでになっていた。本来ならMovable Typeのバージョンアップを行なって、スパムフィルタを導入すればよかったのだ。しかし、テンプレートをカスタマイズしまくったせいで、通常の方法ではバージョンアップができなくなっており、更新が途絶えた。
(これもBlogEditor開発の動機の一つ。テンプレートは変更しなくても。カスタマイズできるようにしたかった。)
それまでのものは諦めて、最新のバージョンで再度構築し直した今回、すこぶる快適だ。フィルタも順調に動作しているし、なぜもっと早くバージョンアップしなかったのかと後悔してしまう。

2007年02月03日

New BSD Licenseについて

ライブラリを公開した際、ライセンスを「New BSD License」とした事をfnyaさんに突っ込まれてしまった。修正版BSDライセンスというつもりでこうしたのだが、今現在はBSDライセンスというとほとんどの場合修正版BSD(2007/02/05修正:ただのBSDとなっていたのを"修正版BSD"に修正)を指すようだ。ややこしいので次回公開時にはMITにしようかと思う。

恥ずかしい間違い...自己申告

以前公開したライブラリで非常に恥ずかしい間違いを起こしていたのを皆さんお気づきだろうか。
文字バイト長取得をおこなうメソッド「getLengthByBite」。
「Bite」?

なるべく早く直します...。

iPhoneに既視感を覚えた理由

正直物欲を掻き立てられた。しかし、同時に既視感も覚えた。次のサイトの右上(2007/02/03現在)のmovie(QuickTime)を見て頂きたい。
携帯端末ではないが、GUIのレベルはiPhoneよりも数段上。指二本での拡大縮小は回転も伴う。アイディア次第でなんでもできそうな予感がする。まず思ったのが「欲しい」の一言。次に「手に入らないまでも一度操作してみたい」。何処かの美術館等で展示してもらえないかとも考えた。自分のパソコンにインストールできないかとも考えた。
(あれだけ巨大なmulti-touch displayの価格を想像すると、この考えは没。)
この何ともいえない感動を受け、日々「欲しい」と考えている時にiPhoneの発表である。「ああ、これが市場に出回るまで何年かかるだろう」と思っていたものが、年明けとともに出現した。たしかに驚きはあったが、先にこの映像を見たせいで、衝撃が薄れてしまったのが非常に残念だった。

2007年02月05日

Google Bookmarksの出力方法の変更

Googleブックマーク(Google Bookmarks)はRSSの取得が可能だ。これはURLにqueryを追加する事で出力方法を変更している。parameterを変更し、他の出力が可能かどうか試してみた。また、一覧表示の表示件数は15件となっている。この表示件数の変更が可能か試してみた。

出力方法の変更
RSSは、URLに「&output=rss」を追加する事で取得できる。では、XMLで取得は可能なのか。「&output=xml」と指定してみた。結果は可能であった。もちろん、RSSとは違うフォーマットである。csvはどうか。「&output=csv」と指定してみる。通常の一覧表示になってしまった。認識しない場合は、無視するようだ。jsonはどうであろうか。もしこれが可能であれば、応用範囲が広がる。更に何らかの変数に代入するような出力形態であれば、とんでもないことになる。
(これが可能であれば、他のサイトから直接読み込む事が可能になる。)
以下を試してみる。
「&output=json」
「&output=js」
「&output=javascript」
「&output=ecmascript」
「&output=es」
「&output=java」
「&output=ecma」
「&output=j」
「&output=e」
全て通常の一覧表示であった。結局見つかったのは、既知の「htmlによる一覧表示」、「rss出力」と新たに「xml出力」だった。
出力件数の変更
Google検索で表示件数の変更と表示開始位置の変更は次のようにして行なう。例えば、101件目から50件表示する場合、URLに「&num=50&start=100」と追加する事で可能だ。では、Googleブックマークではどうだろうか。結論から言えば可能であった。ただ、制限がある。表示件数は下限が5件、上限が1000件であった。これ以下、またはこれ以上の件数を指定すると、この範囲内に丸め込まれてしまう。
個人的に上限が1000件というのは痛い。それを遥かに超える件数を登録しているため、一度に取得が不可能という事だ。RSSをFirefoxのライブブックマークに登録しようにも、全件表示されないということだ。

2007年02月10日

選択範囲をYahoo!辞書で調べるBookmarklet Ver1.0.0

選択範囲を『Yahoo!辞書』で調べるブックマークレットを作成した。選択範囲抽出はクロスブラウザ処理されているのでアイディア次第で他の用途にも使用できるかも...。
/*
================================================================================
    Name        :   選択範囲をYahoo!辞書で調べるBookmarklet Ver1.0.0
    In          :   [none]      
    Out         :   [none]      
    Note        :   選択範囲の文字列をYahoo!辞書のすべての辞書で調べます。
--------------------------------------------------------------------------------
    Version     :   Ver1.0.0    |   2007/02/10  |   新規作成
--------------------------------------------------------------------------------
    License     :   MIT license
    URL         :   www.kanasansoft.com
================================================================================
*/

(
    function(){
        var
             w=window
            ,d=w.document
            ,s="";
            ;

        if(d.selection){
            s   =   d.selection.createRange().text
        }else if(d.getSelection){
            s   =   d.getSelection()
        }else if(w.getSelection){
            s   =   window.getSelection()
        }

        window.open("http://dic.yahoo.co.jp/dsearch?enc=UTF-8&p="+encodeURIComponent(s)+"+&stype=0&dtype=2","_blank")
    }
)
()

JavaScriptのfor文の特殊な記述の仕方

過去に掲載していた『特異なfor文の記述』を一部修正の上、再掲載する。
for文は次の様に定義されていると考えられがちである。
一般的なfor文に対する認識
for([カウンタの開始値(初期化)];[カウンタの終了値];[カウンタの増減値]){
    [実行文]
}
ここで一旦VBScriptの記述を見てる。
VBScriptのfor文(Step以降は省略可。省略時は[Step 1]と見なされる。)
For [カウンタの開始値(初期化)] To [カウンタの終了値] Step [カウンタの増減値]
    [実行文]
Next
0から9までループする処理をそれぞれの方法で記述してみる。
0から9までループ(JavaScript)
for(i=0;i<10;i++){
    [実行文]
}
0から9までループ(VBScript)
For i=0 To 9
    [実行文]
Next
JavaScriptはなぜ変数[i]を複数回記述しなければならないのか。次の様に記述させてもよさそうに思える。
JavaScript似の仮想言語によるfor文
for(i=0;10;1){              //もしくは[for(i=0;9;1){]
    [実行文]
}
実はfor文の定義は次のようになってる。
JavaScriptのfor文
for([ループ初回に実行される処理];[ループを抜ける為の条件(真偽値)];[ループ2回目以降に実行される処理]){
    [実行文]
}
処理を詳細に追ってみよう。
for文の処理を詳細に追う
for(i=0;i<10;i++){
    alert(i.toString(10));
}

i=0                             [ループ初回に実行される処理]
i<10                            [真偽値判定]                        (0<10=true)
alert(i.toString(10));          [実行文]                            ("0"を表示)
i++                             [ループ2回目以降に実行される処理]   (i=1)
i<10                            [真偽値判定]                        (1<10=true)
alert(i.toString(10));          [実行文]                            ("1"を表示)
i++                             [ループ2回目以降に実行される処理]   (i=2)
i<10                            [真偽値判定]                        (2<10=true)
alert(i.toString(10));          [実行文]                            ("2"を表示)



i++                             [ループ2回目以降に実行される処理]   (i=9)
i<10                            [真偽値判定]                        (9<10=true)
alert(i.toString(10));          [実行文]                            ("9"を表示)
i++                             [ループ2回目以降に実行される処理]   (i=10)
i<10                            [真偽値判定]                        (10<10=false)
                                [ループを抜ける]
この様な動作になっている為、次の様な変わった記述も可能なのである。
特異なfor文の例
for(var str="";str.length<50;str+=prompt("入力して下さい。\nstr=\""+str+"\"","")){}
これを一般的な記述方法に書き換えてみよう。
一般的な記述に書き換えた例
var str="";
while(str.length<50){
    str+=prompt("入力して下さい。\nstr=\""+str+"\"","");
}
これらの特異なfor文は推奨しない。ごく一般的なPGはfor文を見ると[カウンタ付のループ]と判断する。[カウンタ付のループ]の定義部分で文字列の操作が行なわれているとは夢にも思わないだろう。

2007年02月12日

レベル高めの個人作成ピタゴラスイッチ(ピタゴラ装置)

YouTubeで公開されている個人作成のピタゴラ装置のなかでは比較的レベルが高いものを見つけた。他の公開されているものは妙に短かったり、リズムがあまり良くないが、これはリズムやその長さ等が本物に近く感心させられる。一部、既製品を使用しているように見えるが、それを差し引いても良くできているのではないかと思う。
※ピタゴラ装置とは、NHKの教育番組の『ピタゴラスイッチ』内の人気コーナーの名前で、Rube Goldberg machine(ルーブ・ゴールドバーグ・マシン)の一種。

2007年02月23日

神社とロングテールとGoogle Earth

昨日(02/22)の朝日新聞朝刊の文化総合のページに『神社分類』という特集があった。なんでも、国学院大学の岡田莊司教授が、神社を祭神をもとに分類しまとめたらしい。約79,000(単位不明)もの神社を調査し、その所在地まで絡めてまとめたのは前例がないとの事。詳細は記事を見てもらうとして、筆者が注目したのは次の点。『信仰別の神社数で上位4位までで全体の1/4を、10位までで約半分を占めている』という事。信仰別の神社数という表には25位26(25位同数)の信仰名とその数が載っている。トップは『八幡』の7,817で全体の約1割。気になったので上位26の神社数を合計してみたら、その数40,404。総神社数を79,000丁度とすると、27位以下の神社数は38,596となる。25位が277なので27位以下は最大でも276。27位からワースト2位まで同数と仮定すれば(最下位は余)、理屈上最少の信仰数が判明する。
38,596/276=139(余232)
上位26までは既に出ているので理屈上の最少信仰数は次の通り。
26+139+1=166
つまり、記事上から得られる情報から、ロングテールが短い場合を算出しても、上位1/6(=26/166)で半数以上(=40,404/79,000)を占めるという事。ちなみにロングテールが最も長いのは、27位から最下位までが全て1で同数の場合の、信仰数38,622(=26+38,596)。詳細なデータがあれば、パレードの法則(80:20)に近い比率が出てきそうだ。
神社の分布についても記事中に色々書いてあったが、これまでの歴史や文化の影響を大きく受けているようだ。ただ、大まかな分布図があれば面白かったのにと思ってしまう。いっそのことKML(Google Earthの地物フォーマット)にでもしてもらえないだろうか。神社数が79,000と多く見えるだろうが、所在地は当然分かっているはずだろうから、経緯度には簡単に変換できるし(所在地+神社名なら尚正確)、プログラムであっという間だと思うのだがどうだろう。

2007年02月27日

文字列の操作を行なうJavaScript Libraryにバックスラッシュエスケープ用メソッドを追加

文字列を操作するJavaScriptのLibraryのバージョンアップ。メソッド名のスペルミスの修正と、新たなメソッドの追加を行なった。新しいメソッドは、文字列をJavaScriptにエンコードする際、特定の文字列にターゲットを絞ったエンコードではなく、全ての文字列をunicode文字へバックスラッシュエスケープしている。
/*
================================================================================
    Name        :   StringUtility
    In          :   [none]      
    Out         :   [none]      
    Note        :   文字列用ユーティリティ群
--------------------------------------------------------------------------------
    Version     :   Ver1.0.0    |   2006/01/16  |   新規作成
                :   Ver1.0.1    |   2006/12/19  |   シングルクォーテーションに対する処理を追加
                :   Ver1.0.2    |   2007/02/15  |   スペルミス修正[getLengthByBite]->[getLengthByByte]
                :   Ver1.1.0    |   2007/02/17  |   [StringUtility.Encode.JavaScriptComplete]を追加
--------------------------------------------------------------------------------
    License     :   MIT license
    URL         :   www.kanasansoft.com
================================================================================
*/

/*--------------------------------------------------------------------------------
    コンストラクタ
--------------------------------------------------------------------------------*/
function StringUtility(){
}

StringUtility.Encode
=   function(){
}

StringUtility.Decode
=   function(){
}

StringUtility.Convert
=   function(){
}

/*--------------------------------------------------------------------------------
    HTMLエンコードを行なう
--------------------------------------------------------------------------------*/
StringUtility.Encode.HTML
=   function(str){
    return          str                                         .
                    replace(    /&/ig   ,   "&amp;"     )       .
                    replace(    /</ig   ,   "&lt;"      )       .
                    replace(    />/ig   ,   "&gt;"      )       .
                    replace(    /'/ig   ,   "&apos;"    )       .
                    replace(    /"/ig   ,   "&quot;"    )       .
                    replace(    / /ig   ,   "&nbsp;"    )       ;
}

/*--------------------------------------------------------------------------------
    HTMLデコードを行なう
--------------------------------------------------------------------------------*/
StringUtility.Decode.HTML
=   function(str){
    return          str                                         .
                    replace(    /&nbsp;/ig  ,   " "     )       .
                    replace(    /&quot;/ig  ,   "\""    )       .
                    replace(    /&apos;/ig  ,   "'"     )       .
                    replace(    /&gt;/ig    ,   ">"     )       .
                    replace(    /&lt;/ig    ,   "<"     )       .
                    replace(    /&amp;/ig   ,   "&"     )       ;
}

/*--------------------------------------------------------------------------------
    HTMLエンコードを行なう(Bookmarklet用)
--------------------------------------------------------------------------------*/
StringUtility.Encode.HTMLforBookmarklet
=   function(str){
    return          str                                         .
                    replace(    /&/ig   ,   "&amp;"     )       .
                    replace(    /</ig   ,   "&lt;"      )       .
                    replace(    />/ig   ,   "&gt;"      )       .
                    replace(    /'/ig   ,   "&apos;"    )       .
                    replace(    /"/ig   ,   "&quot;"    )       ;
}

/*--------------------------------------------------------------------------------
    JavaScriptエンコードを行なう
--------------------------------------------------------------------------------*/
StringUtility.Encode.JavaScript
=   function(str){
    return          str                                         .
                    replace(    /\\/ig  ,   "\\\\"      )       .
/*                  replace(    /\b/ig  ,   "\\b"       )       .*/
                    replace(    /\f/ig  ,   "\\f"       )       .
                    replace(    /\n/ig  ,   "\\n"       )       .
                    replace(    /\r/ig  ,   "\\r"       )       .
                    replace(    /\t/ig  ,   "\\t"       )       .
                    replace(    /'/ig   ,   "\\'"       )       .
                    replace(    /"/ig   ,   "\\\""      )       ;
}

/*--------------------------------------------------------------------------------
    JavaScriptエンコードを行なう
--------------------------------------------------------------------------------*/
StringUtility.Encode.JavaScriptComplete
=   function(str){
    var rtn =   "";
    for(var i=0;i<str.length;i++){
        rtn +=  "\\u"+(("0000"+(str.charCodeAt(i).toString(16))).slice(-4));
    }
    return rtn;
}

/*--------------------------------------------------------------------------------
    tabをspaceに変換する
--------------------------------------------------------------------------------*/
StringUtility.Convert.TabToSpace
=   function(str,tabNumber){

    var linesRN                         =   str.split("\r\n");
    for(var lineCntRN=0;lineCntRN<linesRN.length;lineCntRN++){
        var linesN                      =   linesRN[lineCntRN].split("\n");
        for(var lineCntN=0;lineCntN<linesN.length;lineCntN++){
            var linesR                  =   linesN[lineCntN].split("\r");
            for(var lineCntR=0;lineCntR<linesR.length;lineCntR++){
                var wordsT              =   linesR[lineCntR].split("\t");
                for(var wordsCntT=0;wordsCntT<wordsT.length-1;wordsCntT++){
                    wordsT[wordsCntT]   +=  StringUtility.getRepeatString(
                                                " "                                                                     ,
                                                tabNumber-(StringUtility.getLengthByByte(wordsT[wordsCntT])%tabNumber)  )
                }
                linesR[lineCntR]        =   wordsT.join("");
            }
            linesN[lineCntN]            =   linesR.join("\r");
        }
        linesRN[lineCntRN]              =   linesN.join("\n");
    }
    var rtn                             =   linesRN.join("\r\n");

    return rtn;

}

/*--------------------------------------------------------------------------------
    改行コードを"<br />"に変換する
--------------------------------------------------------------------------------*/
StringUtility.Convert.NewLineCodeToTag
=   function(str){
    return          str                                             .
                    replace(    /\r\n/ig    ,   "<br />"    )       .
                    replace(    /\r/ig      ,   "<br />"    )       .
                    replace(    /\n/ig      ,   "<br />"    )       ;
}

/*--------------------------------------------------------------------------------
    文字バイト長取得
--------------------------------------------------------------------------------*/
StringUtility.getLengthByByte
=   function(str){
    var count   =   0;
    for(var i=0;i<str.length;i++){
        var code    =   str.charCodeAt(i);
        while(code!=0){
            count++;
            code>>>=8;
        }
    }
    return count;
}

/*--------------------------------------------------------------------------------
    繰り返し文字取得
--------------------------------------------------------------------------------*/
StringUtility.getRepeatString
=   function(str,num){
    var rtn =   "";
    for(var i=0;i<num;i++){
        rtn +=  str;
    }
    return rtn;
}

ObjectをJSONへ変換するJavaScript Library

2009/11/24 追記
このJSONの変換処理は時代遅れとなっています。
最新の動向を知りたい方は、以下のキーワードで検索する事をお勧めします。
「JSON.stringify」「JSON.parse」「json2.js」
追記終わり
JSONのエンコード処理時、バックスラッシュエスケープのユニコード文字への変換を行うメソッドを追加した。そもそもJSON変換時、文字列は一部の該当するもののみの変換で良いと思っていたが、どうも全ての変換が必要のようだ。しかし、一部の変換でもJavaScriptは受け付ける事が可能であり、全てをユニコード文字へ変換するとデータ量が増えてしまうデメリットもあるため、古いメソッドは残すことにする。
/*
================================================================================
    Name        :   JSON
    In          :   [none]      
    Out         :   [none]      
    Note        :   JSONユーティリティ群
--------------------------------------------------------------------------------
    Version     :   Ver1.0.0    |   2006/12/04  |   新規作成
                :   Ver1.1.0    |   2007/02/17  |   [JSON.EncodeComplete]を追加
--------------------------------------------------------------------------------
    License     :   MIT license
    URL         :   www.kanasansoft.com
================================================================================
*/

/*--------------------------------------------------------------------------------
    コンストラクタ
--------------------------------------------------------------------------------*/
function JSON(){
}

/*--------------------------------------------------------------------------------
    JSONエンコードを行なう
--------------------------------------------------------------------------------*/
JSON.Encode
=   function(obj){

    var rtn;

    if(obj==null){

        rtn = "null";

    }else{

        switch(obj.constructor){

            case Boolean:
                rtn = obj?"true":"false";
                break;

            case Number:
                rtn = isNaN(obj)||!isFinite(obj)?"null":obj.toString(10);
                break;

            case String:
                rtn = "\""+StringUtility.Encode.JavaScript(obj)+"\"";
                break;

            case Array:
                var buf = [];
                for(var i=0;i<obj.length;i++){
                    //再帰呼出
                    buf.push(arguments.callee(obj[i]));
                }
                rtn = "["+buf.join(",")+"]";
                break;

            case Object:
                var buf = [];
                for(var key in obj){
                    //Object汚染回避判定有
                    if(obj.hasOwnProperty(key)){
                        //再帰呼出
                        buf[buf.length] = arguments.callee(key)+":"+arguments.callee(obj[key]);
                    }
                }
                rtn = "{"+buf.join(",")+"}";
                break;

            default:
                rtn = "null";
                break;

        }

    }

    return rtn;
}

/*--------------------------------------------------------------------------------
    JSONエンコードを行なう
--------------------------------------------------------------------------------*/
JSON.EncodeComplete
=   function(obj){

    var rtn;

    if(obj==null){

        rtn = "null";

    }else{

        switch(obj.constructor){

            case Boolean:
                rtn = obj?"true":"false";
                break;

            case Number:
                rtn = isNaN(obj)||!isFinite(obj)?"null":obj.toString(10);
                break;

            case String:
                rtn = "\""+StringUtility.Encode.JavaScriptComplete(obj)+"\"";
                break;

            case Array:
                var buf = [];
                for(var i=0;i<obj.length;i++){
                    //再帰呼出
                    buf.push(arguments.callee(obj[i]));
                }
                rtn = "["+buf.join(",")+"]";
                break;

            case Object:
                var buf = [];
                for(var key in obj){
                    //Object汚染回避判定有
                    if(obj.hasOwnProperty(key)){
                        //再帰呼出
                        buf[buf.length] = arguments.callee(key)+":"+arguments.callee(obj[key]);
                    }
                }
                rtn = "{"+buf.join(",")+"}";
                break;

            default:
                rtn = "null";
                break;

        }

    }

    return rtn;
}

/*--------------------------------------------------------------------------------
    JSONデコードを行なう
--------------------------------------------------------------------------------*/
JSON.Decode
=   function(str){

    var rtn;

    eval("rtn="+str);

    return rtn;
}
Google

タグ クラウド