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(); // ループ無効
}
}
};







