― MozillaZine.jp フォーラムは Mozilla 製品に関する情報交換の場です ―



All times are UTC + 9 hours

新しいトピックを投稿する トピックへ返信する  [ 10 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2007年12月18日(火) 23:02 
オフライン

登録日時: 2007年7月01日(日) 23:02
記事: 23
お住まい: 千葉
HTMLのinput,textarea要素を拡張したいと思い、XBLを書いています。
その中で、
コード:
<method name="doCommand">
  <parameter name="cmd"/>
  <body><![CDATA[
    var controller = this.controllers.getControllerForCommand(cmd);
    controller.doCommand(cmd);
  ]]></body>
</method>
を実行すると以下のようなエラーとなり実行できません。
コード:
エラー: [Exception... "'Permission denied to call method XULControllers.getControllerForCommand' when calling method: [nsIDOMEventListener::handleEvent]"  nsresult: "0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)"  location: "<unknown>"  data: no]

セキュリティ的に許されていないのだろうとは思うのですが、やりたい事はviエディタのようなモード変更ありのカーソル移動等で、'cmd_charPrevious'等を発行したいだけです。
モード変更があるため、chrome://global/content/pralformHTMLBindingsにあるようなhandler要素のcommand属性が使えません。

大部分はカーソル移動ですので、selectionStart,selectionEndプロパティを操作すれば何とかなるのですが、回避方法があるかどうかを知りたいです。


通報する
ページトップ
 プロフィール  
引用付きで返信する  
投稿記事Posted: 2007年12月19日(水) 12:04 
オフライン

登録日時: 2005年8月02日(火) 22:12
記事: 42
お住まい: 東京都
私はあまり経験がないので、外していたらごめんなさい。

teramako さんが書きました:
コード:
<method name="doCommand">
  <parameter name="cmd"/>
  <body><![CDATA[
    var controller = this.controllers.getControllerForCommand(cmd);
    controller.doCommand(cmd);
  ]]></body>
</method>
を実行すると以下のようなエラーとなり実行できません。

XUL Tutorial:Updating Commands - MDC のコードだと;

コード:
var controller = document.commandDispatcher.getControllerForCommand("cmd_paste");
if (controller && controller.isCommandEnabled("cmd_paste")){
  controller.doCommand(command);
}

なので、commandDispatcher をかましてないのが原因かも? と思いました。
controllers = commandDispatcher なんでしょうか?


通報する
ページトップ
 プロフィール  
引用付きで返信する  
投稿記事Posted: 2007年12月19日(水) 22:06 
オフライン

登録日時: 2007年7月01日(日) 23:02
記事: 23
お住まい: 千葉
引用:
なので、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);
}


通報する
ページトップ
 プロフィール  
引用付きで返信する  
投稿記事Posted: 2007年12月19日(水) 23:06 
teramako さんが書きました:
また、先ほど同じbindingを施したものをchrome://...のURLからアクセスしてみましたが、きちんと動作しました。XBL自体もchrome://...の方においているのですが、Firefox外部のリソースにbindingすると外部リソースと同じく制限を受けてしまうようです。
目的の HTML は、普通の Web サイトにあるもの、ということでしょうか?
また、制限を回避する方法はありますが、その XBL は不特定多数の人に使わせるようなものではないという条件で良いしょうか?
# 制限に穴を開けるわけですから…

まず、制限のかかっている操作を呼び出す関数(XBL なので method?)内で、その操作より前に
コード:
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
を実行してください。
また、about:config 等で signed.applets.codebase_principal_support を true にしておいてください。

そのままでは毎回確認のダイアログが出てきますが、次回も同様に処理するチェックを入れてしまえば、同じドメイン内では次からは確認ダイアログは出ません。

本来はかかっている制限をはずすことになりますので、自己責任で使ってください


通報する
ページトップ
  
引用付きで返信する  
投稿記事Posted: 2007年12月19日(水) 23:29 
オフライン

登録日時: 2007年7月01日(日) 23:02
記事: 23
お住まい: 千葉
あ さんが書きました:
teramako さんが書きました:
また、先ほど同じbindingを施したものをchrome://...のURLからアクセスしてみましたが、きちんと動作しました。XBL自体もchrome://...の方においているのですが、Firefox外部のリソースにbindingすると外部リソースと同じく制限を受けてしまうようです。
目的の HTML は、普通の Web サイトにあるもの、ということでしょうか?
また、制限を回避する方法はありますが、その XBL は不特定多数の人に使わせるようなものではないという条件で良いしょうか?
# 制限に穴を開けるわけですから…

目的としては通常のブラウジング時にviキーバインドでの操作が出来たら幸せだなと思って作ろうとしているので、そういうことになります。

あ さんが書きました:
まず、制限のかかっている操作を呼び出す関数(XBL なので method?)内で、その操作より前に
コード:
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
を実行してください。
また、about:config 等で signed.applets.codebase_principal_support を true にしておいてください。

そのままでは毎回確認のダイアログが出てきますが、次回も同様に処理するチェックを入れてしまえば、同じドメイン内では次からは確認ダイアログは出ません。

本来はかかっている制限をはずすことになりますので、自己責任で使ってください

しかし、セキュリティチェックを外してまでやろうとは思いません。
handler要素のcommand属性からならコマンドが効くので、何か(セキュリティ制限を外すとかではなく)普通にやる方法があるのでは? と思っての質問でした。
素直に諦めた方が良さそうですかね...。


