From: handa Date: Fri, 22 Jan 2010 12:49:05 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: before-ns~2 X-Git-Url: http://git.chise.org/gitweb/?p=m17n%2Fm17n-lib-js.git;a=commitdiff_plain;h=22b191eb5daf71f6065ebba18a2436ddd0a9331c *** empty log message *** --- 22b191eb5daf71f6065ebba18a2436ddd0a9331c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..67f3625 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +DIST=/project/web/extra/m17n-lib/mim-js/ +FILES=index.html latn-post.js mim.js th-kesmanee.js + +upload: + for f in ${FILES}; do \ + if [ $$f -nt ${DIST}/$$f ] ; then \ + echo $$f; \ + cp $$f ${DIST}; \ + fi; \ + done + cd /project/web/source/m17n-lib; make diff --git a/index.html b/index.html new file mode 100644 index 0000000..2dc8d9f --- /dev/null +++ b/index.html @@ -0,0 +1,26 @@ + + + + + + M17N Input Method by JavaScript + + + + + + +
+ + + +
downpressstatuskeyseqrange
00
+
+
+
+ diff --git a/latn-post.js b/latn-post.js new file mode 100644 index 0000000..156ad92 --- /dev/null +++ b/latn-post.js @@ -0,0 +1,364 @@ +//alert ("loading... latin-post"); +im = MIM_find ('latin', 'post'); +im.load_mapdef ({ +" _":" ", +"!/":"¡", +"//":"°", +"<<":"«", +">>":"»", +"/":"¿", +"$/":"£", +"$/":"¤", +"A'":"Á", +"A,":"Ą", +"A-":"Ā", +"A/":"Å", +"A\\":"Ä", +"A^":"Â", +"A`":"À", +"A~":"Ã", +"A~":"Ă", +"C'":"Ć", +"C,":"Ç", +"C.":"Ċ", +"C^":"Ĉ", +"C~":"Č", +"D/":"Ð", +"D/":"Đ", +"D~":"Ď", +"E'":"É", +"E,":"Ę", +"E-":"Ē", +"E.":"Ė", +"E/":"Æ", +"E\\":"Ë", +"E^":"Ê", +"E`":"È", +"E~":"Ě", +"G,":"Ģ", +"G.":"Ġ", +"G^":"Ĝ", +"G~":"Ğ", +"H/":"Ħ", +"H^":"Ĥ", +"I'":"Í", +"I,":"Į", +"I-":"Ī", +"I.":"İ", +"I\\":"Ï", +"I^":"Î", +"I`":"Ì", +"I~":"Ĩ", +"J^":"Ĵ", +"K,":"Ķ", +"L'":"Ĺ", +"L,":"Ļ", +"L/":"Ł", +"L~":"Ľ", +"N'":"Ń", +"N,":"Ņ", +"N/":"Ŋ", +"N~":"Ñ", +"N~":"Ň", +"O'":"Ó", +"O-":"Ō", +"O/":"Ø", +"O/":"Œ", +"O:":"Ő", +"O\\":"Ö", +"O^":"Ô", +"O`":"Ò", +"O~":"Õ", +"R'":"Ŕ", +"R,":"Ŗ", +"R~":"Ř", +"S'":"Ś", +"S,":"Ş", +"S^":"Ŝ", +"S~":"Š", +"T,":"Ţ", +"T/":"Þ", +"T/":"Ŧ", +"T~":"Ť", +"U'":"Ú", +"U,":"Ų", +"U-":"Ū", +"U.":"Ů", +"U:":"Ű", +"U\\":"Ü", +"U^":"Û", +"U`":"Ù", +"U~":"Ũ", +"U~":"Ŭ", +"Y'":"Ý", +"Y\\":"Ÿ", +"Y=":"¥", +"Z'":"Ź", +"Z.":"Ż", +"Z~":"Ž", +"a'":"á", +"a,":"ą", +"a-":"ā", +"a/":"å", +"a\\":"ä", +"a^":"â", +"a_":"ª", +"a`":"à", +"a~":"ã", +"a~":"ă", +"c'":"ć", +"c,":"ç", +"c.":"ċ", +"c^":"ĉ", +"c~":"č", +"c/":"¢", +"d/":"ð", +"d/":"đ", +"d~":"ď", +"e'":"é", +"e,":"ę", +"e-":"ē", +"e.":"ė", +"e/":"æ", +"e\\":"ë", +"e^":"ê", +"e`":"è", +"e~":"ě", +"e=":"€", +"g,":"ģ", +"g.":"ġ", +"g^":"ĝ", +"g~":"ğ", +"h/":"ħ", +"h^":"ĥ", +"i'":"í", +"i,":"į", +"i-":"ī", +"i.":"ı", +"i\\":"ï", +"i^":"î", +"i`":"ì", +"i~":"ĩ", +"j^":"ĵ", +"k,":"ķ", +"k/":"ĸ", +"l'":"ĺ", +"l,":"ļ", +"l/":"ł", +"l~":"ľ", +"n'":"ń", +"n,":"ņ", +"n/":"ŋ", +"n~":"ñ", +"n~":"ň", +"o'":"ó", +"o-":"ō", +"o/":"ø", +"o/":"œ", +"o:":"ő", +"o\\":"ö", +"o^":"ô", +"o_":"º", +"o`":"ò", +"o~":"õ", +"r'":"ŕ", +"r,":"ŗ", +"r~":"ř", +"s'":"ś", +"s,":"ş", +"s/":"ß", +"s^":"ŝ", +"s~":"š", +"t,":"ţ", +"t/":"þ", +"t/":"ŧ", +"t~":"ť", +"u'":"ú", +"u,":"ų", +"u-":"ū", +"u.":"ů", +"u:":"ű", +"u\\":"ü", +"u^":"û", +"u`":"ù", +"u~":"ũ", +"u~":"ŭ", +"y'":"ý", +"y\\":"ÿ", +"z'":"ź", +"z.":"ż", +"z~":"ž", +"!//":"!/", +"///":"//", +"<<<":"<<", +">>>":">>", +"?//":"?/", +"$//":"$/", +"A''":"A'", +"A,,":"A,", +"A--":"A-", +"A//":"A/", +"A\\\\":"A\\", +"A^^":"A^", +"A``":"A`", +"A~~":"A~", +"C''":"C'", +"C,,":"C,", +"C..":"C.", +"C^^":"C^", +"C~~":"C~", +"D//":"D/", +"D~~":"D~", +"E''":"E'", +"E,,":"E,", +"E--":"E-", +"E..":"E.", +"E//":"E/", +"E\\\\":"E\\", +"E^^":"E^", +"E``":"E`", +"E~~":"E~", +"G,,":"G,", +"G..":"G.", +"G^^":"G^", +"G~~":"G~", +"H//":"H/", +"H^^":"H^", +"I''":"I'", +"I,,":"I,", +"I--":"I-", +"I..":"I.", +"I\\\\":"I\\", +"I^^":"I^", +"I``":"I`", +"I~~":"I~", +"J^^":"J^", +"K,,":"K,", +"L''":"L'", +"L,,":"L,", +"L//":"L/", +"L~~":"L~", +"N''":"N'", +"N,,":"N,", +"N//":"N/", +"N~~":"N~", +"O''":"O'", +"O--":"O-", +"O//":"O/", +"O::":"O:", +"O\\\\":"O\\", +"O^^":"O^", +"O``":"O`", +"O~~":"O~", +"R''":"R'", +"R,,":"R,", +"R~~":"R~", +"S''":"S'", +"S,,":"S,", +"S^^":"S^", +"S~~":"S~", +"T,,":"T,", +"T//":"T/", +"T~~":"T~", +"U''":"U'", +"U,,":"U,", +"U--":"U-", +"U..":"U.", +"U::":"U:", +"U\\\\":"U\\", +"U^^":"U^", +"U``":"U`", +"U~~":"U~", +"Y''":"Y'", +"Y\\\\":"Y\\", +"Y==":"Y=", +"Z''":"Z'", +"Z..":"Z.", +"Z~~":"Z~", +"a''":"a'", +"a,,":"a,", +"a--":"a-", +"a//":"a/", +"a\\\\":"a\\", +"a^^":"a^", +"a__":"a_", +"a``":"a`", +"a~~":"a~", +"c''":"c'", +"c,,":"c,", +"c..":"c.", +"c^^":"c^", +"c~~":"c~", +"c//":"c/", +"d//":"d/", +"d~~":"d~", +"e''":"e'", +"e,,":"e,", +"e--":"e-", +"e..":"e.", +"e//":"e/", +"e\\\\":"e\\", +"e^^":"e^", +"e``":"e`", +"e==":"e=", +"e~~":"e~", +"g,,":"g,", +"g..":"g.", +"g^^":"g^", +"g~~":"g~", +"h//":"h/", +"h^^":"h^", +"i''":"i'", +"i,,":"i,", +"i--":"i-", +"i..":"i.", +"i\\\\":"i\\", +"i^^":"i^", +"i``":"i`", +"i~~":"i~", +"j^^":"j^", +"k,,":"k,", +"k//":"k/", +"l''":"l'", +"l,,":"l,", +"l//":"l/", +"l~~":"l~", +"n''":"n'", +"n,,":"n,", +"n//":"n/", +"n~~":"n~", +"o''":"o'", +"o--":"o-", +"o//":"o/", +"o::":"o:", +"o\\\\":"o\\", +"o^^":"o^", +"o__":"o_", +"o``":"o`", +"o~~":"o~", +"r''":"r'", +"r,,":"r,", +"r~~":"r~", +"s''":"s'", +"s,,":"s,", +"s//":"s/", +"s^^":"s^", +"s~~":"s~", +"t,,":"t,", +"t//":"t/", +"t~~":"t~", +"u''":"u'", +"u,,":"u,", +"u--":"u-", +"u..":"u.", +"u::":"u:", +"u\\\\":"u\\", +"u^^":"u^", +"u``":"u`", +"u~~":"u~", +"y''":"y'", +"y\\\\":"y\\", +"z''":"z'", +"z..":"z.", +"z~~":"z~", +}); diff --git a/mim.js b/mim.js new file mode 100644 index 0000000..8c7b461 --- /dev/null +++ b/mim.js @@ -0,0 +1,476 @@ +// -* coding: utf-8; -* + +/* URL to scan JavaScript files defining MIM (M17N Input Method). */ +var MIM_url = "http://www.m17n.org/common/mim-js"; + +/* Boolean flag to tell if MIM is active or not. */ +var MIM_enabled = true; + +var MIM_current_im; + +var MIM_list = new Array (); + +function M17N_im (url, lang, name) +{ + this.status = 0; /* 0: not-yet-loaded, 1:loading, 2:loaded, -1:error */ + this.url = url; + this.lang = lang; + this.name = name; + this.keymap = false; + + function add_keystring (map, keystring, str) + { + var i, c; + var newmap; + var intermediate_string = ""; + + for (i = 0; i < keystring.length; i++) + { + c = keystring.charAt (i); + if (c in map) + { + map = map[c]; + if ('_target_text' in map) + intermediate_string = map['_target_text']; + else + intermediate_string += c; + } + else + { + newmap = new Array (); + map[c] = newmap; + map['_has_child'] = true; + map = newmap; + intermediate_string += c; + map['_target_text'] = intermediate_string; + } + } + map['_target_text'] = str; + } + + function lookup_keyseq (keyseq, limit) + { + var map = this.keymap; + + if (limit > keyseq.length) + limit = keyseq.length; + for (var i = 0; i < limit; i++) + { + var c = keyseq[i]; + if (! (c in map)) + return i; + map = map[c]; + } + return map; + } + + function load_map (mapdef) + { + this.keymap = new Array (); + for (var keystring in mapdef) + add_keystring (this.keymap, keystring, mapdef[keystring]); + } + + this.load_mapdef = load_map; + this.lookup = lookup_keyseq; +} + +function MIM_register (url, lang, name) +{ + var im = new M17N_im (url, lang, name); + if (! (lang in MIM_list)) + MIM_list[lang] = new Array (); + MIM_list[lang][name] = im; + return im; +} + +function MIM_find (lang, name) +{ + if (! (lang in MIM_list)) + return false; + if (! (name in MIM_list[lang])) + return false; + return MIM_list[lang][name]; +} + + +function MIM_load_async (im) +{ + var filename = MIM_url + "/" + im.url; + var obj = (window.XMLHttpRequest ? new XMLHttpRequest () + : window.ActiveXObject ? new ActiveXObject ("Msxml2.XMLHTTP") + : null); + + if (! obj) + alert ("XMLHttpRequest not supported"); + alert ("loading " + filename); + obj.open ('GET', filename, true); + im.status = 1; /* loading */ + obj.onreadystatechange = function () { + alert (obj.readyState + ":" + obj.statusText); + if (obj.readyState == 4) + { + try { + eval (obj.responseText); + im.status = 2; /* loaded */ + alert ("loaded:"+obj.responseXML); + } catch (e) { + alert ("load error:" + e.message + " at " + e.lineNumber + + " " + obj.responseText); + im.status = -1; /* load fail */ + } + } + }; + obj.send (null); + return im; +} + +function MIM_load (im) +{ + var filename = MIM_url + "/" + im.url; + var s = document.createElement ('script'); + + s.charset = 'UTF-8'; + s.src = filename; + document.body.appendChild (s); + alert (s.innerText); + //document.body.removeChild (s); + im.status = 2; + return im; +} + +function MIM_add_event_listener (target, type, listener) +{ + if (target.addEventListener) + target.addEventListener (type, listener, false); + else if (target.attachEvent) + target.attachEvent ('on' + type, + function() { listener.call (target, window.event); }); + else + target['on' + type] + = function(e) { listener.call (target, e || window.event); }; +} + +var MIM_key = new Array (); +MIM_key[0x09] = 'tab'; +MIM_key[0x08] = 'backspace'; +MIM_key[0x0D] = 'return'; +MIM_key[0x1B] = 'escape'; +MIM_key[0x20] = 'space'; +MIM_key[0x21] = 'pageup'; +MIM_key[0x22] = 'pagedown'; +MIM_key[0x23] = 'end'; +MIM_key[0x24] = 'home'; +MIM_key[0x25] = 'left'; +MIM_key[0x26] = 'up'; +MIM_key[0x27] = 'right'; +MIM_key[0x28] = 'down'; +MIM_key[0x2D] = 'insert'; +MIM_key[0x2E] = 'delete'; +for (var i = 1; i <= 12; i++) + MIM_key[111 + i] = "f" + i; +MIM_key[0x90] = "numlock"; +MIM_key[0xF0] = "capslock"; + +function MIM_decode_key (event) +{ + var key = (event.keyCode ? event.keyCode + : event.charCode ? event.charCode + : false); + if (! key) + return false; + if (event.type == 'keydown') + { + key = MIM_key[key]; + if (! key) + return false; + if (event.shiftKey) key = "S-" + key ; + } + else + key = String.fromCharCode (key); + if (event.altKey) key = "A-" + key ; + if (event.ctrlKey) key = "C-" + key ; + return key; +} + +function debug_print (event, ic) +{ + var target = event.target; + var code = event.keyCode; + var char = event.charCode; + var key = MIM_decode_key (event); + + document.getElementById (event.type).innerHTML = "" + code + "/" + char + " : " + key; + document.getElementById ('status').innerHTML = ic.im.status; + var keyseq = ""; + for (var i = 0; i < ic.keyseq.length; i++) + keyseq += ic.keyseq[i]; + document.getElementById ('keyseq').innerHTML = keyseq + ":" + ic.keyseq.length; + document.getElementById ('range').innerHTML = "" + ic.range[0] + "," + ic.range[1];; +} + +function MIM_get_range (target, range) +{ + if (target.selectionStart != null) + { + // for Mozilla + range[0] = target.selectionStart; + range[1] = target.selectionEnd; + return true; + } + if (document.selection != null) + { + target.focus(); + + var range = document.selection.createRange (); + var bookmark = range.getBookmark (); + var value = target.value; + var saved_value = value; + var marker = "_#_MARKER_#_"; + while (value.indexOf (marker) != -1) + marker += "#_"; + var parent = range.parentElement (); + if (parent == null || parent.type != "textarea") + { + range[0] = range[1] = 0; + } + else + { + range.text = marker + range.text + marker; + contents = this.element.value; + range[0] = contents.indexOf (marker); + contents = contents.replace(marker, ""); + range[1] = contents.indexOf(marker); + target.value = originalContents; + range.moveToBookmark (bookmark); + range.select (); + } + return true; + } + return false; +} + +function MIM_set_caret (target, pos) +{ + if (target.selectionStart != null) + { + // Mozilla + target.focus (); + target.setSelectionRange (pos, pos); + return true; + } + if (target.createTextRange != null) + { + // IE + var range = target.createTextRange (); + range.move ('character', pos); + ranges.elect (); + return true; + } + // Unknown + target.focus (); + return false; +} + +function MIM_ic (im, target) +{ + this.im = im; + this.target = target; + this.key = false; + this.keyseq = new Array (); + this.range = new Array (-1, -1); + return this; +} + +MIM_ic.prototype.reset = function () +{ + this.key = false; + while (this.keyseq.length > 0) + this.keyseq.pop (); + this.range[0] = this.range[1] = -1; +} + +MIM_ic.prototype.check_caret = function () +{ + var from = this.range[0]; + var to = this.range[1]; + + MIM_get_range (this.target, this.range); + if (from >= 0) + { + if (this.range[0] != this.range[1] || to != this.range[0]) + this.reset (); + else + this.range[0] = from; + } +} + +function MIM_insert (ic, insert) +{ + var text = ic.target.value; + ic.target.value = (text.substring (0, ic.range[0]) + + insert + + text.substring (ic.range[1])); + ic.range[1] = ic.range[0] + insert.length; + MIM_set_caret (ic.target, ic.range[1]); +} + +function keyseq_string (keyseq) +{ + var str = ""; + for (var i = 0; i < keyseq.length; i++) + str += keyseq[i]; + return str; +} + +function MIM_handle_keyseq (event, ic) +{ + var map = ic.im.lookup (ic.keyseq, 1000); + if (map instanceof Array) + { + MIM_insert (ic, map['_target_text']); + if (! ('_has_child' in map)) + ic.reset (); + event.preventDefault (); + //document.getElementById ('text').value + //= keyseq_string (ic.keyseq) + " handled"; + } + else if (map > 0) + { + MIM_insert (ic, ic.im.lookup (ic.keyseq, map)['_target_text']); + while (map > 0) + { + ic.keyseq.shift (); + map--; + } + ic.range[0] = ic.range[1]; + if (ic.keyseq.length > 0) + MIM_handle_keyseq (event, ic); + } + else + { + ic.reset (); + document.getElementById ('text').value + = keyseq_string (ic.keyseq) + " unhandled"; + } +} + +function MIM_reset_ic (event) +{ + var ic = event.target.mim_ic; + if (ic) + ic.reset (); +} + +function MIM_keydown (event) +{ + if (! (event.target.type == "text" || event.target.type == "textarea")) + return; + + var ic = event.target.mim_ic; + if (! ic || ic.im != MIM_current_im) + { + ic = new MIM_ic (MIM_current_im, event.target); + event.target.mim_ic = ic; + } + MIM_add_event_listener (event.target, 'blur', MIM_reset_ic); + //debug_print (event, ic); + if (ic.im.status < 0) + return; + ic.check_caret (); + ic.key = MIM_decode_key (event); +} + +function MIM_keypress (event) +{ + if (! (event.target.type == "text" || event.target.type == "textarea")) + return; + + var ic = event.target.mim_ic; + var i; + + //debug_print (event, ic); + if (ic.im.status < 0) + return; + if (! ic.key) + ic.key = MIM_decode_key (event); + if (! ic.key) + { + ic.reset (); + return; + } + ic.keyseq.push (ic.key); + if (ic.im.status == 1) // Still loading. + return; + MIM_handle_keyseq (event, ic); + return; +} + +function MIM_select_im (event) +{ + var target = event.target.parentNode; + while (target.tagName != "SELECT") + target = target.parentNode; + var idx = 0; + var im = false; + for (var lang in MIM_list) + for (var name in MIM_list[lang]) + if (idx++ == target.selectedIndex) + { + im = MIM_list[lang][name]; + break; + } + document.getElementsByTagName ('body')[0].removeChild (target); + target.target.focus (); + if (im && im != MIM_current_im) + MIM_current_im = MIM_load (im); +} + +function MIM_destroy_menu (event) +{ + if (event.target.tagName == "SELECT") + document.getElementsByTagName ('body')[0].removeChild (event.target); +} + +function MIM_select_menu (event) +{ + var target = event.target; + + if (! ((target.type == "text" || target.type == "textarea") + && event.which == 1 && event.ctrlKey)) + return; + + var sel = document.createElement ('select'); + sel.onclick = MIM_select_im; + sel.onmouseout = MIM_destroy_menu; + sel.style.position='absolute'; + sel.style.left = (event.clientX - 10) + "px"; + sel.style.top = (event.clientY - 10) + "px"; + sel.target = target; + var idx = 0; + for (var lang in MIM_list) + for (var name in MIM_list[lang]) + { + var option = document.createElement ('option'); + var imname = lang + "-" + name; + option.appendChild (document.createTextNode (imname)); + option.value = imname; + sel.appendChild (option); + if (MIM_list[lang][name] == MIM_current_im) + sel.selectedIndex = idx; + idx++; + } + sel.size = idx; + document.getElementsByTagName ('body')[0].appendChild (sel); +} + +MIM_current_im = MIM_register ('latn-post.js', 'latin', 'post'); +MIM_register ('th-kesmanee.js', 'th', 'kesmanee'); + +function MIM_init () +{ + MIM_add_event_listener (window, 'keydown', MIM_keydown); + MIM_add_event_listener (window, 'keypress', MIM_keypress); + MIM_add_event_listener (window, 'mousedown', MIM_select_menu); + MIM_load (MIM_current_im); +} diff --git a/th-kesmanee.js b/th-kesmanee.js new file mode 100644 index 0000000..050aa17 --- /dev/null +++ b/th-kesmanee.js @@ -0,0 +1,97 @@ +im = MIM_find ('th', 'kesmanee'); +im.load_mapdef ({ +"!":"+", +"\"":".", +"#":"๒", +"$":"๓", +"%":"๔", +"&":"฿", +"'":"ง", +"(":"๖", +")":"๗", +"*":"๕", +"+":"๙", +",":"ม", +"-":"ข", +".":"ใ", +"/":"ฝ", +"0":"จ", +"1":"ๅ", +"2":"/", +"3":"-", +"4":"ภ", +"5":"ถ", +"6":"ุ", +"7":"ึ", +"8":"ค", +"9":"ต", +":":"ซ", +";":"ว", +"<":"ฒ", +"=":"ช", +">":"ฬ", +"?":"ฦ", +"@":"๑", +"A":"ฤ", +"B":"ฺ", +"C":"ฉ", +"D":"ฏ", +"E":"ฎ", +"F":"โ", +"G":"ฌ", +"H":"็", +"I":"ณ", +"J":"๋", +"K":"ษ", +"L":"ศ", +"M":"?", +"N":"์", +"O":"ฯ", +"P":"ญ", +"Q":"๐", +"R":"ฑ", +"S":"ฆ", +"T":"ธ", +"U":"๊", +"V":"ฮ", +"W":"\"", +"X":")", +"Y":"ํ", +"Z":"(", +"[":"บ", +"\\":"ฃ", +"]":"ล", +"^":"ู", +"_":"๘", +"`":"_", +"a":"ฟ", +"b":"ิ", +"c":"แ", +"d":"ก", +"e":"ำ", +"f":"ด", +"g":"เ", +"h":"้", +"i":"ร", +"j":"่", +"k":"า", +"l":"ส", +"m":"ท", +"n":"ื", +"o":"น", +"p":"ย", +"q":"ๆ", +"r":"พ", +"s":"ห", +"t":"ะ", +"u":"ี", +"v":"อ", +"w":"ไ", +"x":"ป", +"y":"ั", +"z":"ผ", +"{":"ฐ", +"|":"ฅ", +"}":",", +"~":"%" +});