2012-01-17 6 views
4

私はui.mouseを拡張するjqueryウィジェットを開発しています。JQuery UIウィジェット - ラッパー要素でイベントを発生させる方法

要素を作成してthis.elementに追加することで、ウィジェットはマウスイベントに反応する必要があります。

子要素を含めることができないIMGタグなどのHTML要素にウィジェットが適用される場合、ウィジェットは代理ラッパー要素を作成してthis.elementをラップします。

this.elementをラッパー要素に置き換えた場合、ウィジェットインスタンスの.bind()呼び出しがラッパーではなく元の要素にハンドラーを適用するため、ウィジェットがトリガーするイベントは決して処理されません。

this.elementをwrapper要素で置き換えないと、ui.mouseで定義された_mouse *イベントは、wrapperではなくthis.elementに適用されるため、正しく呼び出されません。

次のbind()呼び出しが適用されるか、またはui.mouseプロトタイプがthis.element以外の要素に適用されるように、ラッパー要素を何とか返す優雅な方法がありますか?

他の優雅なソリューションやアドバイスは大歓迎です。

これは私が試した2つのシナリオです。

this.element

私は私がいる問題が原因私はjqueryのUIを理解する方法の欠点にあるかなり確信してthis.element
$.widget("ui.example", ui.mouse, { 

    _create: function() 
    { 
     if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) 
     { 
      this._applyContainer(); 
     } 

     // Applies mouse interaction handlers to this.element 
     this._mouseInit(); 

    }, 

    _applyContainer: function() 
    { 
     this.element.wrap("<span>"); 
     this.element = this.element.parent(); 
     this.element.css({position:'relative'}); 
    }, 

    _mouseStart: function (event) { 

     // This event is never handled because it is not raised on the original element. 
     this._trigger("mouseevent"); 
    } 
}) 

$("IMG").example().bind("examplemouseevent", function(){ 
    //This never fires because the bind is to the IMG element, not the wrapper 
}) 

の交換

$.widget("ui.example", ui.mouse, { 

    _containerElement: null, 

    _create: function() 
    { 
     if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) 
     { 
      this._applyContainer(); 
     }else{ 
      this._containerElement = this.element; 
     } 

     // Applies mouse interaction handlers to this.element 
     this._mouseInit(); 

    }, 

    _applyContainer: function() 
    { 
     this.element.wrap("<span>"); 
     this._containerElement = this.element.parent(); 
     this._containerElement.css({position:'relative'}); 
    }, 


    _mouseStart: function (event) { 

     // Not always called because it handles mouse interaction with 
     // the IMG element rather than the wrapper element 

     this._trigger("mouseevent"); 
    } 
}) 

$("IMG").example().bind("examplemouseevent", function(){ 
    //This fires but only when the original IMG element is clicked, not the wrapper 
}) 

を交換することなく、仕事をするための仕事、またはjqueryウィジェットフレームワークの制限。

this.elementを元のthis.elementをラップする要素に置き換えると、イベントは後でウィジェットにバインドされたハンドラに渡されません。

this.elementを置き換えずに、ラッパーへの別の参照を格納すると、jqueryベースui.mouseの動作によってイベントが誤った要素にアタッチされます。

コードは設計通りに動作していますが、私の問題は設計の制約を踏まえて作業する最良の方法です。

私はこれに対処するいくつかの方法を見ることができます。例えば; _triggerメソッドをダック・パンチして正しい要素でイベントをトリガーするか、またはui.mouseが必要なハンドラをアタッチしている間にthis.element値を前後にスワップします。 私が考えているこれらの方法や他の方法はかなり面倒です。

ラッパーも作成するネイティブのjquery.resizableウィジェットコードを見てきましたが、わかりますから、イベントをトリガーしようとすると同じ問題が発生します。

私がJQueryウィジェットを使って作業したのはこれが初めてです。ここで何か不足していないことをJQueryの担当者から確認したいのですが?

+0

これはどのブラウザでテストしていますか?私は似たような問題を抱えていますが、原因は通常、DOMは時間内に更新されないということです。 .parent()を取得しようとすると、はまだ存在しません。私は、スクリプトが実行を停止した後にDOMを更新するだけなので、IEはこれを本当に迷惑にしていることを知っています。 – Flater

+0

Chrome、IE9、Firefoxでテストしました。 –

+0

このundebuggableエラーを排除するために、別々にトリガーされたイベントへの2番目のボタンリンクを作成してテストすることをお勧めします。私が正しいとすれば、DOMを変更して新しいDOMをたどる間に、静かなモーメント(スクリプトによる)がある場合は、うまくいくはずです。ブラウザが本当に元のDOMを本当に更新するかわからないので、これをデバッグする方法は他にありません。ちょうど提案:-) – Flater

答えて

0

私はそれに完全には満足していませんが、私が行った解決策は、this.elementの呼び出しを_mouseInitに置き換えてもう一度元に戻すことです。

_containerElement: null, 

_applyContainer: function() 
{ 
    var origionalElement = this.element; 
    this.element.wrap("<div>"); 
    this._containerElement = this.element.parent(); 
    this.element = this._containerElement; 
    this._mouseInit(); 
    this.element = origionalElement; 
    this._containerElement.css({position:'relative'}); 
}, 

私は美しくはありませんが、機能します。私は将来、ある時点で_mouseInitをオーバーライドしてもらうかもしれませんが、これは今のところ私の目的に合っています。

1

私のようなアプローチしようとするだろう:子供たちに、バインドをラッパー要素を構築する場合

_applyContainer: function() 
{ 
    this.element.wrap("<span>"); 
    this.element.bind("list of events", function(){ 
     this.element.parent().trigger("name of event"); 
    }); 
    this.element = this.element.parent(); 
    this.element.css({position:'relative'}); 
} 

を、どんなイベントリスト(あなたはこの概念が動作しない場合繰り返すことができます)とトリガ親(スコープ、既知の)要素の同じ名前のイベント。 注:「イベントのリスト」は「mouseover mouseout click」などのようにする必要があります。次に、「イベントの名前」をトリガーされたリストを検出するロジックに置き換える必要があります。

関連する問題