/* 
 * jKeyboard for iPhone
 * 
 * Copyright (c) 2007 Naoki Hiroshima
 * You can redistribute it and/or modify it under the same terms as GPL2.
 *
 * Author:: Naoki Hiroshima <n at h7a dot org>
 *
 * 2007-07-07
 *      -  ver 1.0 Release.
 *
 * 2007-07-07
 *      - separated keyboard type and translation mode.
 *      - made key top context aware.
 *      - added user event handler.
 *      - clean up.
 *      - ver 1.1 Release.
 *
 * 2007-07-08
 *      - got rid of prototype.js dependency
 *
 * 2007-07-09
 *      - improved performance
 *      - spelling check
 *
 * 2007-07-10
 *      - made to "candidates" element to list candidates.
 *      - made to pick the candidate by tapping the one rather than
 *        by hitting Space many times.
 *      - supporting single/multi line mode.
 *      - supporting textarea switching.
 *      - clean up.
 *      - ver 1.2 Release.
 *
 * 2007-07-11
 *      - made keys to display target type/mode rather than current one.
 *      - revised key availability and location.
 *      - seprated keyboard type and shift status.
 *      - decided to leave Submit functionality to user of this class.
 *      - made not to initiate Ajax while key is being hit.
 *
 * 2007-07-12
 *      - added status line for current mode and version number.
 *      - renamed to jKeyboard (was JKeyboard).
 *
 * 2007-07-14
 *      - clean up.
 *      - ver 1.3 Release.
 *
 * 2007-07-17
 *      - brushed up with nicer looking graphics by Suguru.
 *      - got rid of XMLHttpRequest.
 *
 * 2007-07-19 
 *      - lots of minor improvement. 
 *      - ver 1.4 Release. 
 *
 * 2007-07-20
 *      - made Enter key show what it will do.
 *      - clean up css.
 *      - added INPUT/TEXTAREA support.
 *      - implemented embedded-jKeyboard.
 *
 * 2007-07-22
 *      - fixed some of minor bugs.
 *      - ver 1.5 Release. 
 */ 

jKeyboard = function() {
  this.initialize.apply(this, arguments);
}
jKeyboard.embedded = false;

