2009-10-07 4 views
5

私はautoCompleteBoxのようなものを作成するカスタム機能を持つjQueryプラグインを作成しようとしています。一致するjQuery要素ごとにメンバ変数を保存するにはどうすればよいですか?jQueryプラグインにメンバー変数とパブリックメソッドを持たせるにはどうすればいいですか?

たとえば、それぞれにtimerIDを格納する必要があります。また、コントロールを構成するいくつかのDOM要素への参照を格納したいと思います。

私は何か作品パブリックメソッド作ることができるようにしたい:私はそのtimerIdのようなその特定のオブジェクトのメンバ変数にアクセスする方法を

$("#myCtrl").autoCompleteEx.addItem("1"); 

しかしのaddItem()の実装では何か?以下は

...私がこれまで持っているものすべてのヘルプや提案のための

感謝です!

(function($) 
{  
    //Attach this new method to jQuery 
    $.fn.autoCompleteEx = function(options) 
    {  
     //Merge Given Options W/ Defaults, But Don't Alter Either 
     var opts = $.extend({}, $.fn.autoCompleteEx.defaults, options); 


     //Iterate over the current set of matched elements 
     return this.each(function() 
     { 
      var acx = $(this); //Get JQuery Version Of Element (Should Be Div) 

      //Give Div Correct Class & Add <ul> w/ input item to it 
      acx.addClass("autoCompleteEx"); 
      acx.html("<ul><li class=\"input\"><input type=\"text\"/></li></ul>"); 

      //Grab Input As JQ Object 
      var input = $("input", acx); 

      //Wireup Div 
      acx.click(function() 
      { 
       input.focus().val(input.val()); 
      }); 


      //Wireup Input 
      input.keydown(function(e) 
      { 
       var kc = e.keyCode; 
       if(kc == 13) //Enter 
       { 

       } 
       else if(kc == 27) //Esc 
       { 

       } 
       else 
       { 
        //Resize TextArea To Input 
        var width = 50 + (_txtArea.val().length*10); 
        _txtArea.css("width", width+"px");  
       } 
      }); 

     }); //End Each JQ Element 

    }; //End autoCompleteEx() 

    //Private Functions 
    function junk() 
    { 

    }; 

    //Public Functions 
    $.fn.autoCompleteEx.addItem = function(id,txt) 
    { 
     var x = this; 
     var y = 0; 
    }; 

    //Default Settings 
    $.fn.autoCompleteEx.defaults = 
    { 
     minChars: 2, 
     delay:  300, 
     maxItems: 1 
    }; 

    //End Of Closure 
})(jQuery); 

答えて

7

:ここ

は(不完全と役に立たない)プラグインがどのように見えるかのラフな一例です。そして、「この」文脈が保存されて

$('#elem').autoCompleteEx('addItem', '1'); 

、あなたはこれらの線に沿って何かを行うことができます:あなたは、あなたのプラグインに文字列引数としてあなたの「余分なメソッド」を作成

function addItem() { 
    // this should be == jquery object when this get called 
} 

$.fn.autoCompleteEx = function(options) { 
    if (options === 'addItem') { 
    return addItem.apply(this, Array.prototype.splice.call(arguments, 1)); 
    } 
}; 
+0

あなたは天才です...このために百万をありがとう! – Legend

1

jQueryの.data機能を見てください。どのオブジェクトにもキー/値のペアを格納できます。

+0

をそれは私のために働くことができるようにはい、それは見えます。それが私が成し遂げようとしていることのための好ましい方法であるかどうか知っていますか? – user169867

+0

1つの欠点は、データがプライベートではないことです。 – user169867

1

使用このような何か:

acx.data("acx-somename", datavalue); 

次に、あなたが後ででそれを取得することができます。ここでは

var datavalue = acx.data("acx-somename"); 
+0

データは問題のDOMオブジェクトに関連するデータを格納しているすべてのもので共有されているため、 "acx-"接頭辞は名前空間として存在します。私は参照してください。 –

+0

ありがとう、アンソニーとコーリー。 – user169867

4

は、私は、より複雑なウィジェットプラグインを構築するときに使って実験していますテンプレートです:

