テキストボックスに入力補完を付けてみる

引き続き、HTML Servicesでどこまで、貧弱なGUI環境をカバーできるかに挑戦中なのですが、GASでフォームのようなものや、UIを作るとなると、様々なライブラリのお世話になる必要性があったりします。GAS自体には、UIを定義するものは、UiAppのGWTしかなく、HTML ServicesのそれはあくまでもHTMLが持っているFORMの機能と、ライブラリを使っているだけでGASではないわけです(HTML中でGASは使えたりするのが、大きな違いではありますが)。

そこで、現在フォームを構築中で最も需要のあるものの一つに、入力補完があります。但し、GASのHTML Servicesで使用できるライブラリと機能は限られているので、どこまでこの入力補完が出来るのか?というのは色々と面白い挑戦になるかと思います。

概要

今回は、超シンプルにテキストボックスに入力中の文字列の入力補完をやってみたいと思います。使用例としては、例えば、メールアドレスの入力補完であったり、特定の名称の入力補完であったり、色々と使えるんじゃないかと思います。また、GASで補ってやることで、入力補完のリストを色々構築できるのではと思います。今回の機能を使うためには、以下の外部ライブラリが必要でした。

  1. jQuery 1.10.2以上のライブラリ
  2. jQuery UI 1.10.2以上のライブラリ
  3. jQuery UI CSS 1.10.2のファイル

いずれのファイルも、Google Hosted Librariesから利用させて頂いています。

ソースコード(基本)

GAS側コード

function doGet(){
  var output = HtmlService.createTemplateFromFile('index.html');
  var html = output.evaluate();
  return html;
}

HTML側コード

※ソースコードそのものはこのサイトより、丸パクリしてます。

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/smoothness/jquery-ui.css" />
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script>
<p><input type="text" id="hogehoge" /><br />
<script type="text/javascript">// <![CDATA[
$(function() {
  var hogehogeTags = [
    "あいうえお",
    "かきくけこ",
    "さしすせそ",
    "たちつてと",

・・・・・ 中略 ・・・・・

    "漢字1",
    "漢字2",
    "漢字3"
  ];
  $( "#hogehoge" ).autocomplete({
    source: hogehogeTags
  });
});
// ]]&gt;</script>

スプレッドシート連携の入力補完機能

しかし、この入力補完は、非常に少数のワードの補完でしか実用的じゃありません。そこで、考えたのがスプレッドシートとの連携。Predication API連携も考えてみたのですが面倒なのでやめました。そこまでするものじゃないと。スプレッドシートに予め、特定のワードを散りばめて於いてそれを入力補完時に呼びだす方法です。しかし、いかんせん遅い部分がありますので、せいぜい1000ワードくらいが限界かなぁと。もうちょっと別の方法が使えれば高速化して、高度な入力補完なんかもできるかもしれません。

今回使用するスプレッドシートはこちらのスプレッドシート。こちらにあるワードを補完リストとして使用します。尚、この方法はデータの塊を取得する部分をVisualization APIなどを併用すれば、Google Sites以外でも利用することが可能です。同様の方法でスプレッドシート連携のGoogle Mapsなんかも作れます。

ソースコード

GAS側コード

function doGet(){
  var output = HtmlService.createTemplateFromFile('index.html');
  var html = output.evaluate().setSandboxMode(HtmlService.SandboxMode.NATIVE);
  return html;
}

HTML側コード

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/smoothness/jquery-ui.css" />
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script>
<style>
.ui-autocomplete {
    max-height: 100px;
    
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: 20px;
}
#jquery-ui-autocomplete label {
    float: left;
    margin-right: 0.5em;
    color: black;
    font-size: 15px;
}
</style>
<script type="text/javascript">
var testman = <?!= JSON.stringify(SpreadsheetApp.openById('スプレッドシートのID').getRangeByName('potato').getValues());?>
</script>
<div id="jquery-ui-autocomplete" class="ui-widget">
    <label for="jquery-ui-autocomplete-label">入力欄: </label>
    <input id="mon" />
</div>
<script type="text/javascript">// <![CDATA[
$(function() {
var word = [];
for(var i = 0;i<testman.length;i++){
   word.push(String(testman[i]));
}
  var pin = word;
  
  $( "#mon" ).autocomplete({
    source: pin
  });
});
// ]]&gt;</script>

解説とヒント

今回は以下のようなポイントがありました。

  1. 今回は、jQueryとjQuery UIおよびCSSを利用しています。
  2. CSSでのサイズ調整を行わないと、Appスクリプトガジェットとして使う場合に、入力候補のスクロールバーが出ても触るだけで消えてしまうので、さらにサイズ調整用のCSSを入れてあります。
  3. 入力補完を行うスクリプトは、メインのHTMLより下に記述してます。
  4. 入力補完用のデータはGASとして、強制表示の<?! ?>の間に、尚且つJSON.stringfyにて、グローバル変数であるtestmanに取得させてます。
  5. ここは、ちょっと考えないといけないのですが、やり方がわからなかったので、毎回4.で取得したデータの塊をword配列に格納してあげてます。
  6. 配列に格納する時に、必ずStringで文字列に変換してあげてください。こうしないと文字列であっても変換候補に出てきません。
  7. 実は色々と試してみたのですが、スプレッドシート側のデータを1つの配列の中に入れてあげないといけないのですが、予めGAS側で処理して渡しても、なぜか表示されませんでした。
  8. jQueryライブラリの力を借りて、リッチで強力な機能がこれで実装し、しかも、HTML Services上で動作することが出来ました。sandbox modeのNATIVEにしたらもうちょっと早く表示されるかもしれません。
  9. 変換候補は、外部JSファイルに格納しておくだとか、この部分をGASで実装し、スプレッドシートから動的に候補を作成する、作成済みの候補リストをcache serviceを使ってキャッシュしておき、それを呼び出すなどが出来るのではと現在実験中です。
  10. 候補を選択すると、テキストボックスにそれが入ります。
  11. Googleの外部APIなどを併用すると、例えばContacts APIでメールアドレス一覧を動的に作るなんてことも可能になるんじゃないかと思ってます。

よって、これに更に修正を掛けるタスクとしては、

  1. word配列は表示時に1度だけ作るようにしたい(どうしたら良いかわからない・・・)。それを補完候補として利用するようにすれば高速化できると思う。
  2. サイズ調整して、入力候補はもうちょっとスマートにしたい。

実行結果

適当に「東京都」といれて確定すると、続けて入力補完候補(新宿区の住所)が出てきます。GWTのサジェストボックスのようなものが実現出来ます。この実行結果は、スプレッドシートと連携(700個くらいのデータ)しています。