0

所以我写了一个 jquery 插件,它可以将选择元素转换为具有相同功能的可样式化 div 和 ul。我以前单独调用每个选择元素,如下所示:

$("#myElementId").selectList();

但是现在我决定我希望能够将“selectList”类添加到选择列表中,然后使用 selectList 类遍历所有元素并将它们转换为动态元素,如下所示:

var selects = $(".selectList");
for (i=0,j=selects.length;i<j;i++){
    $(selects[i]).selectList();
}

效果很好,但仅适用于第一个元素。出于某种原因,一旦 .selectList() 被调用,它就会结束我的 for 循环,并且永远不会进行下一次迭代。我不知道为什么。我已经验证它$(".selectList")确实比 1 长,并且如果我在循环中什么都不放,除了console.log(selects[i])我按预期得到每个元素的日志。直到我在其中一个上调用我的扩展程序,它才停止循环。

有人可以向我解释这种行为吗?

如果您需要,这是我的插件代码。请不要在 js 文件的评论中重新分发或重用我:

// Custom select element functionality.
jQuery.fn.selectList = function(){

// Grab the original select element and it's options
var originalSelect = this;
var originalOptions = originalSelect.children("option");
var originalId = originalSelect.attr("id");

// Set the original select item to be hidden
originalSelect.css({"display": "none !important"});

// Set up our replacement block
var newContainer = "<div class='selectList_container' id='" + originalId + "_selectList' tabindex='0'>" + 
                      "<p class='selectList_value'>" + $(originalOptions[0]).html() + "</p>" + 
                      "<div class='selectList_optionsWrapper' style='height: 0 !important'>" + 
                         "<ul class='selectList_options' style='display: none;'></ul>" + 
                      "</div>" + 
                   "</div>";

// Append it to the original container
$(newContainer).insertAfter(originalSelect);

// Set up our new variables.  All references from here on in the script will reference the existing element already added to the document.
newContainer = $("#" + originalId + "_selectList");
var newValue = newContainer.find(".selectList_value");
var newList = newContainer.find(".selectList_options");
var newItems;

// Function to toggle the list
var toggleList = function(){
    newList.toggle();
};

// Create our options and add them to our new list
for (i=0, j=originalOptions.length; i<j; i++){

    // Get original option values
    var thisOption = $(originalOptions[i]);
    var optionText = thisOption.html();
    var optionValue = thisOption.val();

    // Build out our new item
    var newItem = "<li name='" + optionValue + "'";

    // Add a class of first and last to the first and last options to aid in styling
    if (i == 0) {
        newItem += " class='first' ";
    } else if (i == (j-1)){
        newItem += " class='last' ";
    };

    // Close out our new item
    newItem += ">" + optionText + "</li>";

    // Add our new item to the newItems string to be added to the dom later
    newItems += newItem;
};

// Add our new item to the list we've made
$(newItems).appendTo(newList);

// Reference to the new list items
var newOptions = $("#" + originalId + "_selectList .selectList_options li");

// Default CSS values for our new dom elements
newContainer.css({position: "relative"});
newValue.css({cursor: "pointer", display: "block", "text-align": "left"});
newList.css({margin: "0 auto", "z-index": "9999999"});
newOptions.css({cursor: "pointer", display: 'block'})

// Opens and closes the new select list when the select value is clicked on
newValue.click(toggleList);

// Closes the list if the select element loses focus (mimics default select element behavior).
// In order for this to work, the element the blur event listener is being bound to must have the attribute tabIndex=0.
// This tricks the browser into thinking it is a form element, otherwise blur will not fire.
newContainer.blur(function(){
    // This is in a setTimeout function because of the way IE detects the blur. 
    // 150ms is seamless to the end user but upholds the functionality in IE.
    window.setTimeout(function hide_list(){
        if (newList.is(":visible")) {
            toggleList();   
        };
    },150);
});

// Changes the value of our new select value and activates the old select option when one of our new list items is clicked
for (i=0, j=newOptions.length; i<j; i++) {
    $(newOptions[i]).click(function(){
        var thisText = $(this).html();
        var thisValue = $(this).attr("name");

        newValue.html(thisText).attr({"name": thisValue});
        newList.toggle();
        originalSelect.val($(this).attr("name")).trigger('change');
    });
};

// Make sure if the original select list changes without the use of our new elements, that the new elements stay updated.
this.change(function(){
    newValue.html($(this).find("option:selected").text());
});
};
4

3 回答 3

1

如何使用$.each当前上下文使用它应该有帮助..

$(".selectList").each(function() {

   $(this).selectList()

});

可能将其转换为 DOM 元素selects[i]似乎正在造成问题..

于 2012-11-12T18:39:08.260 回答
1

Look at the authoring plugin guide. You need to use this.each within your plugin to loop over selected elements and return this so as to maintain chainability.

$.fn.selectList = function() {  

   return this.each(function() {
     var $this = $(this);
   }); 

};
于 2012-11-12T18:41:35.330 回答
0

您应该将所有代码应用到

$.fn.selectList = function() { 
         this.each(function() {
  :
   //your code
   :
         });
}

块以确保它适用于选择器中的所有元素。在 each() 循环中,此关键字将使您可以访问单个项目。

参考:http ://docs.jquery.com/Plugins/Authoring

于 2012-11-12T18:42:33.033 回答