(function($){ 

    // configuration, private helper functions and variables 
    var _defaultConfig = { 
     /* ... config ... */ 
     }, 
     _version = 1; 


    // the main controller constructor 
    $.myplugin = function (elm, config) { 

    // if this contructor wasn't newed, then new it... 
    if (this === window) { return new $.myplugin(elm, config || {}); } 

    // store the basics 
    this.item = $(elm); 
    this.config = new $.myplugin.config(config); 

    // don't rerun the plugin if it is already present 
    if (this.item.data('myplugin')) { return; } 

    // register this controlset with the element 
    this.item.data('myplugin', this); 

    // ... more init ... 

    }; 
    $.myplugin.version = _version; 
    $.myplugin.config = function (c) { $.extend(this, $.myplugin.config, c); }; 
    $.myplugin.config.prototype = _defaultConfig; 
    $.myplugin.prototype = { 

    /* ... "public" methods ... */ 

    }; 

    // expose as a selector plugin 
    $.fn.myplugin = function (config) { 
    return this.each(function(){ 
     new $.myplugin(this, config); 
    }); 
    }; 

})(jQuery); 

私はデフォルトの設定とバージョンを上に置きますコードを読んでいる人は探しています。ほとんどの場合、設定ブロックの を調べるだけです。

これは、ウィジェットの「コントローラ」 のコンストラクタとして、$に、コレクションメソッドとして$.fnに「myplugin」を公開します。あなたが見る通り、$.fnメソッドは実際には新しいコントローラをインスタンス化する以外は何もしません。

configはプロトタイプ継承されたオブジェクトで、デフォルトはプロトタイプです。これにより、 の値を$.myplugin.configに割り当てたり、実行中のすべてのプラグインのデフォルト値を$.myplugin.config.prototypeに変更したりすることができます。これには、 が$ .extendでこれらに割り当てられなければなりません。そうしないと、システムが壊れます。より多くのコードでそれを打ち消すことができますが、私は何をしているのかを知ることを好む。 :-)

コントローラのインスタンスは、jQueryのdata()メソッドを使用して要素にバインドされ、実際には同じ要素に対して2回実行されないことをテストするために使用されます(ただし、再構成を許可することもできます)。

// init: 
$('div#myid').myplugin(); 

// call extraMethod on the controller: 
$('div#myid').data('myplugin').extraMethod(); 

このアプローチの最大の欠陥は、それが痛みのビットは、すべてのイベントの割り当てと、「この」文脈を維持することであるということである。

これはあなたのコントローラに以下のインタフェースを提供します。イベントのコンテキストがjQueryに到着するまでは、自由な量のクロージャで処理する必要があります。私はこれを処理するjQueryのUIの方法が最善を動作するように思われることがわかりました

(function($){ 

    // configuration, private helper functions and variables 
    var _defaultConfig = { 
     openOnHover: true, 
     closeButton: '<a href="#">Close</a>', 
     popup: '<div class="wrapper"></div>' 
     }, 
     _version = 1; 

    // the main controller constructor 
    $.myplugin = function (elm, config) { 

    // if this contructor wasn't newed, then new it... 
    if (this === window) { return new $.myplugin(elm, config || {}); } 
    this.item = $(elm); 
    this.config = new $.myplugin.config(config); 
    if (this.item.data('myplugin')) { return; } 
    this.item.data('myplugin', this); 

    // register some events 
    var ev = 'click' + (this.config.openOnHover) ? ' hover' : ''; 
    this.item.bind(ev, function (e) { 
     $(this).data('myplugin').openPopup(); 
    }); 

    }; 
    $.myplugin.version = _version; 
    $.myplugin.config = function (c) { $.extend(this, $.myplugin.config, c); }; 
    $.myplugin.config.prototype = _defaultConfig; 
    $.myplugin.prototype = { 

    openPopup: function() { 
     var C = this.config; 
     this.pop = $(C.popup).insertAfter(this.item); 
     this.pop.text('This says nothing'); 
     var self = this; 
     $(C.closeButton) 
      .appendTo(pop) 
      .bind('click', function() { 
      self.closePopup(); // closure keeps context 
      return false; 
      }); 
     return this; // chaining 
    }, 

    closePopup: function() { 
     this.pop.remove(); 
     this.pop = null; 
     return this; // chaining 
    } 

    }; 

    // expose as a selector plugin 
    $.fn.myplugin = function (config) { 
    return this.each(function(){ 
     new $.myplugin(this, config); 
    }); 
    }; 

})(jQuery); 
0

インスタンスの操作!それはあなたが欲しいものですよね?良い古いファッション、リアルタイムのインスタンス操作。それも私が欲しかったものです。私は同じ質問をして、良い答えをどこでも得ることができませんでした(上記のように)ので、私はそれを考え出した。インスタンスメソッドにアクセスしてjqueryコンシューマに奇妙なものにアクセスする方法についてのラウンドのように思えるので、私のソリューションは気に入らないが、jQueryは最初は奇妙だが素敵だ。その後

