JavaScriptでGoogleサジェストを使ったサイト作ってみたった。

スマホのソフトキーボードで打ち間違い連発に嫌気がさしたので、Googleトレンドやはてなキーワードから検索ワードを取得し、Googleサジェストで次々候補を表示できるサイトを作ってみた。
Touch Search
今まで無かった要素はゴミ箱ボタン。ゴミ箱をタップで、検索文字列のうち一番前の単語が消去される。これを使って、今まで検索したことの無い言葉の組み合わせでサジェスト結果が得られる。
思いついた時は「これは新しい!」と個人的に喜んだが、実装してみるとそこまでは面白くなかったw
よっぽど現在地を利用したサジェストのが面白いなーと。

仕組みとしては、ほとんどはJavaScriptで、外部ドメインXMLを取りに行くときだけRubyで書いたCGI使ってる。
外部APIとしては、Google Suggest APIHeartRails GeoAPI使わせてもらっています。ありがとうございます。

追記(2014.04.18)

一応、Googleサジェスト取得の手順を書いときます。
JQueryを使ってるので、先に読み込んでおいてください。
まず、CGIとして使っているRubyスクリプト

#! /usr/local/bin/ruby
print "Content-type: text/xml charset=utf-8\n\n"
# -*- coding: utf-8 -*-
#
# usage : google_suggest.rb <投入クエリ>
#
#$KCODE="u"
# regquire
require 'net/http'
require 'cgi'
require 'kconv'
require 'rexml/document'

# 検索クエリ
cgi_data = CGI.new
word = cgi_data["q"]

#Googleに候補を取りに行く
http = Net::HTTP.new('www.google.co.jp', 80)
query = "/complete/search?output=toolbar&q=#{CGI::escape(word)}&hl=ja"
req = Net::HTTP::Get.new(query)
res = http.request(req)

#XMLを得る
doc = REXML::Document.new res.body.toutf8

#XMLツリー全体を出力
print '<?xml version="1.0"?>'
print doc.root

最後に標準出力に出すときにXMLのヘッダを出力してやらないとダメだったので本文出力前に追加している。

これを呼び出すJavaScriptは、普通のAjaxによるHTTPアクセスでよい。
setTimeoutで500ミリ秒ごとにフォームを監視し、書き換えが発生していたら
サジェストを取得しに行くようにしている。

//global paramater
var myValue;

//------------------------
// ページ読み込み時の処理
//------------------------

$(document).ready(function(){

	myValue = "";

	//フォーム監視開始
	setTimeout("Check_form()",500);

});

//------------------------
// 一定期間ごとにフォームを監視
//------------------------

function Check_form(){

	//formのidから値を取得
	SrcValue = document.getElementById("input").value;

	// もしform内に変化があるならば
	if (SrcValue != "") {
		if (myValue != SrcValue) {
			$("#answer").empty();	// #answer内を空に
			myValue = SrcValue;		// グローバル変数にform内を格納
			get_suggest(myValue);	// google suggest check
		}
	}
	setTimeout("Check_form()",500);
}
//------------------------
//Google suggestを得る CGI呼び出し
//------------------------

function get_suggest(str){

url_str = "cgi/google_suggest.cgi?q=" + str;

$.ajax({
	    url: url_str,	// http://から始まるURLを指定
    	type: 'GET',
	    success: parse_xml //取得したXMLの処理
});	//end of $.ajax

}	//end of get_suggest

//------------------------
// XMLを表示
//------------------------
function parse_xml(xml,status){  
	//通信できなかったらreturn
    if(status!='success')return;  

	$("#loading").hide();	//loadingアイコン非表示
    //通信できたら
    $(xml).find('suggestion').each(function(){
		//Suggestで得た単語をSuggest要素で追加
		$('#answer').append('<div class="suggest">'+$(this).attr("data")+'</div>'); 
		//Suggest要素にOnClickイベントを追加
		$('div.suggest').click(function() {
			document.getElementById("input").value = $(this).text();
		});
	});  
}  

最後のparse_xmlでは、取得したXMLからサジェストの単語を抜き出して#answer要素内に追加している。
ただ追加するだけだとクリッカブルにならないので、要素追加後にイベントをclickメソッドで追加。
最初悩んだのが、clickイベントで追加するfunction内のthisってなんだ?ってこと。
この場合はクリックされた要素を指すんだね。

知ってる人には簡単なんだろうけど、自分でやってみようと思ったときにjsからCGI呼び出すとか悩んだことが多かったので、ここで書いてみました。今回RubyJQueryに初めて手を出してみたんだけど、Web上の先人たちのブログやリソースでほとんどのことは解決できた。一番わからなかったのが、簡単なはずのjsからのajaxでのCGI呼び出しだったというのが…。1冊は本を買えと言うことなんでしょうか。
次は何を作ってみようか。

制作物の置き場
tbcafe.sakura.ne.jp