2014-08-31 45 views
3

我是新創作的jQuery插件,但我有很多使用它們的經驗。有些插件我已經只能以編程方式初始化工作,即創建一個基於HTML類和名稱初始化自己的jQuery插件

$("input[name='blah']").fancyPants(); 

我覺得這樣不方便,但我設法弄清楚如何從教程編寫一個基本的插件,這樣並通過尋找其他插件碼。

其他人,如引導程序的模態分量,可純粹通過標記初始化,即

<input type='text' name='blah' class='fancy-pants'> 

然後就是通過包括插件js文件,與類fancy-pants被自動初始化爲fancyPants插件任何輸入。我喜歡這種行爲,即使我知道它擁有一個特定的類名。

問題1:他們怎麼做到這一點?我通過bootstrap.js看,但似乎有很多我不明白。

問題2: 假設我有一個包含DOM中多個元素的插件。例如,

<button class="bootstrapradio" name="primary_group" value="epicurist"><i class='fa fa-cutlery'></i></button> 
<button class="bootstrapradio" name="primary_group" value="futurist"><i class='fa fa-space-shuttle'></i></button> 
<button class="bootstrapradio" name="primary_group" value="stoic"><i class='fa fa-tree'></i></button>   

<button class="bootstrapradio" name="beverage" value="beer"><i class='fa fa-beer'></i></button> 
<button class="bootstrapradio" name="beverage" value="martini"><i class='fa fa-glass'></i></button> 

在不改變標記結構(如添加的包裝容器),我怎麼能自動初始化我的插件,一個涵蓋了所有的按鈕一類的bootstrapradio和名稱primary_group的兩個實例,另一個涵蓋了所有類別爲bootstrapradio和名稱beverage的按鈕?

編輯:這就是我現在正在工作。

(function ($) { 

    var methods = { 
     init : function(options) { 
      // Initialization method, adds classes to elements and binds events 
      ... 
      return this; 
     }, 
     value : function(new_val) { 
      // Method to get/set value 
      ... 
     } 
    }; 

    $.fn.bootstrapradio = function(methodOrOptions) { 
     if (methods[methodOrOptions]) { 
      return methods[ methodOrOptions ].apply(this, Array.prototype.slice.call(arguments, 1)); 
     } else if (typeof methodOrOptions === 'object' || ! methodOrOptions) { 
      // Default to "init" 
      return methods.init.apply(this, arguments); 
     } else { 
      $.error('Method ' + methodOrOptions + ' does not exist on jQuery.bootstrapradio'); 
     }  
    };  
}(jQuery)); 

我想如何這個插件來改造DOM的一個例子:

document.ready

<button class="bootstrapradio" name="primary_group" value="epicurist" title='Epicurist' disabled><i class='fa fa-cutlery'></i></button> 
    <button class="bootstrapradio" name="primary_group" value="futurist" title='Futurist'><i class='fa fa-space-shuttle'></i></button> 
    <button class="bootstrapradio" name="primary_group" value="stoic" title='Stoic'><i class='fa fa-tree'></i></button>   

    <button class="bootstrapradio" name="beverage" value="beer" title='Beer'><i class='fa fa-beer'></i></button> 
    <button class="bootstrapradio" name="beverage" value="martini" title='Martini'><i class='fa fa-glass'></i></button> 

document.ready

<button class="btn btn-xs bootstrapradio" name="primary_group" value="epicurist" title='Epicurist' disabled><i class='fa fa-cutlery'></i></button> 
    <button class="btn btn-xs bootstrapradio" name="primary_group" value="futurist" title='Futurist'><i class='fa fa-space-shuttle'></i></button> 
    <button class="btn btn-xs bootstrapradio" name="primary_group" value="stoic" title='Stoic'><i class='fa fa-tree'></i></button> 
    <input type="hidden" name="primary_group"> 

    <button class="btn btn-xs bootstrapradio" name="beverage" value="beer" title='Beer'><i class='fa fa-beer'></i></button> 
    <button class="btn btn-xs bootstrapradio" name="beverage" value="martini" title='Martini'><i class='fa fa-glass'></i></button> 
    <input type="hidden" name="beverage"> 
