+/*\r
+ * JavaScript : Opera と Firefox でのキーイベントの違い\r
+ * http://blog.livedoor.jp/tzifa/archives/50776590.html\r
+ * keydown について。Firefox では押している間中リスナの関数が実行される\r
+ * デフォルトイベントの制御・抑止 (opera)keypress を用いる。\r
+ * \r
+ * キーイベント処理の工夫\r
+ * http://www.keynavi.net/ja/tipsj/kfunc.html\r
+ * keydown/up時にピリオドが文字化け (IE4-6) IE4+では「keypress」でキーコードを処理する 但しCtrlやALTが押されている場合は逆にkeydownで処理する必要があります\r
+ * \r
+ * \r
+ * keydown をトリガーにイベントを発火するもの\r
+ * 1. テンキーの 0~9 keyCode:96-105\r
+ * 2. ScrollLock:145, Ins:45, PuaseBreak:19, HOME:36, PageUp:33, del:46, END:35, PageDown:34,\r
+ * ←↑→↓:37-40, tab:9, capsLock:240or208, Shift+capslock:20, shift:16, ctrl:17, LWIN:91, BS:8,\r
+ * \r
+ * 3. RWIN:92!(Opera<9.5), alt:18, [F1]-[F12]:112-123\r
+ * \r
+ */\r
+\r
+var X_KB_TABLE = {\r
+ specials : {\r
+ '96' : 48,\r
+ '97' : 49,\r
+ '98' : 50,\r
+ '99' : 51,\r
+ '100' : 52,\r
+ '101' : 53,\r
+ '102' : 54,\r
+ '103' : 55,\r
+ '104' : 56,\r
+ '105' : 57,\r
+\r
+ '8' : 'BS',\r
+ '9' : 'TAB',\r
+ '13' : 'ENTER',\r
+ '16' : 'SHIFT',\r
+ '17' : 'CTRL',\r
+ '18' : 'ALT',\r
+ '19' : 'PAUSE_BREAK',\r
+ '20' : 'SHIFT+CAPS_LOCK',\r
+ \r
+ '27' : 'ESC',\r
+ '28' : 'trans',\r
+ '29' : 'no trans',\r
+ \r
+ '33' : 'PAGE_UP',\r
+ '34' : 'PAGE_DOWN',\r
+ '35' : 'END',\r
+ '36' : 'HOME', \r
+ '37' : 'CSR_L',\r
+ '38' : 'CSR_U',\r
+ '39' : 'CSR_R',\r
+ '40' : 'CSR_D',\r
+ '45' : 'INS',\r
+ '44' : 'PRT_SCRN',\r
+ '46' : 'DEL',\r
+ \r
+ '91' : 'LWIN',\r
+ '92' : 'RWIN',\r
+ '93' : 'APP',\r
+ \r
+ '106' : 42,\r
+ '107' : 43,\r
+ '109' : 45,\r
+ '111' : 47,\r
+ '112' : 'F1',\r
+ '113' : 'F2',\r
+ '114' : 'F3',\r
+ '115' : 'F4',\r
+ '116' : 'F5',\r
+ '117' : 'F6',\r
+ '118' : 'F7',\r
+ '119' : 'F8',\r
+ '120' : 'F9',\r
+ '121' : 'F10',\r
+ '122' : 'F11',\r
+ '123' : 'F12',\r
+\r
+ '144' : 'NUM_LOCK',\r
+ '145' : 'SCROLL_LOCK',\r
+ '208' : 'CAPS_LOCK',\r
+ '240' : 'CAPS_LOCK',\r
+ '242' : 'K/H',\r
+ '243' : 'H/Z',\r
+ '244' : 'H/Z'\r
+ \r
+ },\r
+ // keypress 時に keyCode を直す 0 の場合、イベント発火せず。どのキーが押されたか?判定できないため\r
+ 'keypress' : {\r
+ // !-):33-41, *:42, +:43, ,:44, -:45, .:46, /:47, 0-9:48-57 , ::58 , ;:59 , <:60 , =:61, >:62, ?:63, @:64\r
+ // A-Z:65-90, [:91, \:92, ]:93, ^:94, _:95, `:96, a-z:97-122, {:123, |:124, }:125, ~:126\r
+ },\r
+ \r
+ 'keyup' : {\r
+ '189' : '45,61', // ie, safari\r
+ '109' : '45,61', // firefox, opera\r
+ \r
+ '222' : '94,126', // firefox, ie, safari\r
+ '94' : '94,126', // opera\r
+\r
+ '226' : '92,95', // firefox, ie, safari,\r
+ '220' : 9.5 <= X_UA[ 'Opera' ] ? '92,95,124' : '92,124', // firefox, ie, safari, opera9.50+\r
+ '92' : '92,95,124', // opera9.25\r
+ \r
+ '192' : '64,96', // firefox, ie, safari\r
+ '64' : '64,96', // opera\r
+ \r
+ '219' : '91,123', // firefox, ie, safari, opera9.50+\r
+ '91' : '91,123', // opera9.25\r
+ \r
+ '187' : '59,43', // ie, safari\r
+ '61' : '59,43', // firefox, opera\r
+ \r
+ '186' : '58,42', // ie, safari\r
+ '59' : '58,42', // firefox, opera\r
+ \r
+ '221' : '93,125', // firefox, ie, safari, opera9.50+\r
+ '93' : '93,125', // opera9.25\r
+ \r
+ '188' : '44,60', // firefox, ie, safari, opera9.50+\r
+ '44' : '44,60', // opera9.25\r
+ \r
+ '190' : '46,62', // firefox, ie, safari, opera9.50+\r
+ '46' : '46,62', // opera9.25\r
+ \r
+ '191' : '47,63', // firefox, ie, safari, opera9.50+\r
+ '47' : '47,63' // opera9.25\r
+ }\r
+ },\r
+ X_KB_DOWN_KEYS = {},\r
+ X_KB_CANCELED = {},\r
+ X_KB_lastIs10Key = 0,\r
+ X_KB_lastKeyCode = 0, \r
+ X_KB_TRANSFOEM = {},\r
+ \r
+ X_kbManager =\r
+ X_Class_override(\r
+ X_EventDispatcher(),\r
+ { \r
+ handleEvent : function( e ){\r
+ var keyCode = e.keyCode, // keyCode says something about the actual keyboard key the user pressed\r
+ chrCode = e.charCode, // while charCode gives the ASCII value of the resulting character\r
+ cb = X_CALLBACK_NONE,\r
+ special, is10Key, _keyCode;\r
+ \r
+ console.log( e.type + ' > keyCode:' + keyCode + ' chrCode:' + chrCode );\r
+ \r
+ switch( e.type ){\r
+ case 'keydown' :\r
+\r
+ if( X_KB_DOWN_KEYS[ keyCode ] ){\r
+ // 既に押されている、メタキー[shift,ctrl,alt]の変化はある?\r
+ return cb;\r
+ } else\r
+ if( special = X_KB_TABLE.specials[ keyCode ] ){\r
+ \r
+ if( X_Type_isNumber( special ) ){\r
+ // テンキーの [0]~[9]\r
+ //chrCode = special;\r
+ X_KB_lastKeyCode = keyCode;\r
+ X_KB_lastIs10Key = true;\r
+ return cb;\r
+ } else {\r
+ X_KB_DOWN_KEYS[ keyCode ] = true;\r
+ chrCode = 0;\r
+ };\r
+ \r
+ cb = this[ 'dispatch' ]( {\r
+ type : 'keydown',\r
+ keyCode : keyCode,\r
+ charCode : chrCode,\r
+ keyName : X_Type_isString( special ) ? special : '',\r
+ is10key : !!is10Key,\r
+ shiftKey : !!X_KB_DOWN_KEYS[ 16 ],\r
+ ctrlKey : !!X_KB_DOWN_KEYS[ 17 ],\r
+ altKey : !!X_KB_DOWN_KEYS[ 18 ],\r
+ metaKey : !!X_KB_DOWN_KEYS[ 224 ]\r
+ } );\r
+ \r
+ if( cb & X_CALLBACK_PREVENT_DEFAULT ){\r
+ X_KB_CANCELED[ keyCode ] = true;\r
+ };\r
+ } else {\r
+ X_KB_lastKeyCode = keyCode;\r
+ };\r
+\r
+ return cb;\r
+ \r
+ case 'keypress' :\r
+ // keydown 側で発火しているものは再び発火しない\r
+ console.log( 'kp : ' + X_KB_DOWN_KEYS[ chrCode ] + ( X_KB_CANCELED[ chrCode ] ? ' Cancel!' : '' ) );\r
+ if( X_KB_DOWN_KEYS[ chrCode ] ){\r
+ return X_KB_CANCELED[ chrCode ] ? X_CALLBACK_PREVENT_DEFAULT : cb;\r
+ };\r
+\r
+ if( 33 <= chrCode && chrCode <= 126 ){\r
+ X_KB_TRANSFOEM[ X_KB_lastKeyCode ] = chrCode;\r
+ \r
+ cb = this[ 'dispatch' ]( {\r
+ type : 'keydown',\r
+ keyCode : X_KB_lastIs10Key ? X_KB_lastKeyCode : 0,\r
+ charCode : chrCode,\r
+ is10key : X_KB_lastIs10Key,\r
+ shiftKey : !!X_KB_DOWN_KEYS[ 16 ],\r
+ ctrlKey : !!X_KB_DOWN_KEYS[ 17 ],\r
+ altKey : !!X_KB_DOWN_KEYS[ 18 ],\r
+ metaKey : !!X_KB_DOWN_KEYS[ 224 ]\r
+ } );\r
+ \r
+ X_KB_lastIs10Key = true;\r
+ };\r
+ return cb;\r
+ \r
+ case 'keyup' :\r
+ if( X_KB_CANCELED[ keyCode ] ){\r
+ cb = X_CALLBACK_PREVENT_DEFAULT;\r
+ };\r
+ \r
+ if( ( special = X_KB_TABLE.specials[ keyCode ] ) && ( !X_KB_DOWN_KEYS[ keyCode ] && !X_KB_DOWN_KEYS[ special ] ) ){\r
+ cb |= this[ 'dispatch' ]( {\r
+ type : 'keydown',\r
+ keyCode : keyCode,\r
+ charCode : 0,\r
+ keyName : special,\r
+ is10key : false,\r
+ isVirtual : true,\r
+ shiftKey : !!X_KB_DOWN_KEYS[ 16 ],\r
+ ctrlKey : !!X_KB_DOWN_KEYS[ 17 ],\r
+ altKey : !!X_KB_DOWN_KEYS[ 18 ],\r
+ metaKey : !!X_KB_DOWN_KEYS[ 224 ]\r
+ } );\r
+ };\r
+ \r
+ if( X_KB_DOWN_KEYS[ keyCode ] ) delete X_KB_DOWN_KEYS[ keyCode ];\r
+ if( X_KB_CANCELED[ keyCode ] ) delete X_KB_CANCELED[ keyCode ];\r
+ \r
+ chrCode = 0;\r
+ if( !special ){\r
+ chrCode = X_KB_TRANSFOEM[ keyCode ];\r
+ if( !chrCode ) return cb;\r
+ delete X_KB_TRANSFOEM[ keyCode ];\r
+ //keyCode = 0;\r
+ };\r
+ \r
+ cb |= this[ 'dispatch' ]( {\r
+ type : 'keyup',\r
+ keyCode : keyCode,\r
+ charCode : chrCode,\r
+ keyName : X_Type_isString( special ) ? special : '',\r
+ shiftKey : X_KB_DOWN_KEYS[ 16 ],\r
+ ctrlKey : X_KB_DOWN_KEYS[ 17 ],\r
+ altKey : X_KB_DOWN_KEYS[ 18 ],\r
+ metaKey : X_KB_DOWN_KEYS[ 224 ]\r
+ } );\r
+\r
+ return cb;\r
+ \r
+ case X_EVENT_VIEW_ACTIVATE :\r
+ //\r
+ break;\r
+ case X_EVENT_VIEW_DEACTIVATE :\r
+ //\r
+ break; \r
+ };\r
+ }\r
+ }\r
+ ),\r
+\r
+/**\r
+ * キーボードイベント情報を提供するオブジェクト。\r
+ * @namespace X.KB\r
+ * @alias X.KB\r
+ */\r
+ X_KB = X[ 'KB' ] = {\r
+ /**\r
+ * \r
+ * @alias X.KB.listen\r
+ */\r
+ 'listen' : function( type, arg1, arg2, arg3 ){\r
+ type && arg1 && X_kbManager[ 'listen' ]( type, arg1, arg2, arg3 );\r
+ return X_KB;\r
+ },\r
+ \r
+ /**\r
+ * \r
+ * @alias X.KB.listenOnce\r
+ */\r
+ 'listenOnce' : function( type, arg1, arg2, arg3 ){\r
+ type && arg1 && X_kbManager[ 'listenOnce' ]( type, arg1, arg2, arg3 );\r
+ return X_KB;\r
+ },\r
+ \r
+ /**\r
+ * \r
+ * @alias X.KB.unlisten\r
+ */\r
+ 'unlisten' : function( type, arg1, arg2, arg3 ){\r
+ type && arg1 && X_kbManager[ 'unlisten' ]( type, arg1, arg2, arg3 );\r
+ return X_KB;\r
+ },\r
+ \r
+ /**\r
+ * \r
+ * @alias X.KB.listening\r
+ */\r
+ 'listening' : function( type, arg1, arg2, arg3 ){\r
+ return X_kbManager[ 'listening' ]( type, arg1, arg2, arg3 );\r
+ }\r
+ };\r
+\r
+X_ViewPort[ 'listen' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE ], X_kbManager );\r
+\r
+if( X_UA[ 'IE' ] < 9 ){\r
+ X_ViewPort_document[ 'listen' ]( [ 'keyup', 'keydown', 'keypress' ], X_kbManager );\r
+} else {\r
+ X_ViewPort[ 'listen' ]( [ 'keyup', 'keydown', 'keypress' ], X_kbManager );\r
+};\r