jKeyboard.prototype = {
  initialize: function(options) {
    this.options = {
      kserver:  'http://n.h7a.org/iphone/kserver',
      eserver:  'http://n.h7a.org/iphone/eserver',
      ajaxdelay: 500,
      onClick: function(span) { return true; },
      multiline: true,
      textarea: 'jtextarea',
      keyboard: 'jkeyboard',
      candidates: 'jcandidates',
      prompt: '_'
    }

    for (var i in (options || {})) {
      this.options[i] = options[i];
    }

    this.mode = 'hiragana';
    this.type = 'alphabet';
    this.shift = false;
    this.text = '';
    this.texts = [];
    this.e = {};
    this.clearBuffer();
    this.callbackNum = 0;

    this.eTextarea = document.getElementById(this.options.textarea);
    this.eKeyboard = document.getElementById(this.options.keyboard);
    this.eCandidates = document.getElementById(this.options.candidates);

    switch (this.eTextarea.tagName) {
    case 'INPUT':
      this.options.multiline = false;

    case 'TEXTAREA':
      this.native_input = true;
      this.text = this.eTextarea.value;
      break;
    }

    if ((this.eTextarea != null) && (this.eKeyboard != null)) {
      this.createKeyboard();
      setTimeout(this.updateTextarea.bind(this), 100);
    }
  },

  emptyFunction: function() { return true; },

  dispatchEvent: function(eventName, arg) {
    return (this.options['on' + eventName] || this.emptyFunction)(arg);
  },

  startOver: function() {
        this.clearBuffer();
        this.clearText();
  },

  clearBuffer: function() {
    this.tbd = '';
    this.tbdraw = '';
    this.candidates = '';
    this.changeKeys({'Enter': 'return'});
  },

  clearText: function() {
    this.text = '';
    this.texts = new Array();
    this.clearBuffer();
    this.updateTextarea();
  },

  getText: function(id) {
        if (id == null || id == this.options.textarea) {
            return this.text + this.tbd;
        } else {
            return this.texts[id];
        }
  },

  setTextarea: function(textarea, multiline) {
    if (textarea == this.options.textarea) return;

    this.text += this.tbd;
    this.clearBuffer();
    this.updateTextarea(true); // no cursor

    this.texts[this.options.textarea] = this.text; // save
    this.text = this.texts[textarea]; // restore
    if (this.text == null) this.text = '';

    this.options.textarea = textarea;
    this.options.multiline = multiline;

    this.eTextarea = document.getElementById(this.options.textarea);
    this.updateTextarea();
  },

  /*
   * Textarea/Candidates Control Functions
   */
  updateTextarea: function() {
    if (this.native_input) {
      this.eTextarea.value = this.text;
    } else {
      this.eTextarea.innerHTML = this.text.replace(/[\n]/g, '<br />');
    }
    this.eCandidates.innerHTML = '';

    switch (this.mode) {
    case 'katakana':
      this.updateKatakana();
      break;

    case 'hiragana':
      this.updateHiragana();
      break;

    default:
      this.updateAlphanum();
      break;
    }

    if (this.native_input) return;

    var t = this.eTextarea;
    if (t.childNodes.length == 0) {
      t.appendChild(document.createTextNode(this.options.prompt));

    } else if (this.tbd.length == 0) {
      if (!arguments[0]) {
         t.appendChild(document.createTextNode('_'));
      }
    }
  },

  updateKatakana: function(pre) {
    if (!this.tbdraw.length) return;

    var s = this.tbdraw; //.toLowerCase();
    this.tbd = roma2['katakana'](s).toString();
    this.candidates = [ this.tbd ];

    this.appendTBD('jkbd-word-tbd');
    this.listCandidates();
  },

  updateHiragana: function(pre) {
    if (!this.tbdraw.length) return;

    var s = this.tbdraw; //.toLowerCase();
    this.tbd = roma2['hiragana'](s).toString();

    if (this.candidates.length) {
      this.listCandidates();
    } else {
      this.ajaxKserver(this.tbd);
    }

    this.appendTBD('jkbd-word-tbd');
  },

  updateAlphanum: function() {
    if (!this.tbdraw.length) return;

    this.tbd = this.tbdraw;

    if (this.candidates.length) {
      if (this.candidates[0] == '?') {
	this.appendTBD('jkbd-word-unknown');
      } else {
	this.appendTBD('jkbd-word-tbd');
	this.listCandidates();
      }
    } else {
      this.ajaxEserver(this.tbd);
      this.appendTBD('jkbd-word-tbd');
    }
  },

  appendTBD: function(attr) {
    if (this.native_input) {
      this.eTextarea.value += '[' + this.tbd + ']';
      return;
    }
    var df = document.createDocumentFragment();
    var span = document.createElement('span');
    span.setAttribute('class', attr);
    span.appendChild(document.createTextNode(this.tbd));
    df.appendChild(span);
    df.appendChild(document.createTextNode('_ '));
    this.eTextarea.appendChild(df);
  },

  listCandidates: function() {
    var c = document.createDocumentFragment();

    for (var i=0; i<this.candidates.length; i++) {
      if (i) c.appendChild(document.createTextNode(' '));

      var span = document.createElement('span');
      span.setAttribute('class', 'jkbd-candidate');
      span.onclick = (function(t,s, k) {
        return function(){ t.onClickCandidate(s, k); }
      })(this, span, this.candidates[i]);
      span.appendChild(document.createTextNode(this.candidates[i]));
      c.appendChild(span);
    }

    this.eCandidates.appendChild(c);
  },

  /*
   * AJAX related
   */
  callJSONP: function(url) {
    this.callbackNum++;
    jKeyboard['callback' + this.callbackNum] = function(json) {
      this.receiveJSON(json);
    }.bind(this);

    try {
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.charset = 'UTF-8';
      script.src = url + '&callback=jKeyboard.callback' + this.callbackNum;
      document.getElementsByTagName('head')[0].appendChild(script);
    } catch(e) {
      this.dispatchEvent('Exception', e);
    }
  },

  ajaxKserver: function(word) {
    setTimeout((function() {
      if (this.tbd == word) {
        var url = this.options.kserver + '?q=' + word;
        this.callJSONP(url);
      }
    }).bind(this), this.options.ajaxdelay);
  },

  ajaxEserver: function(word) {
    if (word.length < 2) return;
    setTimeout((function() {
      if (this.tbd == word) {
        var url = this.options.eserver + '?q=' + word;
        this.callJSONP(url);
      }
    }).bind(this), this.options.ajaxdelay);
  },

  receiveJSON: function(r) {
    if (typeof r['kserver'] == 'object') {
      if (r['kserver'][this.tbd]) {
        this.candidates = r['kserver'][this.tbd];
        //this.candidates[this.candidates.length] = [this.tbd];
        this.updateTextarea();
      }
    } if (typeof r['eserver'] == 'object') {
      if (r['eserver'][this.tbd]) {
        this.candidates = r['eserver'][this.tbd];
        this.updateTextarea();
      }
    }
  },

  /*
   * Keyboard Event Handlers
   */
  onClick: function(span, key, type) {
    this['onClick'+ type](key);
    if (type == 'Regular') {
      this.dispatchEvent('Click', span);
    }
  },

  onClickCandidate: function(s, k) {
    this.clearBuffer();
    this.text += k;
    if (this.mode == 'alphanum') {
      this.text += ' ';
    }
    this.updateTextarea();
  },

  modeText: {'hiragana':'かな', 'katakana':'カナ', 'alphanum':'英数'},
  nextMode: {'hiragana':'katakana', 'katakana':'alphanum', 'alphanum':'hiragana'},
  nextType: {'alphabet':'number', 'number':'alphabet'},

  onClickMode: function() {
    this.mode = this.nextMode[this.mode];
    this.e['mode'].innerHTML = this.modeText[this.mode];
    this.tbd = '';
    this.candidates = '';
    this.createKeyboard();
    this.updateTextarea();
  },

  onClickType: function() {
    this.type = this.nextType[this.type];
    this.createKeyboard();
    this.updateTextarea();
  },

  onClickShiftOn: function() {
    this.shift = false;
    this.createKeyboard();
    this.updateTextarea();
  },

  onClickShiftOff: function() {
    this.shift = true;
    this.createKeyboard();
    this.updateTextarea();
  },

  onClickEnter: function() {
    if (this.tbd.length > 0) {
      this.text += this.tbd;
      this.clearBuffer();
      if (this.mode == 'alphanum') {
	if (this.options.multiline) this.text += "\n";
      }
    } else {
      if (this.options.multiline) this.text += "\n";
    }

    this.updateTextarea();
    this.dispatchEvent('Enter', this.text);
  },

  onClickBackspace: function() {
    if (this.tbdraw.length > 0) {
      this.tbdraw = this.tbdraw.substr(0, this.tbdraw.length-1);
      this.candidates = ''; // will initiate Ajax
    } else if (this.text.length > 0) {
      this.text = this.text.substr(0, this.text.length-1);
    }

    this.updateTextarea();
    this.dispatchEvent('Backspace', this.text);
  },

  onClickRegular: function (k) {
    if (k && this.native_input && !this.tbdraw.length) {
        this.text = this.eTextarea.value;
    }

    switch (this.mode) {
    case 'hiragana':
      this.tbdraw += k;
      this.candidates = ''; // will initiate Ajax
      if (this.tbdraw.length) this.changeKeys({'Enter': '確定'});
      break;

    case 'katakana':
      this.tbdraw += k;
      if (this.tbdraw.length) this.changeKeys({'Enter': '確定'});
      break;

    default:
      this.tbdraw += k;
      this.candidates = ''; // will initiate Ajax
      break;
    }

    this.updateTextarea();
  },

  onClickSpace: function() {
    this.text += this.tbd + ' ';
    this.clearBuffer();
    this.onClickRegular('');
  },

  /*
   * Keyboard Control Functions
   */
  createKeyboardStatus: function() {
    var v = document.createElement('span');
    v.innerHTML = '<a href="http://n.h7a.org/iphone/jkeyboard">jKeyboard v1.5</a>';
    v.setAttribute('class', 'jkbd-status-version');

    var m = document.createElement('span');
    m.innerHTML = 'かな';
    m.setAttribute('class', 'jkbd-status-mode');

    var s = document.createElement('div');
    s.setAttribute('class', 'jkbd-status');
    s.appendChild(v);
    s.appendChild(m);

    this.e['mode'] = m;
    this.e['status'] = s;
  },

  createKeyboard: function() {
    var keys = this.makeKeys();
//    var div = document.createElement('div');
    var div = document.createDocumentFragment();

    if (this.e['status'] == null) this.createKeyboardStatus();
    div.appendChild(this.e['status']);

    for (var i=0; i<keys.length; i++) {
      var d = document.createElement('div');
      d.setAttribute('class', 'jkbd-keyline');

      for (var j=0; j<keys[i].length; j++) {
        var span = document.createElement('span');
        var key, txt, type;

        if (typeof keys[i][j] == 'string') {
          key = keys[i][j];
          txt = key;
          type = 'Regular';
          span.id = 'jkey' + type + i + j;
        } else {
          key = keys[i][j][0];
          txt = keys[i][j][1];
          type = key;
          span.id = 'jkey' + type;
	}

        span.setAttribute('class', 'jkbd-key jkbd-key-'+type);
        span.onclick = (function(t,s,k, p) {
          return function(){ t.onClick(s, k, p); }
        })(this, span, key, type);
        span.appendChild(document.createTextNode(txt));
        d.appendChild(span);
      }

      div.appendChild(d);
    }

    while (this.eKeyboard.hasChildNodes()) {
      this.eKeyboard.removeChild(this.eKeyboard.lastChild);
    }

    this.eKeyboard.appendChild(div);
  },

  makeKeys: function() {
    var keys = [];

    switch (this.type) {
    case 'alphabet':
      if  (this.shift) {
        keys[0] = ['Q','W','E','R','T','Y','U','I','O','P'];
        keys[1] = ['A','S','D','F','G','H','J','K','L'];
        keys[2] = [['ShiftOn','　'],'Z','X','C','V','B','N','M',['Backspace','　']];
      } else {
        keys[0] = ['q','w','e','r','t','y','u','i','o','p'];
        keys[1] = ['a','s','d','f','g','h','j','k','l'];
        keys[2] = [['ShiftOff','　'],'z','x','c','v','b','n','m',['Backspace','　']];
      }
      keys[3] = [['Type','123'],['Space','space'], ['Mode', 'かな'], ['Enter', 'return']];
      break;

    case 'number':
    default:
      if (this.shift) {
	keys[0] = ['`','~','!','@','#','$','%','^','&','*'];
	keys[1] = ['\\','|','_',';',':','!','?','\'','"'];
	keys[2] = [['ShiftOn','　'],'「','」','『','』','【','】','※',['Backspace','　']];
      } else {
	keys[0] = ['1','2','3','4','5','6','7','8','9','0'];
	keys[1] = ['(',')','<','>','[',']','{','}','^'];
	keys[2] = [['ShiftOff','　'],'+','-','*','/','=','、','。',['Backspace','　']];
	if (this.mode == 'alphanum') {
	  keys[2][6] = ',';
	  keys[2][7] = '.';
	}
      }
      keys[3] = [['Type','ABC'],['Space','space'], ['Mode', 'かな'], ['Enter', 'return']];
      break;
    }

    switch (this.mode) {
    case 'hiragana':
    case 'katakana':
      if (this.tbdraw.length) keys[3][3][1] = '確定';
      break;
    }

    keys[3][2][1] = this.modeText[this.nextMode[this.mode]];

    return keys;
  },

  changeKeys: function(keys) {
    for (var id in keys) {
      var key = document.getElementById('jkey'+id);
      if (key) {
	key.removeChild(key.firstChild);
	key.appendChild(document.createTextNode(keys[id]));
      }
    }
  }
}