+2

究竟你的意思是什麼初始化? – ArtOfCode 2014-08-31 19:33:30

+0

我想OP想知道如何使用'data-role = modal'和類似的屬性來觸發特定的JS事件。 @ArtOfCode – Newtt 2014-08-31 19:35:34

+0

是的,我明白了,我只是不知道他在這個初始化過程中想做什麼。 – ArtOfCode 2014-08-31 19:37:04

回答

0

嘛,@ ArtOfCode的回答讓我在正確的軌道上。基本上,我最終使用$(document).ready中的.each模式,然後檢查是否爲該元素所屬的指定組添加了隱藏的input字段。這樣,我可以將btn btn-xs類添加到所有元素,但只添加一次隱藏的輸入。

然後,我用init方法保留我的原始代碼,以允許以編程方式初始化插件。

這就是我想出了,我在MIT許可下:)釋放它

https://github.com/alexweissman/bootstrapradio

2

您可以選擇屬性用jQuery這種方式

$("[data-role='modal']"); 

所以,在你的榜樣,你就必須像

$(".bootstrapradio[name='primary_group']").myPlugin(); 
$(".bootstrapradio[name='beverage']").myPlugin(); 

大量的插件都這樣做沒有階級,由具有特定插件的屬性名稱。

一個示例是Lightbox2,它使用$("[data-lightbox]")查找其所有可能的元素,然後根據這些屬性的值將它們分成單獨的lightbox組。

如果您希望自動執行此操作,您只需將相同的功能包裝在插件文件中的文檔中即可。

作爲一個例子,對於該HTML:

<div data-bootstrapradio='type1'></div> 
<div data-bootstrapradio='type1'></div> 
<div data-bootstrapradio='type2'></div> 

而且此Javascript:

$(function(){ 

    $.fn.bootstrapradio = function(params) { 
     return $(this).each(function() { 
      // Your code 
     }); 
    } 

    // Get all the radios on the page currently 
    var $radios = $("[data-bootstrapradio]"); 

    // Get the groupings of them 
    var radioTypes = []; 
    $radios.each(function(i,el){ 
     var type = $(this).attr("data-bootstrapradio"); 
     if (radioTypes.indexOf(type) === -1){ 
      radioTypes.push(type); 
     } 
    }); 

    // Initialize the plugin using all radios of each type 
    for (var i=0; i<radioTypes.length; i++){ 

     var type = radioTypes[i]; 

     var radioGroup = $radios.filter(function(i,el){ 
      return $(el).is("[data-bootstrapradio="+type+"]"); 
     }).bootstrapradio(); 

     // Do whatever else with radioGroup you want for initialization 
    } 

}); 

你用2個bootstrapradios結束,將其用兩個元件初始化的第一,第二,其被初始化爲一個。

+0

好的,但記住我想要構造它,以便用戶不需要編寫任何額外的JS來初始化插件。 – alexw 2014-08-31 19:42:31

+0

對,這裏準備好的文檔在你的插件文件中,並且將在所有這些元素上初始化你的插件,而無需用戶做任何事情。 – iabw 2014-08-31 20:07:24

1

那麼它確實取決於你想要在你的初始化中做什麼。一般來說,我想你將不得不使用帶有一些屬性檢查邏輯和自定義初始化代碼的文檔就緒子句。

下面是jQuery插件的標準結構:

(function($) { 
    $.fn.myPlugin = function(params) { 
     return $(this).each(function() { 
      // do your plugin stuff 
     }); 
    } 
})(jQuery); 

我認爲你必須要修改,以便在文檔準備好了,你的插件初始化,然後也許你仍然希望能夠調用它,您添加功能太:

(function($) { 
    $(document).ready(function() { 
     $(".bootstrapradio").each(function() { 
      if($(this).attr("name") == "primary-group") { 
       // do something specific for name 'primary-group' 
      } 
      else if($(this).attr("name") == "something-else") { 
       // do something else 
      } 
      else { 
       // either catch-all or just drop the element 
      } 
     }); 
    }); 

    $.fn.myPlugin = function(params) { 
     // do your plugin stuff 
    } 
})(jQuery); 

如果要使用現有的init方法,只是給它的名字,那就更簡單了:

(function($) { 
    var self = this; 

    $(document).ready(function() { 
     $(".bootstrapradio").each(function() { 
      self.methods.init($(this).attr("name")); 
     }); 
    }); 

    $.fn.myPlugin = function(params) { 
     // do your plugin stuff 
    } 
})(jQuery); 

self對於您在此處訪問正確的範圍非常重要。

此外,您當前的代碼有語法錯誤。你的最後一行:

}(jQuery)); 

應該是:

})(jQuery); 

編輯:值得一提的是,最後一點實際上不是畢竟一個語法錯誤,按照下面的評論鏈接的article。要麼工作。

+0

請參閱http://benalman.com/news/2010/11/immediately-invoked-function-expression/ at「Immediately-Invoked Function Expression(IIFE)」 – guest271314 2014-08-31 19:54:14

+0

我認爲我們已經開始到達那裏,但如果我希望它對任何任意'name'd元素進行操作?我試圖弄清楚如何將$(this).attr(「name」)'傳遞給我的'init'方法。這會起作用嗎? – alexw 2014-08-31 20:01:00

+0

很容易傳入。你想用它做什麼?如果你想用不同的名字做不同的事情,你就會被if-else語句所困住。 – ArtOfCode 2014-08-31 20:06:53

0

嘗試(這種模式)

// hold jquery `ready` event until `plugin` "ready" 
$.holdReady(true); 
$(function() { 
    // `deferred` until _after_ `plugin` defined , 
    // `ready` `hold` `resolved` within `plugin` 
    $.bootstrapradio().css("font-size", "24px") 
}); 

// `plugin` 
(function($, window, undefined) { 
    // define `plugin` as `function` and `object` 
    // check document for `bootstrapradio` `class` elements , 
    // if true , proceed , if not , 
    // create empty jquery object , proceed 
    // define logic checks for elements , objects , other 
    // in window , document , other 
    $.fn.bootstrapradio = $.bootstrapradio = function(options) { 
     $elems = $(".bootstrapradio").is("*") ? $(".bootstrapradio") : $({}); 
     // settings 
     $.bootstrapradio.settings = { 
      "primary_group" : "green" 
      , "beverage" : "blue" 
     }; 
     // extend settings to options 
     var options = $.extend($.bootstrapradio.settings, options); 
     // do stuff 
     // e.g., apply `settings`/`options` to `$elem` 
     // based on `name` , `value` attributes in `html` 
     $elems.each(function(k, v) { 
      $.each(options, function(_name, _value) { 
       if (_name === v.name) { 
        $(v).html(v.value).css("color", _value) 
       } 
      }) 
     }); 
     // return `$elems` 
     return $elems; 
    } || {}; 
    // call `plugin` 
    $.when($.bootstrapradio()) 
    .done(function(_$elem) { 
     // check if `plugin` type cast 
     // to both `function` and `object` , 
     // redundant check if `plugin` `in` window 
     if (typeof $.fn.bootstrapradio === "function" 
      && typeof $.bootstrapradio === "object" 
      && $.bootstrapradio in window) { 
       // resolve jquery `ready` (`document.ready`) `hold` , 
       // do other stuff , 
       // e.g., `$.bootstrapradio().css("font-size", "24px")` 
       $.holdReady(false); 
     }; 
    }) 

}(jQuery, window)); 

的jsfiddle http://jsfiddle.net/guest271314/f2asu701/

相關問題