var instanceAccessor = {}; 
var pluginOptions = {'accessor':instanceAccessor} 
$('div').myPlugin(pluginOptions); 

:>example、私は次のようでした - 私は、画像をフェードする単純なプラグインを書いたが、私はそれでより多く行うために必要な一度、その後、私はここで、この結果を得るために、ライブインスタンスにメソッドを公開したかったですプラグインの中で、私はこのメソッドに、オブジェクトである 'アクセサ'に渡されたメソッドを追加します。私はこのようなプラグイン内部のメソッドを公開:

instanceAccessor.exposedMethod('somevalue'); 
:私たちは、これは奇妙作らjqueryの前に行うために使用されるように

if (pluginOptions.accessor != null && typeof(pluginOptions.accessor) === 'object') { 
    pluginOptions.accessor.exposedMethod = function (someParam) { 
    // call some private function here and access private data here 
    }; 
} 

次に、このプラグインの消費者は、実行時にインスタンスメソッドまたはメソッドをいつでも呼び出すことができます

jqueryプラグインの検索で「ダム・クロス・フェード」を探して、ダム・プラグインを見つけて自分でコードを見ることができます。ここで

1

は、それが私の感想です:

私はインスタンスオブジェクトを作成するために使用されるクロージャ内のオブジェクトを持っています。インスタンスオブジェクトは、jQueryのdata()メソッドを使用して要素ノードにアタッチされます。これらのインスタンスオブジェクトには、必要に応じて呼び出すことができるパブリックメソッドがあります。

(function($) 
{  
// This is used to create AutoComplete object that are attatched to each element that is matched 
// when the plugin is invoked 
var AutoCompleteEx = function(options, acx) { 

    // PRIVATE VARIABLES 
    var timerID; 
    var input; 

    //Give Div Correct Class & Add <ul> w/ input item to it 
    acx.addClass("autoCompleteEx"); 
    acx.html("<ul><li class=\"input\"><input type=\"text\"/></li></ul>"); 

    //Grab Input As JQ Object 
    input = $("input", acx); 

    //Wireup Div 
    acx.click(function() 
    { 
     input.focus().val(input.val()); 
    }); 


    //Wireup Input 
    input.keydown(function(e) 
    { 
     var kc = e.keyCode; 
     if(kc == 13) //Enter 
     { 

     } 
     else if(kc == 27) //Esc 
     { 

     } 
     else 
     { 
      //Resize TextArea To Input 
      var width = 50 + (_txtArea.val().length*10); 
      _txtArea.css("width", width+"px");  
     } 
    }); 

    // PUBLIC METHODS 

    this.setTimerID = function(id) { 
    timerID = id; 
    }; 

    this.getTimerID = function() { 
    return timerID; 
    }; 

}; 


//Attach this new method to jQuery 
$.fn.autoCompleteEx = function(options) 
{  
    //Merge Given Options W/ Defaults, But Don't Alter Either 
    var opts = $.extend({}, $.fn.autoCompleteEx.defaults, options); 

    //Iterate over the current set of matched elements 
    return this.each(function() 
    { 
     var acx = $(this); //Get JQuery Version Of Element (Should Be Div) 

     // creating a new AutoCompleteEx object and attach to the element's data, if not already attached 
     if (!acx.data('autoCompleteEx')) { 
      acx.data('autoCompleteEx', new AutoCompleteEx(options, acx)); 
     } 

    }); //End Each JQ Element 

}; //End autoCompleteEx() 

//Default Settings 
$.fn.autoCompleteEx.defaults = 
{ 
    minChars: 2, 
    delay:  300, 
    maxItems: 1 
}; 

//End Of Closure 
})(jQuery); 

あなたはこのようなメソッドを呼び出すことができます。

$("div#someDiv").autoCompleteEx(); 
$("div#someDiv").data('autoCompleteEx').setTimerID(123); 
var timerId = $("div").data('autoCompleteEx').getTimerID(); 
console.log(timerId); // outputs '123' 

をそして、あなたは複数のインスタンス化されている場合:

$("div.someDiv").autoCompleteEx(); 
$("div.someDiv").eq(0).data('autoCompleteEx').setTimerID(123); 
$("div.someDiv").eq(1).data('autoCompleteEx').setTimerID(124); 
var firstTimerId = $("div").eq(0).data('autoCompleteEx').getTimerID(); 
var secondTimerId = $("div").eq(1).data('autoCompleteEx').getTimerID(); 
console.log(firstTimerId); // outputs '123' 
console.log(secondTimerId); // outputs '124' 
関連する問題