FC2ブログ

スポンサーサイト

-------- --:--:-- --

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【Java】【Google App Engine】GAEでインクリメンタルサーチ【javascript】

2011-12-28 02:07:05 Wed

■GAEでインクリメンタルサーチ


インクリメンタルサーチ(候補検索)を行うには前方一致検索をする必要がある。
SQL的に記述すると param% のような記述になるがこれをGAEの制限されたDatastoreで表現すると次のようになる。
Slim3を使っています。

public List search(Map params){
IncrementalSearchMasterMeta meta = IncrementalSearchMasterMeta.get();
String param = (String)params.get("send_data");
String param2 = param + "\uFFFD";
List list = Datastore.query(meta).filter(meta.text.greaterThanOrEqual(param)).filter(meta.text.lessThan(param2)).limit(10).asList();
return list;
}


こんな感じ。
フィルタクエリで param <= text AND text < param2 と指定しています。
param:あ <= text AND text < param2: あ + \uFFFDという感じの範囲検索で実現できます。
上記であれば「あ」から始まるものをすべて取得できます。

http://code.google.com/p/objectify-appengine/wiki/FrequentlyAskedQuestions
http://blog.virtual-tech.net/2009/10/google-app-engine-key.html


■ちょっと厄介なクライアントコーディング


インクリメンタルサーチをすればGoogleみたいに入力ボックスの下にびろっと出して選択できるようにしたくなりました。
で適当に作りました。
スクロールバーのこととか、下キー上キーのキー制御のロジックとか入っていませんがメモ。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset=utf-8 />
<title>Test</title>
<script src="/common/js/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
// tableタグを生成して非表示で追加
var table = $('<table id="incremental" onclick="onClick(event, true)" onmouseout="onMouseOut(event,true)" onmouseover="highlight(event,true)" style="position: absolute;overflow: visible;top: 73px;left: 8px;width: 155px;border: 1px #E3E3E3 solid;border-collapse: collapse;border-spacing: 0;text-alighn: left;display: none;cursor: pointer; background-color: white;"><tr><td>aaa</td></tr></table>');
$('html').append(table);

// 入力ボックスへのイベント設定
$("[name=keyword]").bind("keyup", onCange);
$("[name=keyword]").bind("blur", onBlur);

// 登録ボタンへのイベント設定
$("#regBtn").bind("click", register);
});

// インクリメンタルサーチの候補一覧が選択されたとき選択されている行のテキストを入力テキストに代入して候補一覧を非表示にする
function onClick(e,b){
    var src;
    // Netscape イベント処理用の分岐
    if (navigator.appName == "Netscape"){
        src = e.target;
    }else{
        src = e.srcElement;
    }
    if (src.tagName == "TD") {
        if(b==true) { // mouseOver, and highlight {
         var text = src.textContent;
         $("[name=keyword]").val(text);
        }else{        // mouseOut, restore original color
        }
    }
    $("#incremental").hide();
}

// マウスが候補一覧上にあるとき特定行の背景色を変更する
function highlight(e,b) {
    var src;
    // Netscape イベント処理用の分岐
    if (navigator.appName == "Netscape"){
        src = e.target;
    }else{
        src = e.srcElement;
    }
    if (src.tagName == "TD") {
        if(b==true) { // mouseOver, and highlight {
            src.originColor=src.style.backgroundColor;
            src.style.backgroundColor="gray";
        }else{        // mouseOut, restore original color
            src.style.backgroundColor=src.originColor;
        }
    }
}

// マウスが候補検索一覧上にあって背景色が変更された特定行からマウスを違うところへ移動したとき背景色を元に戻す
function onMouseOut(e,b){
    var src;
    // Netscape イベント処理用の分岐
    if (navigator.appName == "Netscape"){
        src = e.target;
    }else{
        src = e.srcElement;
    }
    if (src.tagName == "TD") {
        if(b==true) { // mouseOver, and highlight {
            src.originColor=src.style.backgroundColor;
            src.style.backgroundColor="white";
        }else{        // mouseOut, restore original color
            src.style.backgroundColor=src.originColor;
        }
    }
}

// 入力テキストに文字が入力されたときajaxで候補一覧を取得しこれを候補一覧に表示する
function onCange(){

var value = $("[name=keyword]").val();
if(value == ""){
return;
}
jQuery.ajax({
url: "incremental/search",
cache: true,
data: {"send_data": value},
success: function(msg){
// テーブル内のHTMLを空にする
$("#incremental").empty();
// 取得したデータをテーブル内に反映する
var list = msg["retlist"];
for(var i = 0; i < list.length; i++){
var tr = $("<tr><td>" + list[i]["text"] + "</td></tr>");
$("#incremental").append(tr);
}
$("#incremental").show();
}
});
}

// 入力テキストからフォーカスが外れたとき200ミリ秒して候補一覧を非表示にする
function onBlur(){
setTimeout(function(){$("#incremental").hide();},200);
}

// 登録ボタンが押下されたとき入力テキストの入力内容をパラメータとしてajax通信し候補キーワードとして登録する
function register(){
var value = $("[name=keyword]").val();
if(value == ""){
$('#logarea').prepend('<p>キーワードを入力して下さい。' + new Date() + '</p>');
return;
}
jQuery.ajax({
url: "register",
cache: true,
data: {"send_data": value},
success: function(msg){
$('#logarea').prepend('<p>登録完了。' + new Date() + '</p>');
}
});
}

</script>
</head>
<body>
<p>search test</p>
<input type="text" name="keyword" style="width: 150px; height: 17px;">
<input type="button" value="register" id="regBtn" >
<div id="logarea"></div>
</body>



検索のajaxでのサーバ側は単純にリクエストされたテキストを取得して前述したクエリで検索すれば候補検索する一覧が取得できる。
登録のajaxはただただリクエストされたテキストをそのまま候補検索されるカインドにエンティティとして放り込むだけ。
本当はエラーハンドリングとかちゃんとやらないといけないけどそれまた。。。

スポンサーサイト

⇒comment

Secret

名言集
全記事(数)表示
全タイトルを表示
ブログ内検索
Loading
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。