webAi.WebSrch - ソースコード

説明

Web AI」は、クロノス・クラウンの柳井政和が開発しているJavaScirptのライブラリです。「Web AI」を使うと、Web上からデータを取得して構築するWebページを、とても簡単に構築することができます。

「Web AI」は、Webからの検索結果やフィードの取得、短縮URLへのURLの変換、日本語文章からのキーワードや文章抽出、日本語文章のマルコフ連鎖、クエリーの管理などの機能を備えています。

このページでは、この「Web AI」のファイルの1つである「crocro.webAi.WebSrch.js」のソースコードを掲載します。

「crocro.webAi.WebSrch.js」

「crocro.webAi.WebSrch.js」には、通信系の機能がまとめられています。このファイルには「crocro.webAi.WebSrch」オブジェクトが収録されています。

「WebSrch」オブジェクトは、検索処理やRSSフィードの取得、短縮URLの取得などの非同期命令をメソッド・チェーン化します。そして非同期命令を、上から順番に並べて、見やすく書けるようにします。

この「WebSrch」オブジェクトの検索処理は、「Google Ajax API」を内部的に利用しています。

使い方は、「Web AI」の各サンプルを参考にしてください。

ソースコード

以下、「crocro.webAi.WebSrch.js」のソースコードです。

/*  Web AI <http://crocro.com/write/web_ai/wiki.cgi>
    is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
    in a Japanese translation <http://sourceforge.jp/projects/opensource/wiki/licenses%2FMIT_license>
    Copyright (c) 2010 Masakazu Yanai / (c) 2010 Cronus Crown <webmaster@crocro.com>
*/

    // crocro.webAiの初期化
    if (! crocro) var crocro = {};
    if (! crocro.webAi) crocro.webAi = {};

    /**
     *  @variable   crocro.webAi.WebSrch()
     *  @title  検索用オブジェクト
     *  @description
     *
     *      検索用オブジェクト。
     *      主に、「Google AJAX Search API」を使いやすくすることを目的としている。
     *      メソッド・チェーンで、初期化や検索、その結果の処理などを記述できる。
     *      newで初期化してから利用する。
     *
     *      「reset」メソッドで予約をクリアして、
     *      各種メソッドで予約の登録を行った後、
     *      「start」メソッドで、予約した処理を順番に実行していく。
     *
     *      「start」を呼び出すまでは実行は行われないので、
     *      ユーザーの操作をいくつか受け付けた後に、
     *      実行ボタンで処理を開始するようなことも可能。
     *
     *      例)<br>
     *      var g = new crocro.webAi.WebSrch();<br>
     *      g<br>
     *      .reset()        // 予約のクリア<br>
     *      .hoge()         // 命令の追加<br>
     *      .hoge()         // 命令の追加<br>
     *      .hoge()         // 命令の追加<br>
     *      .start();       // 追加した命令を実行
     *
     *      実際の用法は、サンプルコードを参照。
     */
    crocro.webAi.WebSrch = function() {
        // 内部パラメータ
        /**
         *  @variable   WebSrch.srchPrms
         *  @title  検索オブジェクト
         *  @description
         *      「web: {obj: null, init: function() {return new google.search.WebSearch();}}」
         *      の形式の配列。この場合、「WebSrch.init」メソッドで「web」を指定すると、
         *      「web.obj」に「web.init()」の戻り値が登録される。
         *
         *      デフォルトで「web」「img」「nws」「blg」が設定されている。
         *      配列にオブジェクトを追加することで、他の検索も利用することができる。
         *
         *      詳しくはソースコードを参照。
         */
        this.srchPrms = {
             web: {obj: null, init: function() {return new google.search.WebSearch();}}
            ,img: {obj: null, init: function() {return new google.search.ImageSearch();}}
            ,nws: {obj: null, init: function() {return new google.search.NewsSearch();}}
            ,blg: {obj: null, init: function() {return new google.search.BlogSearch();}}
        };

        // 自分自身
        var self = this;

        /**
         *  @variable   WebSrch.isExec
         *  @title  実行中か否か
         *  @description
         *      命令が実行中の間は「true」が格納されている。
         *      二重起動防止などの判定用に利用する。
         *
         *      詳しくはサンプルのソースコードを参照。
         */
        this.isExec = false;

        // インターバル
        /**
         *  @variable   WebSrch.intrvl
         *  @title  インターバル
         *  @description
         *      処理の実行インターバル。
         *      数値か、数値を戻す関数を設定する。
         *
         *      通信の負荷を軽減するために、1秒に一度実行を行うなどの用途で利用する。
         *
         *      デフォルトは「0」。
         */
        this.intrvl = 0;    // 処理の実行インターバル(数値か、数値を戻す関数)

        // 未初期化時の自動初期化処理(無限ループ対策)
        var autoJSInit = false;         // 外部JavaScript
        var autoSrcherInit = false;     // Searcherオブジェクト

        // Google AJAX APIのURL
        var urlGglJSApi = "http://www.google.com/jsapi";

        // jQueryのURL
        var urlJQuery = "http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js";

        // Google JSAPIのURL
        var urlGglJSApi = "http://www.google.com/jsapi";

        /*
         *--------------------------------------------------
         */

        /**
         *  @variable   WebSrch.ready(fnc)
         *  @title  google検索オブジェクト・ロード後のコールバック
         *  @description
         *
         *      「google.setOnLoadCallback」と等価。短縮表記用。
         *
         *      HTMLページ読み込み直後に処理を行う際は、
         *      この関数の引数に、処理を行う関数をセットして実行させる。
         *
         *      また、HTMLページ読み込み直後には、「init」だけ行っておき、
         *      その後の検索処理は、ボタンクリックなどのイベント発生時に行わせてもよい。
         *
         *  @param  fnc     検索オブジェクト・ロード後に実行させる関数。
         *  @return なし(メソッド・チェーン不可)。
         */
        this.ready = function(fnc) {
            // googleオブジェクトがなければ読み込む
            if (! ("google" in window)      // Chromeではgoogleオブジェクトが名前だけ存在している
             || ! google.setOnLoadCallback  // ので「google.setOnLoadCallback」の有無を確認する。
            ) {
                loadGgl(fnc, null);
                return;
            }

            // ロード時実行を開始
            google.setOnLoadCallback(fnc);
        };

        /**
         *  @variable   WebSrch.loadGgl(fnc, arg)
         *  @title  googleローダーの読み込み
         *  @description
         *
         *      googleローダーがまだ初期化されていなければ、googleローダーを読み込む。
         *
         *  @return なし。
         */
        function loadGgl(fnc, arg) {
            if (! document.readyState
                || document.readyState === "loaded"
                || document.readyState === "complete"
            ) {
                // googleの読み込みを実行
                loadJS(urlGglJSApi, fnc, arg);  // 実行後に呼び出し元に戻す
            } else {
                setTimeout(function(){
                    loadGgl(fnc, arg);      // JSのロード
                }, 10);
            }
        }

        /*
         *--------------------------------------------------
        */

        // 命令用の変数
        var cmnds = [];     // 命令を格納する配列
        var execCnt = 0;    // 命令の現在実行位置を保持する変数

        // 挿入モードのオン/オフ
        var isInsrtOn = false;  // 挿入モードがオンか?
        var insrtPos  = 0;      // 挿入モード時の挿入位置

        /**
         *  @variable   WebSrch.reset()
         *  @title  命令のリセット
         *  @description
         *
         *      登録していた命令を全て削除する。
         *
         *  @return this(メソッドチェーン可能)。
         */
        this.reset = function() {
            cmnds = [];
            return this;
        };

        /**
         *  @variable   WebSrch.start()
         *  @title  命令の開始
         *  @description
         *
         *      登録していた命令を全て実行する。
         *      命令の開始は、非同期で開始される。
         *      メソッド・チェーンの末尾に記述するメソッド。
         *
         *  @return なし(メソッド・チェーン不可)。
         */
        this.start = function() {
            initExecVar();          // 実行設定の初期化
            self.isExec = true;     // 実行中(googleオブジェクト読み込み時にthisの
                                    // 対象が変わるのでselfで指定)

            // googleオブジェクトがなければ読み込む
            if (! ("google" in window)      // Chromeではgoogleオブジェクトが名前だけ存在している
             || ! google.setOnLoadCallback  // ので「google.setOnLoadCallback」の有無を確認する。
            ) {
                loadGgl(self.start, null);
                return;
            }

            // 非同期で実行開始
            setTimeout(nextExec, 1);
        };

        /**
         *  @access private
         *  @variable   WebSrch.initExecVar()
         *  @title  実行設定の初期化
         *  @description
         *
         *      実行用変数の初期化
         *
         *  @return なし。
         */
        function initExecVar() {
            self.isExec = false;    // 実行中をfalseに
            execCnt = 0;            // 命令の現在実行位置
            insrtPos = 0;           // 挿入モード時の挿入位置
            self.loopCnt = -1;      // ループのカウント
        }

        /**
         *  @access private
         *  @variable   WebSrch.nextExec()
         *  @title  命令の逐次実行処理
         *  @description
         *
         *      登録していた命令を1つずつ実行する。
         *      内部処理用のメソッド。外部からの呼び出しは行わない。
         *
         *  @return なし。
         */
        function nextExec() {
            // 終了判定
            if (execCnt >= cmnds.length || self.isExec == false) {
                initExecVar();      // 実行設定の初期化
                return;             // 実行終了
            }

            // 変数の初期化
            var cmnd = cmnds[execCnt];
            eachCall(); // 毎回処理
            execCnt ++;         // カウント処理

            // 実行処理
            if (cmnd.fnc && cmnd.prm) {
                cmnd.fnc(cmnd.prm);     // 命令を実行
            }
        }

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.pushCmnds(arg)
         *  @title  命令の登録
         *  @description
         *
         *      命令を登録する。通常時は、命令は末尾に追加していく。
         *      挿入モードがオンの場合は、現在実行位置の次の位置に、次々と追加していく。
         *
         *  @param  arg     引数となるオブジェクト。
         *  @return 取得した値。
         */
        this.pushCmnds = function(arg) {
            if (! isInsrtOn) {
                // 通常時
                cmnds.push(arg);
            } else {
                // 挿入モード時
                if (insrtPos >= cmnds.length) {
                    // 実行位置が末尾
                    cmnds.push(arg);
                } else {
                    // 実行位置が途中
                    var pos = insrtPos > 0 ? insrtPos : 1;
                    var arr0 = cmnds.slice(0, pos);
                    var arr1 = cmnds.slice(pos);
                    arr0.push(arg);
                    cmnds = arr0.concat(arr1);
                    insrtPos ++;
                }
            }
        }

        /**
         *  @access private
         *  @variable   WebSrch.getPrm(arg)
         *  @title  値の取得
         *  @description
         *
         *      引数などに使うオブジェクトから値を取得する。
         *      文字列や数値なら、その値をそのまま返し、関数なら戻り値を返す。
         *
         *  @param  obj     値を取得するオブジェクト。
         *  @return 取得した値。
         */
        function getPrm(obj) {
            if (obj) {
                if (obj instanceof Function) {
                    return obj();
                } else {
                    return obj;
                }
            }
            return null;
        }

        /**
         *  @access private
         *  @variable   WebSrch.getIntrvl()
         *  @title  インターバルの取得
         *  @description
         *
         *      インターバル用のオブジェクトから数値を取得する。
         *      文字列や数値なら、数値を戻し、関数なら戻り値を数値化して戻す。
         *
         *  @return インターバルの取得。
         */
        function getIntrvl() {
            var intrvl = 0;
            if (self.intrvl) {
                if (self.intrvl instanceof Function) {
                    intrvl = self.intrvl();
                } else {
                    intrvl = self.intrvl;
                }
            }
            if (! intrvl) intrvl = 0;
            return intrvl * 1;
        }

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.insrtOn()
         *  @title  挿入モードを有効に
         *  @description
         *
         *      挿入モードを有効にする。これ以降、挿入モードを無効にするまで、
         *      現在実行位置の直後に、次々と命令を追加していく。
         *
         *      ※この命令は、呼び出された瞬間に効果を発揮する。
         *       命令の登録ではなく、単なるモードの変更である。
         *
         *  @return this(メソッドチェーン可能)。
         */
        this.insrtOn = function() {
            insrtPos = execCnt;
            isInsrtOn = true;
            return this;
        }

        /**
         *  @variable   WebSrch.insrtOff()
         *  @title  挿入モードを無効に
         *  @description
         *
         *      挿入モードを無効にする。これ以降、命令を追加すると、末尾に追加されていく。
         *
         *      ※この命令は、呼び出された瞬間に効果を発揮する。
         *       命令の登録ではなく、単なるモードの変更である。
         *
         *  @return this(メソッドチェーン可能)。
         */
        this.insrtOff = function() {
            isInsrtOn = false;
            return this;
        }

        /*
         *--------------------------------------------------
        */

        // 毎回処理関数
        var eachCall = function(){};

        /**
         *  @variable   WebSrch.setEachCall(arg)
         *  @title  毎回処理追加
         *  @description
         *
         *      ステップごとに呼び出される処理を追加する。
         *
         *  @param  arg     関数。
         *  @return this(メソッドチェーン可能)。
         */
        this.setEachCall = function(arg) {
            this.pushCmnds({prm : arg, fnc : doSetEachCall});
            return this;
        }

        /**
         *  @access private
         *  @variable   WebSrch.doSetEachCall(arg)
         *  @title  毎回処理追加 実行
         *  @description
         *
         *      ステップごとに呼び出される処理を追加する。
         *
         *  @param  arg     関数。
         *  @return this(メソッドチェーン可能)。
         */
        function doSetEachCall(arg) {
            eachCall = arg;
            nextExec();     // 次の命令を実行
        }

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.brand(arg)
         *  @title  googleのブランド表示
         *  @description
         *
         *      ブランド表示を行う、表示先のエレメントIDを引数として指定する。
         *
         *  @param  arg     エレメントのID。
         *  @return this(メソッドチェーン可能)。
         */
        this.brand = function(arg) {
            this.pushCmnds({prm : arg, fnc : doBrand});
            return this;
        };

        /**
         *  @access private
         *  @variable   WebSrch.doBrand(arg)
         *  @title  googleのブランド表示 実行
         *  @description
         *
         *      登録した「brand」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return なし。
         */
        function doBrand(arg) {
            // google.searchの初期化確認
            if (! google.search) {
                // google.searchオブジェクトが不在
                loadGglJS("search", "1", doBrand, arg);
                return;
            }

            // ブランド表示
            var eleBrnd = document.getElementById(arg);
            google.search.Search.getBranding(eleBrnd);
            nextExec();     // 次の命令を実行
        };

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.init(arg)
         *  @title  初期化処理
         *  @description
         *
         *      Google検索オブジェクトの初期化処理を行う。
         *
         *  @param  arg.type    種類を指定(web, img, nws)
         *  @param  arg.opt     検索オブジェクトを受け取る関数を指定。
         *                      この関数の中で、Google検索オブジェクトの追加の設定を行う。
         *  @return this(メソッドチェーン可能)。
         */
        this.init = function(arg) {
            this.pushCmnds({prm : arg, fnc : doInit});
            return this;
        };

        /**
         *  @access private
         *  @variable   WebSrch.doInit(arg)
         *  @title  初期化処理 実行
         *  @description
         *
         *      登録した「init」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return なし。
         */
        function doInit(arg) {
            // google.searchの初期化確認
            if (! google.search) {
                // google.searchオブジェクトが不在
                loadGglJS("search", "1", doInit, arg);
                return;
            }

            // 初期化処理
            if (arg && arg.type) {
                var obj = null;
                for (var key in self.srchPrms) {
                    if (arg.type == key) {
                        obj = self.srchPrms[key].obj = self.srchPrms[key].init();
                        break;
                    }
                }
                if (obj && "opt" in arg && arg.opt instanceof Function) {
                    arg.opt(obj);   // 追加設定
                }
            }
            nextExec();     // 次の命令を実行
        };

        /*
         *--------------------------------------------------
        */

        /**
         *  @access private
         *  @variable   WebSrch.loadGglJS(typ, ver, fnc, arg)
         *  @title  Googleオブジェクトのロード
         *  @description
         *
         *      Googleオブジェクトが初期化されていない場合に読み込む処理。
         *
         *  @param  typ     読み込むオブジェクト。
         *  @param  ver     バージョン。
         *  @param  fnc     追加実行する関数。
         *  @param  arg     追加実行する関数の引数。
         *  @return なし。
         */
        function loadGglJS(typ, ver, fnc, arg) {
            if (autoJSInit) {
                autoJSInit = false; // 自動初期化終了
                alert("err : can't load " + typ + " " + ver + ".");
                self.cmndsBreak();  // 命令処理終了
                nextExec();         // 次の命令を実行
                return;
            }
            autoJSInit = true;      // 自動初期化開始
            google.load(typ,  ver, {callback: function() {
                autoJSInit = false; // 自動初期化終了
                fnc(arg);           // 再度関数を実行
            }});
            return;
        }

        /**
         *  @access private
         *  @variable   WebSrch.loadJS(typ, ver, fnc, arg)
         *  @title  JSのロード
         *  @description
         *
         *      外部JavaScriptを読み込む処理。
         *      外部JavaScriptのオブジェクトが初期化されていない場合に利用する。
         *
         *  @param  url     読み込む外部JavaScriptのURL。
         *  @param  fnc     追加実行する関数。
         *  @param  arg     追加実行する関数の引数。
         *  @return なし。
         */
        function loadJS(url, fnc, arg) {
            if (autoJSInit) {
                autoJSInit = false; // 自動初期化終了
                alert("err : can't load " + url + ".");
                self.cmndsBreak();  // 命令処理終了
                nextExec();         // 次の命令を実行
                return;
            }
            autoJSInit = true;      // 自動初期化開始

            // scriptタグの追加
            var head = document.getElementsByTagName("head")[0]
                    || document.documentElement;
            var script = document.createElement("script");
            script.charset = "UTF-8";
            script.src = url;

            var isDone = false;
            script.onload = script.onreadystatechange = function() {
                // 読み込み後処理
                if (! isDone
                 && (! this.readyState
                    || this.readyState === "loaded"
                    || this.readyState === "complete"
                    )
                ) {
                    isDone = true;

                    // 実行
                    autoJSInit = false; // 自動初期化終了
                    fnc(arg);           // 再度関数を実行

                    // IEメモリー・リーク対策
                    script.onload = script.onreadystatechange = null;
                    if (head && script.parentNode) {
                        head.removeChild(script);
                    }
                }
            };

            // IE6バグ対策付きでscriptを追加
            head.insertBefore(script, head.firstChild);
        }

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.add(arg)
         *  @title  追加処理
         *  @description
         *
         *      引数として、追加実行する関数を指定。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return this(メソッドチェーン可能)。
         */
        this.add = function(arg) {
            this.pushCmnds({prm : arg, fnc : doAdd});
            return this;
        }

        /**
         *  @access private
         *  @variable   WebSrch.doAdd(arg)
         *  @title  追加処理 実行
         *  @description
         *
         *      登録した「add」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return なし。
         */
        function doAdd(arg) {
            if (arg) arg(); // 関数を実行
            nextExec();     // 次の命令を実行
        }

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.end(arg)
         *  @title  終了処理
         *  @description
         *
         *      命令の実行処理を終了する。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return this(メソッドチェーン可能)。
         */
        this.end= function(arg) {
            this.pushCmnds({prm : arg, fnc : doEnd});
            return this;
        }

        /**
         *  @access private
         *  @variable   WebSrch.doEnd(arg)
         *  @title  追加処理 実行
         *  @description
         *
         *      登録した「add」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return なし。
         */
        function doEnd(arg) {
            if (arg) arg();         // 関数を実行
            self.isExec = false;    // 実行中をfalseに
            nextExec();             // 次の命令を実行
        }

        /*
         *--------------------------------------------------
        */

        // コールバック・ループ用の変数
        var nowArg;         // 一時的な検索引数の格納

        /**
         *  @variable   WebSrch.loopCnt
         *  @title  ループのカウント
         *  @description
         *      検索などのループ指定を行える処理の場合に、現在のループ回数を取得するための変数。
         *
         *      詳しくはサンプルのソースコードを参照。
         */
        this.loopCnt = -1;  // ループのカウント

        /**
         *  @variable   WebSrch.addCallback(arg)
         *  @title  追加処理 コールバック
         *  @description
         *
         *      引数として、コールバック付きの追加実行する関数を指定。
         *      このメソッド内で行うコールバック処理が終わったタイミングで、
         *      「endCallback」を呼び出す。そうすれば、次の命令に移動して
         *      実行が継続される。
         *
         *  @param  arg.init    ループ実行前の処理を関数で指定。
         *  @param  arg.loop    ループ回数の数字か関数を指定。
         *  @param  arg.exec    処理を行う関数を指定。
         *  @return this(メソッドチェーン可能)。
         */
        this.addCallback = function(arg) {
            this.pushCmnds({prm : arg, fnc : doAddCallback});
            return this;
        }

        /**
         *  @access private
         *  @variable   WebSrch.doAddCallback(arg)
         *  @title  追加処理 コールバック 実行
         *  @description
         *
         *      登録した「addCallback」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return なし。
         */
        function doAddCallback(arg) {
            // エラー対策
            if (! arg) {loopUnable(); return}   // ループ無効

            // 値の展開
            initNowArg(arg);
            nowArg.exec = arg.exec;

            // コールバック処理の実行
            if (arg.exec) {
                nowArg.exec();  // 関数を実行
            } else {
                loopUnable();   // ループ無効
            }
        }

        /**
         *  @access private
         *  @variable   WebSrch.initNowArg(arg)
         *  @title  現在引数の初期化
         *  @description
         *
         *      コールバック系処理の、現在引数を初期化する。
         *
         *  @param  arg     追加実行する関数オブジェクト
         *  @return なし。
         */
        function initNowArg(arg) {
            // 現在引数を初期化
            nowArg = {};

            // 初期化処理
            //  ループが始まる前に一度だけ実行される。
            //  ループ回数の展開の前に行う。
            if (self.loopCnt == -1) {
                self.loopCnt = 0;       // ループ・カウントを0にセット
                if (arg.init && arg.init instanceof Function) {
                    arg.init();
                }
            }

            // ループ回数
            nowArg.loop = getPrm(arg.loop);
            nowArg.loop = (! nowArg.loop || nowArg.loop <= 0) ? 1 : nowArg.loop;
        }

        /**
         *  @access private
         *  @variable   WebSrch.loopUnable()
         *  @title  ループ無効
         *  @description
         *
         *      ループ無効時の処理。カウントを初期値にして、次の命令に移行する。
         *
         *  @return なし(メソッドチェーン不可)。
         */
        function loopUnable() {
            self.loopCnt = -1;  // ループのカウントを初期値に
            nextExec();     // 次の命令を実行
        }

        /**
         *  @variable   WebSrch.endCallback()
         *  @title  追加処理 コールバック 終了時用
         *  @description
         *
         *      登録した「addCallback」命令の終了時に呼び出すメソッド。
         *      この命令が呼ばれると、次の処理が実行される。
         *
         *  @return なし。
         */
        this.endCallback = function() {
            // ループのカウント
            var arg = nowArg;
            self.loopCnt ++;
            if (self.loopCnt < arg.loop) {
                execCnt --;     // カウント処理を戻す
            } else {
                self.loopCnt = -1;  // ループを無効に
            }

            // 命令を実行
            var intrvl = getIntrvl();   // インターバル
            if (intrvl <= 0) {
                nextExec();     // 次の命令を実行
            } else {
                setTimeout(nextExec, intrvl);   // インターバルで実行
            }
        }

        /**
         *  @variable   WebSrch.loopBreak()
         *  @title  ループ終了
         *  @description
         *
         *      ループ処理中で、ループを打ち切るフラグを立てるためのメソッド。
         *
         *  @return なし(メソッドチェーン不可)。
         */
        this.loopBreak = function() {
            nowArg.loop = 0;
        }

        /**
         *  @variable   WebSrch.cmndsBreak()
         *  @title  命令処理終了
         *  @description
         *
         *      命令処理中に、条件に応じて全ての処理を終了するためのメソッド。
         *      これ以降の命令を全て無効にして、現在実行中の処理までで終了する。
         *
         *  @return なし(メソッドチェーン不可)。
         */
        this.cmndsBreak = function() {
            this.isExec = false;
        }

        /*
         *--------------------------------------------------
        */

        // 検索用の変数
        var nowSrchObj;     // 一時的な検索オブジェクトの格納
        var pgCnt;          // ページのカウント
        var srchResArr;     // 検索結果配列
        this.srchKw = "";   // 検索キーワード

        /**
         *  @variable   WebSrch.srch(arg)
         *  @title  検索
         *  @description
         *
         *      検索の種類とループ回数を指定して、検索を行う。
         *      検索は、実行毎に「arg.key」の引数で指定した関数の戻り値を検索語として利用する。
         *      検索の結果は、「arg.res」の引数で指定した関数の戻り値として受け取る。
         *
         *  @param  arg.init    ループ実行前の処理を関数で指定。
         *  @param  arg.loop    ループの回数を指定。
         *  @param  arg.type    種類を指定(web, img, nws, blg)。
         *  @param  arg.page    検索結果のページを、何ページ分取得するか指定。
         *  @param  arg.key     戻り値にキーワードを返す関数を指定。
         *  @param  arg.res     結果を受け取る関数を指定。
         *  @return this(メソッドチェーン可能)。
         */
        this.srch = function(arg) {
            this.pushCmnds({prm : arg, fnc : doSrch});
            return this;
        };

        /**
         *  @access private
         *  @variable   WebSrch.doSrch(arg)
         *  @title  検索 実行
         *  @description
         *
         *      登録した「srch」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return なし。
         */
        function doSrch(arg) {
            // エラー対策
            if (! arg) {loopUnable(); return}   // ループ無効

            // 値の展開
            initNowArg(arg);

            nowArg.type = getPrm(arg.type) || "";

            nowArg.page = getPrm(arg.page); 
            nowArg.page = (! nowArg.page || nowArg.page <= 0) ? 1 : nowArg.page;

            nowArg.key  = getPrm(arg.key);
            nowArg.res  = arg.res;

            // 検索オブジェクトの取得
            var obj = null;
            for (var key in self.srchPrms) {
                if (nowArg.type == key) {
                    obj = self.srchPrms[key].obj;

                    // Searcherオブジェクトの初期化確認
                    if (obj == null) {
                        if (autoSrcherInit) {
                            // 無限ループ対策
                            autoSrcherInit = false; // 自動初期化開始
                            alert("err : can't use Searcher type " + nowArg.type + ".");
                            self.cmndsBreak();  // 命令処理終了
                            nextExec();         // 次の命令を実行
                            return;
                        }
                        autoSrcherInit = true;  // 自動初期化開始
                        var newArg = {type: nowArg.type};
                        execCnt --;         // カウント処理を戻す
                        doInit(newArg);     // 初期化を行う
                        return;
                    }

                    break;
                }
            }
            autoSrcherInit = false; // 自動初期化開始

            // 検索の実行
            if (obj != null && nowArg.key) {
                nowSrchObj = obj;   // 一時的な検索オブジェクトの格納
                pgCnt = 0;          // ページ位置の初期化
                srchResArr = [];    // 検索結果配列の初期化
                obj.setSearchCompleteCallback(this, function(){
                    doPage();
                }, null);
                self.srchKw = nowArg.key;   // 検索キーワード
                obj.execute(nowArg.key);
            } else {
                loopUnable();   // ループ無効
            }
        };

        /**
         *  @access private
         *  @variable   WebSrch.doPage()
         *  @title  検索 ページング
         *  @description
         *
         *      登録した「srch」のページ処理を行うためのメソッド。
         *
         *  @return なし。
         */
        function doPage() {
            // 変数の初期化
            pgCnt ++;
            var obj = nowSrchObj;
            var arg = nowArg;
            var res = obj.results;

            appndRes();         // 結果追加
            eachCall(); // 毎回処理

            // 結果の格納
            if (res && res.length > 0) {
                srchResArr = srchResArr.concat(res);    // 検索結果の連結
            }

            // ページ数
            var pgMax = 0;
            if (obj.cursor && obj.cursor.pages) pgMax = obj.cursor.pages.length;

            // 結果による分岐
            if (pgCnt < arg.page && pgCnt < pgMax) {
                // ページめくりが継続
                var intrvl = getIntrvl();   // インターバル
                if (intrvl <= 0) {
                    obj.gotoPage(pgCnt);        // 次のページを実行
                } else {
                    setTimeout(function() {     // インターバルで実行
                        obj.gotoPage(pgCnt);    // 次のページを実行
                    }, intrvl);
                }
            } else {
                // ページめくりが終了
                arg.res(srchResArr, obj.cursor);    // 引数の関数に結果を入れて実行
                self.endCallback();
            }
        }

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.feed(arg)
         *  @title  フィード検索
         *  @description
         *
         *      RSSフィードをJSONにして取得する。
         *
         *  @param  arg.init    ループ実行前の処理を関数で指定。
         *  @param  arg.loop    ループ回数の数字か関数を指定。
         *  @param  arg.url     読み込むRSSのURLを関数の戻り値として指定。
         *  @param  arg.res     結果を受け取る関数を指定。
         *  @return this(メソッドチェーン可能)。
         */
        this.feed = function(arg) {
            this.pushCmnds({prm : arg, fnc : doFeed});
            return this;
        };

        /**
         *  @access private
         *  @variable   WebSrch.doFeed(arg)
         *  @title  フィード検索 実行
         *  @description
         *
         *      登録した「feed」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト
         *  @return なし。
         */
        function doFeed(arg) {
            // エラー対策
            if (! arg) {loopUnable(); return}   // ループ無効

            // google.feedsの初期化確認
            if (! google.feeds) {
                // google.feedsオブジェクトが不在
                loadGglJS("feeds", "1", doFeed, arg);
                return;
            }

            // 値の展開
            initNowArg(arg);
            nowArg.url  = getPrm(arg.url);
            nowArg.res  = arg.res;

            // フィード検索の実行
            if (nowArg.url != "" && nowArg.res instanceof Function) {
                var feed = new google.feeds.Feed(nowArg.url);
                feed.setNumEntries(100);    // 100取得
                feed.load(function(res){
                    nowArg.res(res)
                    self.endCallback();
                });
            } else {
                loopUnable();   // ループ無効
            }
        };

        /*
         *--------------------------------------------------
        */

        // 検索結果追加先(検索が行われるごとに呼び出される)
        /**
         *  @variable   WebSrch.appndResTgt
         *  @title  検索結果追加先の要素ID
         *  @description
         *      検索が行われるとごとに、検索結果を出力させるために使用。要素IDを指定する。
         *
         *      デフォルトは空文字(指定なし)。
         *
         *      詳しくはサンプルのソースコードを参照。
         */
        this.appndResTgt = "";      // 検索結果追加先の要素ID

        /**
         *  @variable   WebSrch.appndResDeco
         *  @title  検索結果追加の加工用関数
         *  @description
         *      検索が行われるとごとに、検索結果を出力させるために使用。
         *      出力を加工するための関数を指定。
         *
         *      デフォルトはnull。
         *
         *      詳しくはサンプルのソースコードを参照。
         */
        this.appndResDeco = null;   // 検索結果追加の加工用関数

        /**
         *  @access private
         *  @variable   WebSrch.appndRes()
         *  @title  結果追加
         *  @description
         *
         *      検索が行われるごとに、検索結果を出力するために呼び出される内部関数。
         *
         *  @return なし。
         */
        function appndRes() {
            // 出力先の初期化
            if (self.appndResTgt == "") return;     // 不使用時
            var ele = document.getElementById(self.appndResTgt);
            if (! ele) return;      // 不正な指定
            var tagName = ele.tagName;
            var isTextArea = !! tagName.match(/textarea/i);

            // 変数の初期化
            var appndStr = "";
            var obj = nowSrchObj;
            var res = obj.results;

            if (! res || res.length <= 0) return;

            var deco;
            if (self.appndResDeco != null) {
                deco = self.appndResDeco;
            } else
            if (isTextArea) {
                deco = function(r) {
                    var resStr = "";
                    for (var key in r) {
                        resStr += key + " : " + r[key] + "\n";
                    }
                    resStr += "-----\n";
                    return resStr;
                };
            } else {
                deco = function(r) {
                    var resStr = "";
                    for (var key in r) {
                        resStr += '<div class="appndRes">'
                            + key + " : " + r[key] + "</div>";
                    }
                    resStr += '<hr class="appndResSplt">';
                    return resStr;
                };
            }

            // 加工処理
            for (var i = 0; i < res.length; i ++) {
                // 検索結果の追加
                if (isTextArea) {
                    ele.value += deco(res[i]);
                } else {
                    ele.innerHTML += deco(res[i]);
                }
            }
        }

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.shrtUrl(arg)
         *  @title  短縮URL
         *  @description
         *
         *      短縮URLの作成を行う。
         *
         *  @param  arg.init    ループ実行前の処理を関数で指定。
         *  @param  arg.loop    ループ回数の数字か関数を指定。
         *  @param  arg.url     変換を行うURLの文字列か関数を指定。
         *  @param  arg.res     結果を受け取る関数を指定。
         *  @return this(メソッドチェーン可能)。
         */
        this.shrtUrl = function(arg) {
            this.pushCmnds({prm : arg, fnc : doShrtUrl});
            return this;
        }

        /**
         *  @access private
         *  @variable   WebSrch.doShrtUrl(arg)
         *  @title  短縮URL 実行
         *  @description
         *
         *      登録した「shrtUrl」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return なし。
         */
        function doShrtUrl(arg) {
            // エラー対策
            if (! arg) {loopUnable(); return}   // ループ無効

            // jQueryの初期化確認
            if (! ("$" in window)) {
                // jQueryオブジェクトが不在
                loadJS(urlJQuery, doShrtUrl, arg);
                return;
            }

            // 値の展開
            initNowArg(arg);
            nowArg.url = getPrm(arg.url) || "";
            nowArg.res = arg.res;

            // コールバック処理の実行
            if (nowArg.url != "" && nowArg.res instanceof Function) {
                // 短縮URLの取得
                $.getJSON(
                    "http://json-tinyurl.appspot.com/?&callback=?",
                    {url: nowArg.url}, 
                    function(data){
                        nowArg.res(data.tinyurl);
                        self.endCallback();
                    }
                ); 
            } else {
                loopUnable();   // ループ無効
            }
        }

        /*
         *--------------------------------------------------
        */

        /**
         *  @variable   WebSrch.sgst(arg)
         *  @title  Google Suggest
         *  @description
         *
         *      Google Suggestを利用して、関連語の取得を行う。
         *
         *      戻り値を受け取る「arg.res」関数は、1つの連想配列を引数として受け取る。
         *      この引数の連想配列の内容は以下の通り。
         *
         *      「res : function(res) {}」の場合
         *
         *      res.jsonp …… 取得したJSONPの生データ。<br>
         *      res.raw …… 取得したデータ部分の生配列。<br>
         *      res.wrd …… 取得したデータを単語の配列にしたもの。
         *                  以降のデータは、半角スペースが入った文字列は分割して格納。<br>
         *      res.hd …… 検索文字を先頭に含む文字列配列(hd = head)。
         *                  「本」で検索して「本と私」という結果があれば「本と私」を格納。<br>
         *      res.not …… 検索文字を含まない単語配列。
         *                  「本」で検索して「本と私」という結果があれば無視する。<br>
         *
         *      検索語の末尾に半角スペースを入れると、関連語の一覧が取得できる。
         *      その際は「res.not」を使って関連語のリストを取得するとよい。
         *
         *      検索語の末尾に半角スペースを入れるなければ、その語に続く文章が取得できる。
         *      その際は「res.hd」を使って文字列を取得するとよい。
         *
         *  @param  arg.init    ループ実行前の処理を関数で指定。
         *  @param  arg.loop    ループ回数の数字か関数を指定。
         *  @param  arg.kw      検索するキーワードの文字列か関数を指定。
         *  @param  arg.res     結果を受け取る関数を指定。
         *  @return this(メソッドチェーン可能)。
         */
        this.sgst = function(arg) {
            this.pushCmnds({prm : arg, fnc : doSgst});
            return this;
        }

        /**
         *  @access private
         *  @variable   WebSrch.doSgst(arg)
         *  @title  Google Suggest 実行
         *  @description
         *
         *      登録した「doSgst」命令の実行。
         *
         *  @param  arg     追加実行する関数オブジェクト。
         *  @return なし。
         */
        function doSgst(arg) {
            // エラー対策
            if (! arg) {loopUnable(); return}   // ループ無効

            // jQueryの初期化確認
            if (! ("$" in window)) {
                // jQueryオブジェクトが不在
                loadJS(urlJQuery, doSgst, arg);
                return;
            }

            // 値の展開
            initNowArg(arg);
            nowArg.kw  = getPrm(arg.kw) || "";
            nowArg.res = arg.res;

            // コールバック処理の実行
            if (nowArg.kw != "" && nowArg.res instanceof Function) {
                // Google Suggestの取得
                $.getJSON(
                    "http://suggestqueries.google.com/complete/search?json=t&jsonp=?",
                    {hl: "ja", qu: nowArg.kw},
                    function(data){
                        /*
                         *  Suggestの戻り値の構造
                         *  callback(
                         *      検索キーワード,
                         *      [戻り値の配列],
                         *      [空文字列の配列],
                         *  )
                         */
                        var resArg = {
                            jsonp: data,    // 取得したJSONPの生データ。
                            raw: [],    // 取得したデータ部分の生配列。
                            wrd: [],    // 取得したデータを単語の配列にしたもの。
                                        // 以降のデータは、半角スペースが入った文字列は分割して格納。
                            hd: [], // 検索文字を先頭に含む文字列配列。
                                        // 「本」で検索して「本と私」という結果があれば「本と私」を格納。
                            not: []     // 検索文字を含まない単語配列。
                                        // 「本」で検索して「本と私」という結果があれば無視する。
                        };

                        // 引数の作成
                        if (data.length >= 2) {
                            // 変数の初期化
                            var dArr = resArg.raw = data[1];
                            var wrdHash = {};
                            var hdHash = {};
                            var notHash = {};
                            var kw = nowArg.kw.replace(/^ +| +$/g, "");

                            // 値の格納
                            for (var i = 0; i < dArr.length; i ++) {
                                var d = dArr[i].split(" ");
                                for (var j = 0; j < d.length; j ++) {
                                    // 変数の初期化
                                    var w = d[j];

                                    // 単語配列
                                    if (wrdHash[w] != 1 && w != kw) resArg.wrd.push(w);
                                    wrdHash[w] = 1;

                                    // 検索文字を先頭に含む文字列配列
                                    if (w.indexOf(kw) == 0 && w != kw) {
                                        if (hdHash[w] != 1) resArg.hd.push(w);
                                        hdHash[w] = 1;
                                    }

                                    // 検索文字を含まない単語配列
                                    if (w.indexOf(kw) == -1) {
                                        if (notHash[w] != 1) resArg.not.push(w);
                                        notHash[w] = 1;
                                    }
                                }
                            }
                        }

                        // 登録関数の実行
                        nowArg.res(resArg);
                        self.endCallback();
                    }
                ); 
            } else {
                loopUnable();   // ループ無効
            }
        }
    };
Cronus Crown(クロノス・クラウン)のトップページに戻る
(c)2002-2024 Cronus Crown (c)1997-2024 Masakazu Yanai
ご意見・お問い合わせはサイト情報 弊社への連絡までお願いします
個人情報の取り扱い、利用者情報の外部送信について