通報する
ページトップ
 プロフィール  
引用付きで返信する  
投稿記事Posted: 2007年12月20日(木) 08:43 
オフライン
Moderator

登録日時: 2007年5月03日(木) 01:11
記事: 92
お住まい: 東京
XBLでやるのは諦めて、

コード:
gBrowser.addEventListener('keypress', function(aEvent) {
  var node = aEvent.originalTarget;
  if (node.localName == 'textarea') {
    var controller = node.controllers.....
    (略)
    aEvent.stopPropagation();
    aEvent.preventDefault();
  }
}, true);


という感じでChrome権限のコードの中で書くしかないかも。


通報する
ページトップ
 プロフィール  
引用付きで返信する  
投稿記事Posted: 2007年12月20日(木) 10:56 
オフライン

登録日時: 2007年7月01日(日) 23:02
記事: 23
お住まい: 千葉
Piro さんが書きました:
Chrome権限のコードの中で書くしかないかも。

たしかにそれが一番確実な方法ですね。
その方向で考えていきたいと思います。

また、何か分かりましたら宜しくお願いします。


通報する
ページトップ
 プロフィール  
引用付きで返信する  
投稿記事Posted: 2007年12月20日(木) 20:57 
teramako さんが書きました:
handler要素のcommand属性からならコマンドが効くので、何か(セキュリティ制限を外すとかではなく)普通にやる方法があるのでは? と思っての質問でした。
そういうことでしたか。
そうすると、こんな感じでしょうか。
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')">
        <setter><![CDATA[
          var selectionStart = this.selectionStart;
          var selectionEnd = this.selectionEnd;
          this.setAttribute('mode',val);
          this.selectionStart = selectionStart;
          this.selectionEnd = selectionEnd;
          this.blur();
          this.focus();
          return val;
        ]]></setter>
      </property>
       <constructor><![CDATA[
          //this.mode = this.hasAttribute('mode') ? this.getAttribute('mode') : 'insert';
          if (!this.hasAttribute('mode'))
            this.setAttribute('mode', 'insert');
       ]]></constructor>
    </implementation>
  </binding>
  <binding id="viInputFieldsInsert" extends="#viInputFields">
    <handlers>
      <handler event="keypress" keycode="VK_ESCAPE"><![CDATA[
        this.mode = 'normal';
      ]]></handler>
    </handlers>
  </binding>
  <binding id="viInputFieldsNormal" extends="#viInputFields">
    <handlers>
      <handler event="keypress" key="i" modifiers="shift" command="cmd_beginLine"/>
      <handler event="keypress" key="h" command="cmd_charPrevious"/>
      <handler event="keypress" key="l" command="cmd_charNext"/>
      <handler event="keypress"><![CDATA[
        switch(event.charCode){
          case 73: //`I'
            setTimeout(function(t) {t.mode = 'insert';}, 0, this);
            return;
          case 105: //`i'
            this.mode = 'insert';
            break;
          case 104: //`h'
          case 108: //`l'
            return;
          }
        event.preventDefault();
      ]]></handler>
    </handlers>
  </binding>
</bindings>

userContent.css
コード:
input {
-moz-binding: url("chrome://hogehoge/content/bindigns/vi_input.xbl#viInputFieldsInsert");
}
input[mode="normal"] {
-moz-binding: url("chrome://hogehoge/content/bindigns/vi_input.xbl#viInputFieldsNormal");
}

# trunk で動かないのは、バグなのか仕様変更なのか…


通報する
ページトップ
  
引用付きで返信する  
投稿記事Posted: 2007年12月20日(木) 21:37 
オフライン

登録日時: 2007年7月01日(日) 23:02
記事: 23
お住まい: 千葉
なるほどっ!
属性値を変える事で動的にバインディング自体を変える手法がありましたね。
盲点でした。

あ さんが書きました:
# trunk で動かないのは、バグなのか仕様変更なのか…

ありゃりゃ、仕様変更だとしたらこの先動かなくなるわけですね。 セキュリティ的な問題なら仕方ないですが、そうでないならバグであることを祈りますw

回答を下さった、georigeiさん、あさん、piroさん、ありがとうございました。
これで安眠できそうです :D


追記です。
mode属性のsetterでselectionStart,selectionEndを再代入しているのは何故? と思ってましたが、bindingを変えるとフォーカスが外れてキャレット位置もリセットされてしまうんですね。細かいところまで気が利いていて感動。


通報する
ページトップ
 プロフィール  
引用付きで返信する  
投稿記事Posted: 2007年12月21日(金) 22:27 
teramako さんが書きました:
何故? と思ってましたが、bindingを変えるとフォーカスが外れてキャレット位置もリセットされてしまうんですね。細かいところまで気が利いていて感動。
細かいところまで気が利いているというよりは、XBL がからむとどうにもおかしなことが起こるので、しかたなく workaround を入れたというような感じです。
そのままでは、キャレットが消えてフォーカスが外れたように見えますが、入力すればそのまま input 要素に入力できたりして、意味不明。


通報する
ページトップ
  
引用付きで返信する  
期間内表示:  ソート  
新しいトピックを投稿する トピックへ返信する  [ 10 件の記事 ] 

All times are UTC + 9 hours


オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[13人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
Powered by MozillaZine.jp® Forum Software © phpBB Group , Almsamim WYSIWYG
Japanese translation principally by ocean