所以我写了一个 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());
});
};