ime.js
1
2 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3 // Don't Remove Following.
4 // Japanese Input Method Sample ver1.00 for Ajax Baron
5 // Copyright 2006 web2driver.com
6 // programmed by T.Misawa
7 // info@web2driver.com
8 // スクリプトの改変は自由に行って結構ですが、
9 // この著作権表示は残してください
10 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11
12 //キー定数の定義
13 var VKEY_RIGHT=39;
14 var VKEY_LEFT=37;
15 var VKEY_UP=38;
16 var VKEY_DOWN=40;
17 var VKEY_ESC=27;
18 var VKEY_BS=8;
19 var VKEY_ENTER=13;
20 var VKEY_SPACE=32;
21
22 //変換の飾り枠関連定数群
23 var BRACKET_RH_S="(";//ローマ字->ひらがな変換中のブラケット
24 var BRACKET_RH_E=")";//ローマ字->ひらがな変換中のブラケット
25 var BRACKET_HK_S="[";//ひらがな->漢字変換中のブラケット
26 var BRACKET_HK_E="]";//ひらがな->漢字変換中のブラケット
27 //変換モード関連定数群
28 var HENKAN_MODE_HKANJI_HTML="<span style='background-color:black;color:white'>R単
29 漢字変換[あ]</span>";//変換モード名
30 var HENKAN_MODE_KKANJI_HTML="<span style='background-color:black;color:white'>R単
31 漢字変換[ア]</span>";//変換モード名
32 var HENKAN_MODE_DIRECT_HTML="<span style='background-color:white;color:black'>直
33 接入力[a]</span>";//変換モード名
34 var HENKAN_MODE_DIRECT=0;
35 var HENKAN_MODE_HKANJI=1;
36 var HENKAN_MODE_KKANJI=2;
37 //入力ステータス関連定数群
38 var STAT_WAITING_FOR_INPUT=0;//ひらがな入力待ち
39 var STAT_NOW_ROMAN_TYPING=1;//ひらがな入力中
40 var STAT_NOW_KANJI_CONVERTING=2;//漢字変換中
41
42 var romanKanaMap=new Object();//ローマ字-ひらがな対照表を格納する連想配列
43 var localDictionary=new Object();//ローカルに保持するキャッシュ用辞書
44 var inputStat=STAT_WAITING_FOR_INPUT;//入力のステータス
45 var hotText="";//変換対象のテキスト
46 var fixedText="";//確定済みのテキスト
47 var nominationSelectIdx=-1;//変換中に表示される候補のカレント候補番号
48 var henkanMode=HENKAN_MODE_HKANJI;//変換モード
49 var textBox;//入力テキストボックス用HTML要素
50 var nominationBox;//候補表示用HTML要素
51
52 //ローマ字->ひらがな 対照表 "ローマ字","ひらがな"の順番に格納する
53 var ROMAN_KANA_DATA=[
54 "A","あ","I","い","U","う","E","え","O","お",
55 "KA","か","KI","き","KU","く","KE","け","KO","こ",
56 "GA","が","GI","ぎ","GU","ぐ","GE","げ","GO","ご",
57 "KYA","きゃ","KYU","きゅ","KYO","きょ",
58 "GYA","ぎゃ","GYU","ぎゅ","GYO","ぎょ",
59 "SA","さ","SHI","し","SU","す","SE","せ","SO","そ",
60 "ZA","ざ","JI","じ","ZU","ず","ZE","ぜ","ZO","ぞ",
61 "SHA","しゃ","SHU","しゅ","SHO","しょ",
62 "JA","じゃ","JU","じゅ","JO","じょ",
63 "TA","た","CHI","ち","TSU","つ","TE","て","TO","と",
64 "DA","だ","DI","ぢ","DU","づ","DE","で","DO","ど",
65 "CHA","ちゃ","CHU","ちゅ","CHO","ちょ",
66 "NA","な","NI","に","NU","ぬ","NE","ね","NO","の",
67 "NYA","にゃ","NYU","にゅ","NYO","にょ",
68 "HA","は","HI","ひ","FU","ふ","HE","へ","HO","ほ",
69 "BA","ば","BI","び","BU","ぶ","BE","べ","BO","ぼ",
70 "HYA","ひゃ","HYU","ひゅ","HYO","ひょ",
71 "BYA","びゃ","BYU","びゅ","BYO","びょ",
72 "PA","ぱ","PI","ぴ","PU","ぷ","PE","ぺ","PO","ぽ",
73 "PYA","ぴゃ","PYU","ぴゅ","PYO","ぴょ",
74 "MA","ま","MI","み","MU","む","ME","め","MO","も",
75 "MYA","みゃ","MYU","みゅ","MYO","みょ",
76 "YA","や","YU","ゆ","YO","よ",
77 "RA","ら","RI","り","RU","る","RE","れ","RO","ろ",
78 "RYA","りゃ","RYU","りゅ","RYO","りょ",
79 "WA","わ","WO","を","NN","ん",
80 "SI","し","TI","ち","TU","つ","XTU","っ",
81 "XA","ぁ","XI","ぃ","XU","ぅ","XE","ぇ","XO","ぉ",
82 "VA","ヴぁ","VI","ヴぃ","VU","ヴ","VE","ヴぇ","VO","ヴぉ",
83 "FA","ふぁ","FI","ふぃ","HU","ふ","FE","ふぇ","FO","ふぉ",
84 String.fromCharCode(188),"、",String.fromCharCode(189),"ー",String.fromCh
85 arCode(190),"。",
86 "0","0","1","1","2","2","3","3","4","4","5","5","6","6","7","7","
87 8","8","9","9"
88 ];
89
90 //ひらがなデータ
91 var HIRAGANA_DATA = "ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞ
92 ただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆ
93 ょよらりるれろゎわゐゑをんー−ヵヶヴ";
94 //カタカナデータ
95 var KATAKANA_DATA = "ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾ
96 タダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユ
97 ョヨラリルレロヮワヰヱヲンー−ヵヶヴ";
98
99 function initialize(){
100
101 textBox=getById("textBox");
102 nominationBox=getById("nominationBox");
103 getById("henkanMode").innerHTML=HENKAN_MODE_HKANJI_HTML;
104
105 //テキストボックスにフォーカス
106 textBox.focus();
107
108 //随時入力されるローマ字を格納しておくバッファ用変数
109 var charBuffer ="";
110
111 //Ajax Baronのスタブオブジェクトを生成
112 var stub=new AjaxBaronServiceStub();
113 // <nomination>要素を配列としてパースするよう設定する
114 stub.setArrayNodes("nomination");
115 //リクエストデータオブジェクトを生成
116 var requestData=new Object();
117 //サービスアドレスを定数に代入
118 var endpointAddress="jim";
119
120 //サービス実行結果を受け取るコールバックメソッドの設定
121 stub.onXmlReceive=henkanCallBack;
122
123 //ローマ字-ひらがな対照表を生成
124 buildRomanKanaMap();
125
126 //キー押下イベントの登録
127 textBox.onkeydown=function(e){
128
129 var keyCode=0;
130
131 //ブラウザ判定
132 if(document.all){
133 keyCode=event.keyCode;
134 }
135 else if(document.getElementById){
136 keyCode=e.which;
137 }
138
139 //ESCで変換モードの切り替え
140 if(keyCode==VKEY_ESC){
141 if(inputStat!=STAT_WAITING_FOR_INPUT){
142 alert("入力中は変換モードの切り替えはできません。
143 \n入力を確定してから[ESC]キーを押してください。");
144 }else{
145 //変換モードを切り替える
146 henkanMode++;
147
148 if(henkanMode>HENKAN_MODE_KKANJI){
149 henkanMode=HENKAN_MODE_DIRECT;
150 }
151 if(henkanMode==HENKAN_MODE_HKANJI){
152 fixedText=textBox.value;
153 getById("henkanMode").innerHTML=HENKAN_MO
154 DE_HKANJI_HTML;
155
156 }else if(henkanMode==HENKAN_MODE_KKANJI){
157 getById("henkanMode").innerHTML=HENKAN_MO
158 DE_KKANJI_HTML;
159 }else{
160 getById("henkanMode").innerHTML=HENKAN_MO
161 DE_DIRECT_HTML;
162 }
163 }
164 }
165
166 if(henkanMode!=HENKAN_MODE_DIRECT){
167
168 //キーが AからZ までの場合のみ か ,と.を変換する
169 //onkeydownイベントとonkeypressでは一部keyCodeが異なるた
170 め注意が必要
171 if( (keyCode>=48 && keyCode<=90) || (keyCode>=188 && keyC
172 ode<=190) ){
173
174 var unitChar=String.fromCharCode(keyCode);
175
176 //バッファに1文字のローマ字を追加
177 charBuffer+=unitChar;
178 //バッファにあるローマ字文字列からひらがながを取
179 り出してみる
180 var hiragana=getHiraganaFromRoman(charBuffer);
181
182 if(hiragana!=null){
183 //ひらがなに変換できたら、ローマ字->ひら
184 がな変換モードにする
185 inputStat=STAT_NOW_ROMAN_TYPING;
186 if(henkanMode==HENKAN_MODE_KKANJI){
187 hiragana=hiragana2kanakana(hiraga
188 na);
189 }
190 hotText+=hiragana;
191 textBox.value=fixedText+BRACKET_RH_S+hotT
192 ext+BRACKET_RH_E;
193 charBuffer="";
194 }
195 }
196
197 //エンターキーが押されたら
198 if(keyCode==VKEY_ENTER){
199
200 if(inputStat==STAT_WAITING_FOR_INPUT){
201 return true;
202 }
203 if(inputStat==STAT_NOW_KANJI_CONVERTING){
204 hotText=showNomination(hotText,nomination
205 SelectIdx);
206 }
207 //エンターキーが押されたら、hotTextを確定済みテキ
208 ストに追加
209 fixedText+=hotText;
210 //ホットテキストをクリア
211 hotText="";
212 //テキストボックスに確定済みテキストを設定
213 textBox.value=fixedText;
214 //モードを初期状態にする
215 inputStat=STAT_WAITING_FOR_INPUT;
216 }
217
218 if(keyCode==VKEY_SPACE ){
219
220 if(inputStat==STAT_NOW_ROMAN_TYPING){
221 //漢字候補番号を先頭にリセットする
222 nominationSelectIdx=-1;
223 //漢字変換モードに切り替える
224 inputStat=STAT_NOW_KANJI_CONVERTING;
225 }
226
227 //
228 if(inputStat==STAT_NOW_KANJI_CONVERTING){
229 //ローカル辞書にhotTextに相当する単語がな
230 ければ、サーバに問い合わせにいく
231 //つまり、1度変換された単語はローカル辞
232 書にキャッシュされる
233 if(localDictionary[hotText]==null){
234 requestData["hiraganaWord"]=hotTe
235 xt;
236 stub.processRequest(requestData,e
237 ndpointAddress);
238 }else{
239 //ローカル辞書にhotTextに相当する
240 単語があった場合は、候補番号をインクリメントして、
241 //候補一覧を表示する
242 nominationSelectIdx++;
243 showNomination(hotText,nomination
244 SelectIdx);
245 }
246 }
247 }
248
249 //矢印キーの下か右で変換候補を進める
250 if(keyCode==VKEY_DOWN || keyCode==VKEY_RIGHT){
251 if(inputStat==STAT_NOW_KANJI_CONVERTING){
252 if(localDictionary[hotText]!=null){
253 nominationSelectIdx++;
254 showNomination(hotText,nomination
255 SelectIdx);
256 }
257 }
258 }
259 //矢印キーの上か左で変換候補を戻す
260 if(keyCode==VKEY_UP || keyCode==VKEY_LEFT){
261 if(inputStat==STAT_NOW_KANJI_CONVERTING){
262 if(localDictionary[hotText]!=null){
263 nominationSelectIdx--;
264 if(nominationSelectIdx<0){
265 nominationSelectIdx=local
266 Dictionary[hotText].length;
267 }
268 showNomination(hotText,nomination
269 SelectIdx);
270 }
271 }
272 }
273
274 //バックスペース処理
275 if(keyCode==VKEY_BS){
276
277 //ローマ字->ひらがな変換中の場合
278 if(inputStat==STAT_NOW_ROMAN_TYPING){
279
280 var hotTextLeng=hotText.length;
281 //一番右の1文字を削除する
282 hotText=left(hotText,hotTextLeng-1);
283
284 if(hotText.length>0){
285 textBox.value=fixedText+BRACKET_R
286 H_S+hotText+BRACKET_RH_E;
287 }else{
288 //削除した結果 hotTextが空になっ
289 たらfixedTextのみ表示
290 inputStat=STAT_WAITING_FOR_INPUT;
291 textBox.value=fixedText;
292 }
293 }
294 //漢字変換中だった場合
295 else if(inputStat==STAT_NOW_KANJI_CONVERTING){
296 //漢字候補番号を先頭にリセットする
297 nominationSelectIdx=-1;
298 textBox.value=fixedText+BRACKET_RH_S+hotT
299 ext+BRACKET_RH_E;
300 inputStat=STAT_NOW_ROMAN_TYPING;
301 }
302 //変換確定後だった場合
303 else if(inputStat==STAT_WAITING_FOR_INPUT){
304 var fixedTextLeng=fixedText.length;
305 fixedText=left(fixedText,fixedTextLeng-1)
306 ;
307 textBox.value=fixedText;
308 }
309 }
310
311 if(inputStat!=STAT_NOW_KANJI_CONVERTING){
312 nominationBox.innerHTML="";
313 }
314
315 //変換モード中のキー入力はキャンセルする
316 return false;
317 }else{
318 //直接入力時はキー入力を戻す
319 return true;
320 }
321 }
322 }
323
324 //romanBlockであらわされるローマ字をひらがなに変換する関数
325 function getHiraganaFromRoman(romanBlock){
326
327 var retValue=null;
328
329 //romanBlockをキーに連想配列romanKanaMapからひらがなを取り出す
330 var hiragana=romanKanaMap[romanBlock];
331
332 //連想配列内に該当するひらがながみつからなければ、特殊ケースとして分析す
333 る。
334 if(hiragana==null){
335
336 //3文字でも該当が無い場合
337 if(romanBlock.length==3){
338
339 //3文字中後ろ2文字で該当した場合
340 if(romanKanaMap[right(romanBlock,2)]!=null){
341
342 //最初2文字が同じ文字である場合は 「っ」+後ろ2文
343 字が意味するひらがな
344 if(mid(romanBlock,1,1)==mid(romanBlock,2,1)){
345 retValue="っ"+romanKanaMap[right(romanBlo
346 ck,2)];
347 }
348 //最初の1文字がNである場合は 「ん」+後ろ2文字が意
349 味するひらがな
350 else if(left(romanBlock,1)=="N"){
351 retValue="ん"+romanKanaMap[right(romanBlo
352 ck,2)];
353 }
354 //それ以外の場合は、 最初1文字のローマ字と後ろ2文
355 字が意味するひらがな
356 else{
357 retValue=left(romanBlock,1)+romanKanaMap
358 [right(romanBlock,2)];
359 }
360 }
361 //3文字中後ろ1文字で該当があったら はじめの2文字のローマ
362 字と後ろ1文字が意味するひらがな
363 else if(romanKanaMap[right(romanBlock,1)]) {
364
365 retValue=left(romanBlock,2)+romanKanaMap[right(ro
366 manBlock,1)];
367 }else{
368 //該当がなければ、3文字のローマ字をそのまま出力
369 retValue=romanBlock;
370 }
371 }
372 }
373 else{
374 retValue=hiragana;
375 }
376
377 return retValue;
378 }
379
380 //変換サービスのAjax呼びだしを受け取るコールバック関数
381 function henkanCallBack(responseData){
382 var result=responseData.result;
383 var hiraganaWord=result.hiraganaWord;
384 //該当する変換候補があったら
385 if(result.nomination){
386 //ローカル辞書に hiraganaWordをキーにして変換候補一覧(nomination)
387 を保存する
388 localDictionary[hiraganaWord]=result.nomination;
389 //カレントの変換候補番号をインクリメント
390 nominationSelectIdx++;
391 }
392 //変換候補の表示処理を呼び出す
393 showNomination(hiraganaWord,nominationSelectIdx);
394 }
395
396 //変換候補の表示処理を行う
397 function showNomination(hiraganaWord,nominationIdx){
398 var nomination=localDictionary[hiraganaWord];
399 var targetWord=null;
400
401 //候補があった場合
402 if(nomination!=null){
403 //候補番号を取得する(効率化のため剰余を使用)
404 var idx=nominationIdx % nomination.length;
405 //idx番目の変換候補を取得する
406 var kanjiWord=nomination[idx];
407
408 //変換候補ボックス内に変換候補を表示するためのinnerHTMLを生成する。
409 var innerHtml="【候補】 ";
410 for(var i=0;i<nomination.length;i++){
411 var htmlPart="<span style='color:black;background-color:w
412 hite;'>"+nomination[i]+"</span> ";
413 if(i==idx){
414 htmlPart="<span style='color:white;background-col
415 or:blue;'>"+nomination[i]+"</span> ";
416 }
417 innerHtml+=htmlPart;
418 }
419
420 //変換候補ボックス内に変換候補を設定
421 nominationBox.innerHTML=innerHtml;
422 targetWord=kanjiWord;
423 }else{
424 //変換候補が無かった場合はひらがなをそのまま表示
425 targetWord=hiraganaWord;
426 }
427 //テキストボックスに変換途中の候補を表示する
428 textBox.value=fixedText+BRACKET_HK_S+targetWord+BRACKET_HK_E;
429
430 return targetWord;
431 }
432
433 //ローマ字->ひらがな対照表の連想配列を生成する。
434 function buildRomanKanaMap(){
435 for(var i=0;i<ROMAN_KANA_DATA.length;i+=2){
436 romanKanaMap[ROMAN_KANA_DATA[i]]=ROMAN_KANA_DATA[i+1];
437 }
438 }
439
440 //以下ヘルパー関数群---------------------------------------------
441 function mid(str,start,leng){
442 // 文字列のstart文字(最初の文字は1)からleng文字文を切り抜く
443 return str.substring((start-1),(start-1)+leng);
444 }
445 function right(str,cutLeng){
446 // 文字列の右側からcutLeng文字分を切り抜く
447 var leng=str.length;
448 return str.substring(leng-cutLeng,leng);
449 }
450 function left(str,cutLeng){
451 // 文字列の左側からcutLeng文字分を切り抜く
452 var leng=str.length;
453 return str.substring(0,cutLeng);
454 }
455 function getById(id){
456 return document.getElementById(id);
457 }
458
459 //ひらがなtoカタカナ変換
460 function hiragana2kanakana(hiragana){
461 var retVal="";
462 for(var i=0;i<hiragana.length;i++){
463 var tmpChar=hiragana.charAt(i);
464 var idx=HIRAGANA_DATA.indexOf(tmpChar);
465 if(idx>=0){
466 retVal+=KATAKANA_DATA.charAt(idx);
467 }else{
468 retVal+=tmpChar;
469 }
470 }
471 return retVal;
472 }