そこで、select要素を同じ機能を持つスタイル可能なdivとulに変換するjqueryプラグインを作成しました。以前は、次のように、各select要素を個別に呼び出していました。
$("#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])
期待どおりに各要素のログを取得します。ループを停止するのは、そのうちの1つで自分の内線番号を呼び出すまではありません。
誰かが私にこの振る舞いを説明してもらえますか?
必要に応じて、これが私のプラグインコードです。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());
});
};