// -* coding: utf-8; -*
-var MIM = function ()
+var MIM = {};
+
+// URL of the input method server.
+MIM.server = "http://www.m17n.org/common/mim-js",
+// Boolean flag to tell if MIM is active or not.
+MIM.enabled = true;
+// Boolean flag to tell if MIM is running in debug mode or not.
+MIM.debug = false;
+// List of registered input methods.
+MIM.list = new Array ();
+// Currently selected input method.
+MIM.current_im = false;
+
+MIM.im = function (lang, name, filename)
{
- var server = "http://www.m17n.org/common/mim-js",
- /* Boolean flag to tell if MIM is active or not. */
- var enabled = true;
- /* Boolean flag to tell if MIM is running in debug mode or not. */
- var debug = false;
- var current_im = false;
-
- function im (lang, name, filename)
+ this.status = 0; /* 0: not-yet-loaded, 1:loading, 2:loaded, -1:error */
+ this.url = MIM.server + "/" + filename;
+ this.lang = lang;
+ this.name = name;
+ this.keymap = false;
+ this.body = null;
+
+ function add_keystring (map, keystring, str)
{
- this.status = 0; /* 0: not-yet-loaded, 1:loading, 2:loaded, -1:error */
- this.url = server + "/" + filename;
- this.lang = lang;
- this.name = name;
- this.keymap = false;
+ var i, c;
+ var newmap;
+ var intermediate_string = "";
- function add_keystring (map, keystring, str)
+ for (i = 0; i < keystring.length; i++)
{
- 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;
+ 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;
- map['_target_text'] = intermediate_string;
- }
- }
- map['_target_text'] = str;
+ }
+ 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;
+ this.lookup = function (keyseq, limit)
+ {
+ var map = this.keymap;
- if (limit > keyseq.length)
- limit = keyseq.length;
- for (var i = 0; i < limit; i++)
+ 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;
+ return map;
+ }
+
+ this.load_map = function (mapdef)
+ {
+ this.keymap = new Array ();
+ for (var keystring in mapdef)
+ add_keystring (this.keymap, keystring, mapdef[keystring]);
+ }
+};
+
+MIM.error_return = function (msg, ret)
+{
+ alert (msg);
+ return ret;
+}
+
+MIM.first_element = function (node)
+{
+ node.mim_index = 0;
+ return MIM.next_element (node);
+}
+
+MIM.next_element = function (node)
+{
+ var element = node.childNodes[node.mim_index++];
+ while (element && element.nodeType != 1)
+ element = node.childNodes[node.mim_index++];
+ return element;
+}
+
+MIM.check_map = function (im, map)
+{
+ var rules = map.getElementsByTagName ('rule');
+ var len = rules.length;
+
+ for (var i = 0; i < len; i++)
+ {
+ var rule = rules[i];
+ var elm = MIM.first_element (rule);
+
+ if (!elm || elm.nodeName != 'keyseq')
+ return false;
+ while ((elm = MIM.next_element (rule)))
+ if (elm.nodeName != 'insert')
+ return false;
}
+ return true;
+}
- function load_map (mapdef)
+MIM.check_state = function (im, state)
+{
+ var branches = state.getElementsByTagName ('branch');
+ var len = branches.length;
+
+ for (var i = 0; i < len; i++)
{
- this.keymap = new Array ();
- for (var keystring in mapdef)
- add_keystring (this.keymap, keystring, mapdef[keystring]);
+ var branch = branches[i];
+ var elm = MIM.first_element (branch);
+
+ if (elm)
+ return false;
}
+ return true;
+}
- this.load_mapdef = load_map;
- this.lookup = lookup_keyseq;
- }
+MIM.parse = function (im)
+{
+ var maps = im.body.getElementsByTagName ('map');
+ var states = im.body.getElementsByTagName ('state');
+ var str = "";
+ var i;
- return { }
-} ();
+ if (! maps || maps.length == 0)
+ MIM.error_return ('No map', false);
+ if (! states)
+ MIM.error_return ('No state', false);
+ for (i = 0; i < maps.length; i++)
+ if (! MIM.check_map (im, maps[i]))
+ MIM.error_return ('Unsupported directive in map', false);
+ for (var i = 0; i < states.length; i++)
+ if (! MIM.check_state (im, states[i]))
+ MIM.error_return ('Unsupported directive in state', false);
+ return true;
+}
-function MIM_register (url, lang, name)
+MIM.register = function (lang, name, url)
{
- var im = new M17N_im (url, lang, name);
- if (! (lang in MIM_list))
- MIM_list[lang] = new Array ();
- MIM_list[lang][name] = im;
+ var im = new MIM.im (lang, name, url);
+ if (! (lang in MIM.list))
+ MIM.list[lang] = new Array ();
+ MIM.list[lang][name] = im;
return im;
-}
+};
-function MIM_find (lang, name)
+MIM.find = function (lang, name)
{
- if (! (lang in MIM_list))
+ if (! (lang in MIM.list))
return false;
- if (! (name in MIM_list[lang]))
+ if (! (name in MIM.list[lang]))
return false;
- return MIM_list[lang][name];
-}
-
+ return MIM.list[lang][name];
+};
-function MIM_load_async (im)
+MIM.load_async = function (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);
+ obj.open ('GET', im.url, 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);
};
obj.send (null);
return im;
-}
+};
-function MIM_load (im)
+MIM.load_sync = function (im)
+{
+ var obj = (window.XMLHttpRequest ? new XMLHttpRequest ()
+ : window.ActiveXObject ? new ActiveXObject ("Msxml2.XMLHTTP")
+ : null);
+
+ if (! obj)
+ alert ("XMLHttpRequest not supported");
+ if (true)
+ {
+ obj.open ('GET', im.url, false);
+ im.status = 1; /* loading */
+ obj.send ("");
+ try {
+ eval (obj.responseText);
+ im.status = 2; /* loaded */
+ } catch (e) {
+ alert ("load error:" + e.message + " at " + e.lineNumber
+ + " " + obj.responseText);
+ im.status = -1; /* load fail */
+ };
+ }
+
+ if (true) {
+ obj.open ('GET', 'latn-post.mimx', false);
+ obj.overrideMimeType ('text/xml');
+ obj.send ("");
+ im.body = obj.responseXML;
+ document.AnXml = im.body;
+ if (! MIM.parse (im))
+ {
+ alert (im.parse_error);
+ return false;
+ }
+ } else {
+ var doc = document.implementation.createDocument ("", "", null);
+ doc.async = false;
+ doc.contentType = "text/xml";
+ doc.load ('latn-post.mimx');
+ document.AnXml = doc;
+ im.body = doc;
+ MIM.parse (im);
+ }
+ return im;
+};
+
+MIM.load = function (im)
{
- var filename = MIM_url + "/" + im.url;
var s = document.createElement ('script');
s.charset = 'UTF-8';
- s.src = filename;
+ s.src = im.url;
document.body.appendChild (s);
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)
+};
+
+MIM.add_event_listener
+ = (window.addEventListener
+ ? function (target, type, listener) {
+ target.addEventListener (type, listener, false);
+ }
+ : window.attachEvent
+ ? function (target, type, listener) {
+ target.attachEvent ('on' + type,
+ function() {
+ listener.call (target, window.event);
+ });
+ }
+ : function (target, type, listener) {
+ target['on' + type]
+ = function (e) { listener.call (target, e || window.event); };
+ });
+
+(function () {
+ var keys = new Array ();
+ keys[0x09] = 'tab';
+ keys[0x08] = 'backspace';
+ keys[0x0D] = 'return';
+ keys[0x1B] = 'escape';
+ keys[0x20] = 'space';
+ keys[0x21] = 'pageup';
+ keys[0x22] = 'pagedown';
+ keys[0x23] = 'end';
+ keys[0x24] = 'home';
+ keys[0x25] = 'left';
+ keys[0x26] = 'up';
+ keys[0x27] = 'right';
+ keys[0x28] = 'down';
+ keys[0x2D] = 'insert';
+ keys[0x2E] = 'delete';
+ for (var i = 1; i <= 12; i++)
+ keys[111 + i] = "f" + i;
+ keys[0x90] = "numlock";
+ keys[0xF0] = "capslock";
+ MIM.special_key = keys;
+}) ();
+
+MIM.decode_key = function (event)
{
var key = ((event.type == 'keydown' || event.keyCode) ? event.keyCode
: event.charCode ? event.charCode
return false;
if (event.type == 'keydown')
{
- key = MIM_key[key];
+ key = MIM.special_key[key];
if (! key)
return false;
if (event.shiftKey) key = "S-" + key ;
if (event.altKey) key = "A-" + key ;
if (event.ctrlKey) key = "C-" + key ;
return key;
-}
+};
-function debug_print (event, ic)
+MIM.debug_print = function (event, ic)
{
- if (! MIM_debug)
+ if (! MIM.debug)
return;
+ if (! MIM.debug_nodes)
+ {
+ MIM.debug_nodes = new Array ();
+ MIM.debug_nodes['status'] = document.getElementById ('status');
+ MIM.debug_nodes['range'] = document.getElementById ('range');
+ MIM.debug_nodes['keydown'] = document.getElementById ('keydown');
+ MIM.debug_nodes['keypress'] = document.getElementById ('keypress');
+ MIM.debug_nodes['keyseq'] = document.getElementById ('keyseq');
+ }
var target = event.target;
var code = event.keyCode;
- var ch = event.type == 'keydown' ? "-none-" : event.charCode;
- var key = MIM_decode_key (event);
-
- document.getElementById (event.type).innerHTML = "" + code + "/" + ch + " : " + key;
- document.getElementById ('status').innerHTML = ic.im.status;
+ var ch = event.type == 'keydown' ? 0 : event.charCode;
+ var key = MIM.decode_key (event);
var keyseq = "";
+
+ MIM.debug_nodes[event.type].innerHTML = "" + code + "/" + ch + " : " + key;
+ MIM.debug_nodes['status'].innerHTML = ic.im.status;
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];;
-}
+ MIM.debug_nodes['keyseq'].innerHTML = keyseq + ":" + ic.keyseq.length;
+ MIM.debug_nodes['range'].innerHTML = "" + ic.range[0] + "," + ic.range[1];;
+};
-function MIM_get_range (target, range)
+MIM.get_range = function (target, range)
{
if (target.selectionStart != null)
{
return true;
}
return false;
-}
+};
-function MIM_set_caret (target, pos)
+MIM.set_caret = function (target, pos)
{
- if (target.selectionStart != null)
+ if(/*@cc_on ! @*/ false) // IE
{
- // 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;
}
+ if (target.selectionStart != null) // Mozilla
+ {
+ target.focus ();
+ target.setSelectionRange (pos, pos);
+ return true;
+ }
// Unknown
target.focus ();
return false;
-}
+};
-function MIM_ic (im, target)
+MIM.ic = function (im, target)
{
this.im = im;
this.target = target;
this.keyseq = new Array ();
this.range = new Array (-1, -1);
return this;
-}
+};
-MIM_ic.prototype.reset = function ()
+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 ()
+MIM.ic.prototype.check_caret = function ()
{
var from = this.range[0];
var to = this.range[1];
- MIM_get_range (this.target, this.range);
+ MIM.get_range (this.target, this.range);
if (from >= 0)
{
if (this.range[0] != this.range[1] || to != this.range[0])
else
this.range[0] = from;
}
-}
+};
-function MIM_insert (ic, insert)
+MIM.insert = function (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]);
-}
+ MIM.set_caret (ic.target, ic.range[1]);
+};
function keyseq_string (keyseq)
{
return str;
}
-function MIM_handle_keyseq (event, ic)
+MIM.handle_keyseq = function (event, ic)
{
var map = ic.im.lookup (ic.keyseq, 1000);
if (map instanceof Array)
{
- MIM_insert (ic, map['_target_text']);
+ MIM.insert (ic, map['_target_text']);
if (! ('_has_child' in map))
ic.reset ();
event.preventDefault ();
}
else if (map > 0)
{
- MIM_insert (ic, ic.im.lookup (ic.keyseq, map)['_target_text']);
+ MIM.insert (ic, ic.im.lookup (ic.keyseq, map)['_target_text']);
while (map > 0)
{
ic.keyseq.shift ();
}
ic.range[0] = ic.range[1];
if (ic.keyseq.length > 0)
- MIM_handle_keyseq (event, ic);
+ MIM.handle_keyseq (event, ic);
}
else
{
//document.getElementById ('text').value
//= keyseq_string (ic.keyseq) + " unhandled";
}
-}
+};
-function MIM_reset_ic (event)
+MIM.reset_ic = function (event)
{
var ic = event.target.mim_ic;
if (ic)
ic.reset ();
-}
+};
-function MIM_keydown (event)
+MIM.keydown = function (event)
{
if (! (event.target.type == "text" || event.target.type == "textarea"))
return;
var ic = event.target.mim_ic;
- if (! ic || ic.im != MIM_current_im)
+ if (! ic || ic.im != MIM.current_im)
{
- ic = new MIM_ic (MIM_current_im, event.target);
+ 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);
+ MIM.add_event_listener (event.target, 'blur', MIM.reset_ic);
+ MIM.debug_print (event, ic);
if (ic.im.status < 0)
return;
ic.check_caret ();
- ic.key = MIM_decode_key (event);
-}
+ ic.key = MIM.decode_key (event);
+};
-function MIM_keypress (event)
+MIM.keypress = function (event)
{
if (! (event.target.type == "text" || event.target.type == "textarea"))
return;
var ic = event.target.mim_ic;
var i;
- debug_print (event, ic);
+ MIM.debug_print (event, ic);
if (ic.im.status < 0)
return;
if (! ic.key)
- ic.key = MIM_decode_key (event);
+ ic.key = MIM.decode_key (event);
if (! ic.key)
{
ic.reset ();
ic.keyseq.push (ic.key);
if (ic.im.status == 1) // Still loading.
return;
- MIM_handle_keyseq (event, ic);
+ MIM.handle_keyseq (event, ic);
return;
-}
+};
-function MIM_select_im (event)
+MIM.select_im = function (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])
+ for (var lang in MIM.list)
+ for (var name in MIM.list[lang])
if (idx++ == target.selectedIndex)
{
- im = MIM_list[lang][name];
+ 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);
-}
+ if (im && im != MIM.current_im)
+ MIM.current_im = MIM.load (im);
+};
-function MIM_destroy_menu (event)
+MIM.destroy_menu = function (event)
{
if (event.target.tagName == "SELECT")
document.getElementsByTagName ('body')[0].removeChild (event.target);
-}
+};
-function MIM_select_menu (event)
+MIM.select_menu = function (event)
{
var target = event.target;
return;
var sel = document.createElement ('select');
- sel.onclick = MIM_select_im;
- sel.onmouseout = MIM_destroy_menu;
+ 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])
+ 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)
+ 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.init = function ()
{
- 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.add_event_listener (window, 'keydown', MIM.keydown);
+ MIM.add_event_listener (window, 'keypress', MIM.keypress);
+ MIM.add_event_listener (window, 'mousedown', MIM.select_menu);
if (window.location == 'http://localhost/mim/index.html')
- MIM_url = 'http://localhost/mim';
- MIM_load (MIM_current_im);
-}
+ MIM.server = 'http://localhost/mim';
+ MIM.current_im = MIM.register ('latin', 'post', 'latn-post.js');
+ MIM.register ('th', 'kesmanee', 'th-kesmanee.js');
+ MIM.load_sync (MIM.current_im);
+};
-function MIM_init_debug ()
+MIM.init_debug = function ()
{
- MIM_debug = true;
- MIM_init ();
-}
+ MIM.debug = true;
+ MIM.init ();
+};