/*
 * Functions from prototype.js by Sam Stephenson
 */
Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

/* 
 * JavaScriptによるローマ字仮名変換ライブラリ by ma.la
 */
var roma2 = {};
roma2.hiragana = function(text){return roma2x(text,"hiragana")}
roma2.katakana = function(text){return roma2x(text,"katakana")}
function roma2x(orig,to){
	var nstr = [];
	var temp,kana;
	var skip = 0;
    var text = orig.toLowerCase();
	var latin = /[a-zA-Z.,-]/;
	for(var pos=0; pos<text.length; pos++){
		if (skip > 0) {skip--; continue}
		temp = text.charAt(pos);
		if (!latin.test(temp)) {nstr.push(temp); continue}
		var slen = 5;
		var f = false;
		while(--slen){
			temp = text.slice(pos,pos+slen);
			if (!roma[to].hasOwnProperty(temp)) continue;
			f = true;
			kana = roma[to][temp];
			skip = (slen == 2) ? 1 : slen-1;
			//「っ」の場合、一文字戻す
			slen == 2 && kana.charAt(0) == roma[to].tt && pos--;
			nstr.push(kana);
			break
		}
		!f && nstr.push(orig.charAt(pos))
	}
	return nstr.join("");
}
var roma = {};
roma.hiragana = {"a":"あ","i":"い","yi":"い","u":"う","wu":"う","whu":"う","e":"え","o":"お","la":"ぁ","xa":"ぁ","li":"ぃ","xi":"ぃ","lyi":"ぃ","xyi":"ぃ","lu":"ぅ","xu":"ぅ","le":"ぇ","xe":"ぇ","lye":"ぇ","xye":"ぇ","lo":"ぉ","xo":"ぉ","wha":"うぁ","whi":"うぃ","wi":"うぃ","whe":"うぇ","we":"うぇ","who":"うぉ","ka":"か","ca":"か","ki":"き","ku":"く","cu":"く","qu":"く","ke":"け","ko":"こ","co":"こ","lka":"ヵ","xka":"ヵ","lke":"ヶ","xke":"ヶ","ga":"が","gi":"ぎ","gu":"ぐ","ge":"げ","go":"ご","kya":"きゃ","kyi":"きぃ","kyu":"きゅ","kye":"きぇ","kyo":"きょ","qya":"くゃ","qyu":"くゅ","qwa":"くぁ","qa":"くぁ","kwa":"くぁ","qwi":"くぃ","qi":"くぃ","qyi":"くぃ","qwu":"くぅ","qwe":"くぇ","qe":"くぇ","qye":"くぇ","qwo":"くぉ","qo":"くぉ","gya":"ぎゃ","gyi":"ぎぃ","gyu":"ぎゅ","gye":"ぎぇ","gyo":"ぎょ","gwa":"ぐぁ","gwi":"ぐぃ","gwu":"ぐぅ","gwe":"ぐぇ","gwo":"ぐぉ","sa":"さ","si":"し","ci":"し","shi":"し","su":"す","se":"せ","ce":"せ","so":"そ","za":"ざ","zi":"じ","ji":"じ","zu":"ず","ze":"ぜ","zo":"ぞ","sya":"しゃ","sha":"しゃ","syi":"しぃ","syu":"しゅ","shu":"しゅ","sye":"しぇ","she":"しぇ","syo":"しょ","sho":"しょ","swa":"すぁ","swi":"すぃ","swu":"すぅ","swe":"すぇ","swo":"すぉ","zya":"じゃ","ja":"じゃ","jya":"じゃ","zyi":"じぃ","jyi":"じぃ","zyu":"じゅ","ju":"じゅ","jyu":"じゅ","zye":"じぇ","je":"じぇ","jye":"じぇ","zyo":"じょ","jo":"じょ","jyo":"じょ","ta":"た","ti":"ち","chi":"ち","tu":"つ","tsu":"つ","te":"て","to":"と","ltu":"っ","xtu":"っ","ltsu":"っ","da":"だ","di":"ぢ","du":"づ","de":"で","do":"ど","tya":"ちゃ","cha":"ちゃ","cya":"ちゃ","tyi":"ちぃ","cyi":"ちぃ","tyu":"ちゅ","chu":"ちゅ","cyu":"ちゅ","tye":"ちぇ","che":"ちぇ","cye":"ちぇ","tyo":"ちょ","cho":"ちょ","cyo":"ちょ","tsa":"つぁ","tsi":"つぃ","tse":"つぇ","tso":"つぉ","tha":"てゃ","thi":"てぃ","thu":"てゅ","the":"てぇ","tho":"てょ","twa":"とぁ","twi":"とぃ","twu":"とぅ","twe":"とぇ","two":"とぉ","dya":"ぢゃ","dyi":"ぢぃ","dyu":"ぢゅ","dye":"ぢぇ","dyo":"ぢょ","dha":"でゃ","dhi":"でぃ","dhu":"でゅ","dhe":"でぇ","dho":"でょ","dwa":"どぁ","dwi":"どぃ","dwu":"どぅ","dwe":"どぇ","dwo":"どぉ","na":"な","ni":"に","nu":"ぬ","ne":"ね","no":"の","nya":"にゃ","nyi":"にぃ","nyu":"にゅ","nye":"にぇ","nyo":"にょ","ha":"は","hi":"ひ","hu":"ふ","fu":"ふ","he":"へ","ho":"ほ","ba":"ば","bi":"び","bu":"ぶ","be":"べ","bo":"ぼ","pa":"ぱ","pi":"ぴ","pu":"ぷ","pe":"ぺ","po":"ぽ","hya":"ひゃ","hyi":"ひぃ","hyu":"ひゅ","hye":"ひぇ","hyo":"ひょ","fya":"ふゃ","fyu":"ふゅ","fyo":"ふょ","fwa":"ふぁ","fa":"ふぁ","fwi":"ふぃ","fi":"ふぃ","fyi":"ふぃ","fwu":"ふぅ","fwe":"ふぇ","fe":"ふぇ","fye":"ふぇ","fwo":"ふぉ","fo":"ふぉ","bya":"びゃ","byi":"びぃ","byu":"びゅ","bye":"びぇ","byo":"びょ","va":"ヴぁ","vi":"ヴぃ","vu":"ヴ","ve":"ヴぇ","vo":"ヴぉ","vya":"ヴゃ","vyi":"ヴぃ","vyu":"ヴゅ","vye":"ヴぇ","vyo":"ヴょ","pya":"ぴゃ","pyi":"ぴぃ","pyu":"ぴゅ","pye":"ぴぇ","pyo":"ぴょ","ma":"ま","mi":"み","mu":"む","me":"め","mo":"も","mya":"みゃ","myi":"みぃ","myu":"みゅ","mye":"みぇ","myo":"みょ","ya":"や","yu":"ゆ","yo":"よ","lya":"ゃ","xya":"ゃ","lyu":"ゅ","xyu":"ゅ","lyo":"ょ","xyo":"ょ","ra":"ら","ri":"り","ru":"る","re":"れ","ro":"ろ","rya":"りゃ","ryi":"りぃ","ryu":"りゅ","rye":"りぇ","ryo":"りょ","wa":"わ","wo":"を","n":"ん","nn":"ん","n'":"ん","xn":"ん","lwa":"ゎ","xwa":"ゎ",".":"。",",":"、","bb":"っ","cc":"っ","dd":"っ","ff":"っ","gg":"っ","hh":"っ","jj":"っ","kk":"っ","ll":"っ","mm":"っ","pp":"っ","qq":"っ","rr":"っ","ss":"っ","tt":"っ","vv":"っ","ww":"っ","xx":"っ","yy":"っ","zz":"っ","-":"ー"};
roma.katakana = {"a":"ア","i":"イ","yi":"イ","u":"ウ","wu":"ウ","whu":"ウ","e":"エ","o":"オ","la":"ァ","xa":"ァ","li":"ィ","xi":"ィ","lyi":"ィ","xyi":"ィ","lu":"ゥ","xu":"ゥ","le":"ェ","xe":"ェ","lye":"ェ","xye":"ェ","lo":"ォ","xo":"ォ","wha":"ウァ","whi":"ウィ","wi":"ウィ","whe":"ウェ","we":"ウェ","who":"ウォ","ka":"カ","ca":"カ","ki":"キ","ku":"ク","cu":"ク","qu":"ク","ke":"ケ","ko":"コ","co":"コ","lka":"ヵ","xka":"ヵ","lke":"ヶ","xke":"ヶ","ga":"ガ","gi":"ギ","gu":"グ","ge":"ゲ","go":"ゴ","kya":"キャ","kyi":"キィ","kyu":"キュ","kye":"キェ","kyo":"キョ","qya":"クャ","qyu":"クュ","qwa":"クァ","qa":"クァ","kwa":"クァ","qwi":"クィ","qi":"クィ","qyi":"クィ","qwu":"クゥ","qwe":"クェ","qe":"クェ","qye":"クェ","qwo":"クォ","qo":"クォ","gya":"ギャ","gyi":"ギィ","gyu":"ギュ","gye":"ギェ","gyo":"ギョ","gwa":"グァ","gwi":"グィ","gwu":"グゥ","gwe":"グェ","gwo":"グォ","sa":"サ","si":"シ","ci":"シ","shi":"シ","su":"ス","se":"セ","ce":"セ","so":"ソ","za":"ザ","zi":"ジ","ji":"ジ","zu":"ズ","ze":"ゼ","zo":"ゾ","sya":"シャ","sha":"シャ","syi":"シィ","syu":"シュ","shu":"シュ","sye":"シェ","she":"シェ","syo":"ショ","sho":"ショ","swa":"スァ","swi":"スィ","swu":"スゥ","swe":"スェ","swo":"スォ","zya":"ジャ","ja":"ジャ","jya":"ジャ","zyi":"ジィ","jyi":"ジィ","zyu":"ジュ","ju":"ジュ","jyu":"ジュ","zye":"ジェ","je":"ジェ","jye":"ジェ","zyo":"ジョ","jo":"ジョ","jyo":"ジョ","ta":"タ","ti":"チ","chi":"チ","tu":"ツ","tsu":"ツ","te":"テ","to":"ト","ltu":"ッ","xtu":"ッ","ltsu":"ッ","da":"ダ","di":"ヂ","du":"ヅ","de":"デ","do":"ド","tya":"チャ","cha":"チャ","cya":"チャ","tyi":"チィ","cyi":"チィ","tyu":"チュ","chu":"チュ","cyu":"チュ","tye":"チェ","che":"チェ","cye":"チェ","tyo":"チョ","cho":"チョ","cyo":"チョ","tsa":"ツァ","tsi":"ツィ","tse":"ツェ","tso":"ツォ","tha":"テャ","thi":"ティ","thu":"テュ","the":"テェ","tho":"テョ","twa":"トァ","twi":"トィ","twu":"トゥ","twe":"トェ","two":"トォ","dya":"ヂャ","dyi":"ヂィ","dyu":"ヂュ","dye":"ヂェ","dyo":"ヂョ","dha":"デャ","dhi":"ディ","dhu":"デュ","dhe":"デェ","dho":"デョ","dwa":"ドァ","dwi":"ドィ","dwu":"ドゥ","dwe":"ドェ","dwo":"ドォ","na":"ナ","ni":"ニ","nu":"ヌ","ne":"ネ","no":"ノ","nya":"ニャ","nyi":"ニィ","nyu":"ニュ","nye":"ニェ","nyo":"ニョ","ha":"ハ","hi":"ヒ","hu":"フ","fu":"フ","he":"ヘ","ho":"ホ","ba":"バ","bi":"ビ","bu":"ブ","be":"ベ","bo":"ボ","pa":"パ","pi":"ピ","pu":"プ","pe":"ペ","po":"ポ","hya":"ヒャ","hyi":"ヒィ","hyu":"ヒュ","hye":"ヒェ","hyo":"ヒョ","fya":"フャ","fyu":"フュ","fyo":"フョ","fwa":"ファ","fa":"ファ","fwi":"フィ","fi":"フィ","fyi":"フィ","fwu":"フゥ","fwe":"フェ","fe":"フェ","fye":"フェ","fwo":"フォ","fo":"フォ","bya":"ビャ","byi":"ビィ","byu":"ビュ","bye":"ビェ","byo":"ビョ","va":"ヴァ","vi":"ヴィ","vu":"ヴ","ve":"ヴェ","vo":"ヴォ","vya":"ヴャ","vyi":"ヴィ","vyu":"ヴュ","vye":"ヴェ","vyo":"ヴョ","pya":"ピャ","pyi":"ピィ","pyu":"ピュ","pye":"ピェ","pyo":"ピョ","ma":"マ","mi":"ミ","mu":"ム","me":"メ","mo":"モ","mya":"ミャ","myi":"ミィ","myu":"ミュ","mye":"ミェ","myo":"ミョ","ya":"ヤ","yu":"ユ","yo":"ヨ","lya":"ャ","xya":"ャ","lyu":"ュ","xyu":"ュ","lyo":"ョ","xyo":"ョ","ra":"ラ","ri":"リ","ru":"ル","re":"レ","ro":"ロ","rya":"リャ","ryi":"リィ","ryu":"リュ","rye":"リェ","ryo":"リョ","wa":"ワ","wo":"ヲ","n":"ン","nn":"ン","n'":"ン","xn":"ン","lwa":"ヮ","xwa":"ヮ",".":"。",",":"、","bb":"ッ","cc":"ッ","dd":"ッ","ff":"ッ","gg":"ッ","hh":"ッ","jj":"ッ","kk":"ッ","ll":"ッ","mm":"ッ","pp":"ッ","qq":"ッ","rr":"ッ","ss":"ッ","tt":"ッ","vv":"ッ","ww":"ッ","xx":"ッ","yy":"ッ","zz":"ッ","-":"ー"};

