引用:
なので、commandDispatcher をかましてないのが原因かも? と思いました。
controllers = commandDispatcher なんでしょうか?
いいえ、this.controllersは、input,textarea要素についているネイティブ(?)のプロパティで、DOM Inspectorで見ると[object XULControllers]となっています。おそらく、nsIControllersではないかと思います。このオブジェクト配下にはcommandDispatcherもありますが、残念ながらnull値です。
あと、XUL Windowにはdocument.commandDispatcherがあるのですがHTMLドキュメントには存在しないようです。
また、先ほど同じbindingを施したものをchrome://...のURLからアクセスしてみましたが、きちんと動作しました。XBL自体もchrome://...の方においているのですが、Firefox外部のリソースにbindingすると外部リソースと同じく制限を受けてしまうようです。
しかし、通常のキーバインド、
コード:
<handler event="keypress" key="l" command="cmd_charNext"/>
は外部リソースでも動作します。動的にhandlerを追加/削除できれば良いのですが...
ついでなので今現在のソースを晒しておきます。
chrome://hogehoge/content/bindings/vi_input.xbl
コード:
<?xml version="1.0"?>
<bindings id="viInputBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="viInputFields">
<implementation>
<property name="mode"
onget="return this.getAttribute('mode')"
onset="this.setAttribute('mode',val); return val"/>
<method name="doCommand">
<parameter name="cmd"/>
<body><![CDATA[
var controller = this.controllers.getControllerForCommand(cmd);
controller.doCommand(cmd);
]]></body>
</method>
<constructor><![CDATA[
this.mode = this.hasAttribute('mode') ? this.getAttribute('mode') : 'insert';
this.addEventListener('keypress',function(e){
if(this.mode == 'normal'){
switch(e.charCode){
case 73: //`I'
this.doCommand('cmd_beginLine');
case 105: //`i'
this.mode = 'insert';
break;
case 104: //`h'
this.doCommand('cmd_charPrevious');
break;
case 108: //`l'
this.doCommand('cmd_charNext');
break;
}
e.preventDefault();
} else if(this.mode == 'insert'){
if(e.keyCode == e.DOM_VK_ESCAPE){
this.mode = 'normal';
}
}
},true);
]]></constructor>
</implementation>
</binding>
</binding>
userContent.css
コード:
input {
-moz-binding: url(chrome://hogehoge/content/bindigns/vi_input.xbl#viInputFields);
}