--- /dev/null
+// -* 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);
+}