if (jKeyboard.embedded) {
(function () {
  function load_css() {
    var style = document.getElementById('jKeyboard-css');
    if (!style) {
      style = document.createElement('link');
      style.id = 'jKeyboard-css';
      style.rel = 'stylesheet';
      style.href = 'http://n.h7a.org/iphone/jkeyboard/jkeyboard.css';
      style.type = 'text/css';
      document.getElementsByTagName('head')[0].appendChild(style); 
    }
  }

  function embed(n, input) {
    var div = document.getElementById('jKeyboard-'+n);
    if (div) return;

    jkbd= document.createElement('div');
    jkbd.id = 'jKeyboard-'+n;


    var jk = document.createElement('div');
    jk.id='jk-'+n;
    jk.setAttribute('class','jkbd-keyboard');

    var jc = document.createElement('div');
    jc.id='jc-'+n;
    jc.setAttribute('class','jkbd-candidates');

    jkbd.appendChild(jk);
    jkbd.appendChild(jc);

    jkbd.setAttribute('class','jkbd');
    jkbd.style.position = 'absolute';
    jkbd.style.display = 'none';
    jkbd.style.top = '-100px';
    jkbd.style.left = '-100px';

    var jswitch= document.createElement('span');
    jswitch.setAttribute('class', 'jkbd-switch');

    jswitch.appendChild(document.createTextNode('jKbd'));
    jswitch.onclick = (function(jkbd, input) {
      return function(){
	if (jkbd.style.top == '-100px') {
	  var x, y1, y2;
      var block = false;
	  x = 0;

	  y1 = input.offsetHeight;
	  for (var o=input; o ; o=o.offsetParent) {
        if (o.nodeName == 'DIV') block = true;

        if (!block) {
	      x += (o.offsetLeft - o.scrollLeft);
        }
	    y1 += (o.offsetTop - o.scrollTop);

        if (o.nodeName == 'TABLE') block = true;
	  }

	  y2 = this.offsetHeight;	  
	  for (var o=this; o ; o=o.offsetParent) {
	    y2 += (o.offsetTop - o.scrollTop);
	  }

	  jkbd.style.top = (y1 > y2 ? y1 : y2) + 'px';
	  jkbd.style.left = x + 'px';
	}
        jkbd.style.display = (jkbd.style.display == 'none') ? '' : 'none';
      }
    })(jkbd, input);


    input.parentNode.insertBefore(jswitch, input.nextSibling);
    input.parentNode.appendChild(jkbd);
    if(input.id==''){
      input.id='jt-'+n;
    }

    var jkbd = new jKeyboard({
      textarea:input.id,
      keyboard:jk.id,
      candidates:jc.id
    });
  }

  load_css();

  var index = 0;

  var inputs = document.getElementsByTagName('input');
  for(var i=0;i<inputs.length;i++){
    if(inputs[i].type=='text'){
      index++;
      embed(index, inputs[i]);
    }
  }

  var textareas = document.getElementsByTagName('textarea');
  for(var i=0;i<textareas.length;i++){
    index++;
    embed(index, textareas[i]);
  }
})();
}
