2012-02-16 13 views
4

我在寫我的第一個jQuery插件。下面是插件的骨架:獲取我的jQuery插件附加到的控件的ID

(function($) { 
    var methods = { 
     init : function(options) { 
      var settings = $.extend({ 
       'id' : '#' + this[0].id, 
       'foo' : 3,  
       'bar' : 4,  
      }, options); 
     } 
    } 

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

附上插件這樣的:

$('#some-id').MyPlugin({ 
    'something' : 'something 
}); 

其中一個網頁上顯示一個控制工作正常,但是當我開始這樣做:

$('#some-id-2').MyPlugin({ 
    'something' : 'something 
}); 

$('#some-id-3').MyPlugin({ 
    'something' : 'something 
}); 

我收到以下錯誤:

Uncaught TypeError: Cannot read property 'id' of undefined 

,因爲我從this得到我的ID,它的計算結果爲[],它代表了我目前不在的頁面上的任何控件!

獲取插件所附控件ID的正確方法是什麼?

非常感謝:)。

+1

你確實需要'id',還是你想要整個選擇器字符串?如果插件應用於一組沒有任何'id'的元素會怎麼樣? – 2012-02-16 13:02:08

回答

11

有這裏有一個根本性的問題:你在想一個單獨的元素。 jQuery全部是關於集合的元素。插件中的this是一個jQuery實例,它可能包含0..n匹配的元素。可能是零,一個,二十三,三十二等等。所以在做一個jQuery插件this[0].id並沒有什麼意義,因爲你只是得到第一個匹配元素的id(如果它有一個;必要條件)或錯誤(如你所發現的),當組中沒有任何元素時。

因此,如果您開始考慮將插件作爲處理集合的匹配元素(可能是空集,小集或大集),那麼您將處於正確的路徑。

這裏有一個具體的例子:我們來編寫一個插件,做了愚蠢的事情:原來的元素(一個或多個)一種顏色,然後在超時後他們將恢復到其原來的顏色。我們將使用這樣的:

$("selector").plugin("newcolor", timeout) 

如果我們在各個元素方面在想,我們的插件將無法正常工作:

// The "foo" plug-in thinks in terms of just one element 
$.fn.foo = function(color, time) { 
    var self, oldColor; 

    self = this; 

    // Save the current color -- this is wrong 
    oldColor = self.css("color"); 

    // Set new color 
    self.css("color", color); 

    // Restore old color after timeout 
    setTimeout(function() { 
     self.css("color", oldColor); 
    }, time); 
}; 

現在讓我們使用它:

$("#theButton").click(function() { 
    $(".foo").foo("blue", 1000); 
}); 

...這個HTML:

<div class="foo">This is the first "foo" div</div> 
<div class="foo" style="color: green">This is the second "foo" div</div> 
<div class="foo" style="color: red">This is the third "foo" div</div> 
<div><input type="button" id="theButton" value="Use foo"></div> 

這裏的問題是,通過考慮一個元素,插件錯誤地保存了第一個元素的顏色;當它恢復原始顏色時,它會將第一個元素的顏色應用於所有其他顏色,這是錯誤的。我們最終得到了三個使用黑色文本的div,其中第二個不應該是黑色。Live example | Source

相反,如果我們認爲以成套方面,我們會做這樣的(例如,不是說這是這個星球上最漂亮的代碼):

// The "bar" plug-in understands sets 
$.fn.bar = function(color, time) { 
    var self; 

    self = this; 

    // Get the current color of each element 
    self.each(function() { 
     var entry = $(this); 
     entry.data("oldColor", entry.css("color")); 
    }); 

    // Set new color 
    self.css("color", color); 

    // Restore old color after timeout 
    setTimeout(function() { 
     self.each(function() { 
     var entry = $(this); 
     entry.css("color", entry.data("oldColor")).removeData("oldColor"); 
     }); 
    }, time); 
}; 

我們將用它像這樣的(基本相同):

$("#theButton").click(function() { 
    $(".bar").bar("blue", 1000); 
}); 

...這個HTML(基本一致):

<div class="bar">This is the first "bar" div</div> 
<div class="bar" style="color: green">This is the second "bar" div</div> 
<div class="bar" style="color: red">This is the third "bar" div</div> 
<div><input type="button" id="theButton" value="Use foo"></div> 

注意它如何通過data來節省每個元素的顏色以及元素本身。恢復時,它會恢復每個元素的顏色。 Live example | Source

+0

明智的答案。不僅爲我提供了一個說明性解決方案,還讓我重新思考了我的插件的一個主要部分。非常感謝。 – ale 2012-02-16 15:49:52

+0

@ vivid-colours:不客氣!很高興這有幫助。 – 2012-02-16 15:51:44

1

你應該實現使用each你的插件,那麼你將不會有問題,空的jQuery對象:

$.fn.MyPlugin = function(method) { 
    this.each(function() { 
    if (methods[method]) { 
     return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 
    } else if (typeof method === 'object' || ! method) { 
     return methods.init.apply(this, arguments); 
    } else { 
     $.error('Method ' + method + ' does not exist on MyPlugin'); 
    } 
    }); 
};