おもしろかったので紹介。
Opera Unite とウェブページで JSONP 通信して、アドオンのようなことを実現するサンプル。
これで使われている JSMigemo というのは、辞書ファイルを複数の XML に分割して、XMLHttpRequest で取りに行っている。ローカルサーバーで走っているのにこれだと効率が悪いので、せっかくなら辞書を1ファイルにしてしまおう、という話を別のブログに書いた。
作ったファイルがこれ。
これを使うように JSMigemo を修正するなら、変更点はこんな感じになる。
% diff -u migemo_orig.js migemo.js --- migemo_orig.js 2009-07-20 19:58:50.000000000 -0400 +++ migemo.js 2009-07-20 14:23:08.000000000 -0400 @@ -276,79 +276,14 @@ }, - Dictionary: function () { - // Dictionary class - this.createIndex = function() { - var doc = _migemo.xmlDocument(_migemo.joinPath(_migemo.dictdir_path, - "dictindex.xml")); - var items = doc.getElementsByTagName("item"); - for (var i=0; i<items.length; i++) { - var values = items[i].getElementsByTagName("value"); - var pathList = []; - for (var j=0; j<values.length; j++) { - pathList.push(values[j].firstChild.nodeValue); - } - this._index[items[i].getAttribute("key")] = pathList; - } - } - - this.getLookupTable = function(xmldoc) { - var table = []; - var items = xmldoc.getElementsByTagName("item"); - for (var i=0; i<items.length; i++) { - var candidates = new Array(); - var valueElements = items[i].getElementsByTagName("value"); - for (var j=0; j<valueElements.length; j++) { - candidates.push(valueElements[j].firstChild.nodeValue); - } - table.push({"key":items[i].getAttribute("key"), - "candidates": candidates}); - } - table.sort(function(x,y) {return _migemo.compareStrings(x.key,y.key);}); - return table; - } - - this.seek = function(path, key) { - result = new Array(); - // load dictionary - var doc = _migemo.xmlDocument(_migemo.joinPath(_migemo.dictdir_path, - path)); - var dic = doc.getElementsByTagName("dictionary")[0].firstChild; - var text = dic.nodeValue; - // search matched lines - var lines = text.match(RegExp("^"+key+".*\n","mg")); - // for each line: - if (lines) { - for (var i=0; i<lines.length; i++) { - // add result to result - var values = lines[i].slice(0,-1).split("\t").slice(1); - result = result.concat(values); - } - } - // return result - return result; - } - + Dictionary: function(){ this.lookup = function(key) { - var paths = this.getDictionaryPaths(key); - var values = new Array(); - for (var i=0; i<paths.length; i++) { - values = values.concat(this.seek(paths[i], key)); - } - return values; - } - - this.getDictionaryPaths = function(key) { - var paths = this._index[key.substring(0,1)]; - if (typeof paths == "undefined") { - paths = []; - } - return paths; + var initial = key[0]; + var candidates = migemoDict[initial]; + var ans = []; + for(var word in candidates) if (!word.indexOf(key)) ans = ans.concat(candidates[word]); + return ans; } - - // initialization - this._index = {}; - this.createIndex(); }, Node: function (value, children) { @@ -394,22 +329,6 @@ } }, - xmlDocument: function (path) { - // download XML document located at path - var xmldoc; - if( window.ActiveXObject && /Win/.test(navigator.userAgent) ) { - xmldoc = new ActiveXObject("Microsoft.XMLDOM"); - xmldoc.async = false; - xmldoc.load(path); - } else if( document.implementation && - document.implementation.createDocument ) { - xmldoc = document.implementation.createDocument("", "", null); - xmldoc.async = false; - xmldoc.load(path); - } - return xmldoc; - }, - compareStrings: function (x, y){ var result; if (x.slice(0,y.length)==y) {
つまり、_migemo.Dictionary を以下のものに変えて、さらに _migemo.xmlDocument を削除する、という意味。
Dictionary: function(){ this.lookup = function(key) { var initial = key[0]; var candidates = migemoDict[initial]; var ans = []; for(var word in candidates) if (!word.indexOf(key)) ans = ans.concat(candidates[word]); return ans; } },
それから、index.html のほうで新しい辞書を読んであげる。
<script type="text/javascript; charset=utf-8" src="migemoDict.js"></script> <script type="text/javascript; charset=utf-8" src="migemo.js"></script>
XML ファイルは config.xml 以外全部消す。
ちょっとは速くなるかな? (ちゃんと比べてないのでわからない)
JSMigemo はこれ以外にも精度やパフォーマンスの問題を抱えているので、まだ効率向上の余地はあるはず。一度検索したものをキャッシュしたりなどなど。
(JSMigemo はちょっと古いので、XUL/Migemo の方が参考になる)