не работает trigger()
Добрый день, уважаемые.
Я новичек в JS и в JQuery, соответственно. После изучения JS, решил освоить библиотеку JQuery. Взял книгу Берда Бибо и Иегуды Каца "подробное руководство по продвинутому JavaScript". В конце главы 4 есть пример небольшого приложения. Код взятый из книги работать отказывается. В первую очередь из-за того, что там используются устаревшие функции live(). В общем, пример я чуть подправил, но есть вопрос, который (!) 3ий день не даёт мне покоя. Почему (см. код ниже) при toggle("adjustName") из $(document).on("change", "select.filterChooser", function() { этот самый toggle не вызывается? Т.е. сам нестандартный обработчик при изменении значения в селекте не вызывается и ничего не делает. Я уже всю голову сломал, и контексты перепробовал и delegate пробовал использовать. Специально для проверки работы onChange для селекта выкинул alert. Но, он не выводится при выборе другого элемента в селекте. Моё предположение, что надо как то применять stopPropagation. В общем, помогите, пожалуйста Вот этот код: <script type="text/javascript"> var filterCount = 0; $(document).ready(function() { $("#addFilterButton").click(function() { var filterItem = $("<div>").addClass("filterItem") .appendTo("#filterPane") .data("suffix", "." + (filterCount++)); $("div.template.filterChooser").children() .clone() .appendTo(filterItem) .trigger("adjustName"); }); $("#filterPane").on("adjustName", ".filterItem select.filterChooser", function() { var suffix = $(this).closest(".filterItem").data("suffix"); alert(suffix); if (/(\w)+\.(\d)+$/.test($(this).attr("name"))) { return; } $(this).closest(".filterItem").attr("name",$(this).attr("name")+suffix); }); $(document).on("change", "select.filterChooser", function() { var filterType = $(":selected",this).attr("data-filter-type"); var filterItem = $(this).closest(".filterItem"); $(".qualifier", filterItem).remove(); $("div.template." + filterType) .children() .clone() .addClass("qualifier") .appendTo(filterItem) .trigger("adjustName"); $("option[value='']",this).remove(); }); $(document).on("click", "button.filterRemover", function() { $(this).closest("div.filterItem").remove(); }); $("#addFilterButton").click(); $(document).on("keypress", "input.numeric", function(event) { if(event.which < 48 || event.which > 57) { return false; } }); $(document).on("keypress keyup", "input[name='term']", function() { if($(this).val() != null && $(this).val().length >= 1) { if(!(/^[A-Za-zа-яА-Я0-9\s\"]+$/.test($(this).val()))) { $(this).val( $(this).val().slice(0, -1) ); return false; } } }); $(document).on("keypress keyup", "input.dateValue", function() { if($(this).val() != null && $(this).val().length >= 1) { if(!(/^[0-9\.]+$/.test($(this).val()))) { $(this).val( $(this).val().slice(0, -1) ); return false; } } }); }); </script> <meta charset="utf-8"> </head> <body> <div id="pageContent"> <h1>DVD Ambassador</h1> <h2>Disc Locator</h2> <form id="filtersForm" action="/fetchFilteredResults" method="post"> <fieldset id="filtersPane"> <legend>Filters</legend> <div id="filterPane"> <!-- Сюда будем складывать всё --> </div> <div class="buttonBar"> <button type="button" id="addFilterButton">Add Filter</button> <button type="submit" id="applyFilterButton">Apply Filters</button> </div> </fieldset> <div id="resultsPane"> <span class="none">No results displayed</span> </div> </form> </div> <div id="templates"> <div class="template filterChooser"> <button type="button" class="filterRemover" title="Remove this filter">X</button> <select name="filter" class="filterChooser" title="Select a property to filter"> <option value="" data-filter-type="" selected="selected">-- choose a filter --</option> <option value="title" data-filter-type="stringMatch"> DVD Title </option> <option value="category" data-filter-type="stringMatch"> Category </option> <option value="binder" data-filter-type="numberRange"> Binder </option> <option value="release" data-filter-type="dateRange"> Release Date</option> <option value="viewed" data-filter-type="boolean"> Viewed? </option> </select> </div> <div class="template stringMatch"> <select name="stringMatchType"> <option value="*"> contains </option> <option value="^"> starts with </option> <option value="$"> ends with </option> <option value="="> is exactly </option> </select> <input type="text" name="term"/> </div> <div class="template numberRange"> <input type="text" name="numberRange1" class="numeric"/> <span>through</span> <input type="text" name="numberRange2" class="numeric"/> </div> <div class="template dateRange"> <input type="text" name="dateRange1" class="dateValue"/> <span>through</span> <input type="text" name="dateRange2" class="dateValue"/> </div> <div class="template boolean"> <input type="radio" name="booleanFilter" value="true" checked="checked"/> <span>Yes</span> <input type="radio" name="booleanFilter" value="false"/> <span>No</span> </div> </div> </body> И извините за длинное сообщение =) |
Цитата:
|
Полный код скинул ради полной картины, но хорошо, привожу упрощенный вариант.
Не работает вот это: $("#filterPane").on("adjustName", ".filterItem select.filterChooser", function() { var suffix = $(this).closest(".filterItem").data("suffix"); alert(suffix); if (/(\w)+\.(\d)+$/.test($(this).attr("name"))) { return; } $(this).closest(".filterItem").attr("name",$(this).attr("name")+suffix); }); При вызове вот отсюда: $(document).on("change", "select.filterChooser", function() { var filterType = $(":selected",this).attr("data-filter-type"); var filterItem = $(this).closest(".filterItem"); $(".qualifier", filterItem).remove(); $("div.template." + filterType) .children() .clone() .addClass("qualifier") .appendTo(filterItem) .trigger("adjustName"); $("option[value='']",this).remove(); }); Тега [HTML run] не нашел. Подставил руками - всё вывелось без обработки. |
vertigo,
строки 33 34 35 уберите - замените на иное |
vertigo,
убирать ненадо ))) строка 4 сделайте отмену всплытия $("#addFilterButton").click(function(event) { event.stopPropagation(); |
Цитата:
|
При помощи точек останова понял, что после onChange в селекте нестандартное событие adjustName не вызывается из trigger() вот в этом куске (уже кидал выше):
$(document).on("change", "select.filterChooser", function(event) { event.stopPropagation(); var filterType = $(":selected",this).attr("data-filter-type"); var filterItem = $(this).closest(".filterItem"); $(".qualifier", filterItem).remove(); $("div.template." + filterType) .children() .clone() .addClass("qualifier") .appendTo(filterItem) .trigger("adjustName"); $("option[value='']",this).remove(); }); При этом, если изменить строку 13 из первого поста на вот такую: $(document).on("adjustName", ".filterItem", function() { То alert начинает вызываться. Но, при событии click функция вызываемая обработчиком adjustName вызывается 2 раза, при change от 2 до 5 раз, в зависимости от выбранного элемента в селекте. stopPropagation и stopImmediatePropagation здесь также не помогли. |
Выходит, что количество добавленных элементов напрямую влияет на вызов нестандартного обработчика.
Например, если в селекте выбрать пункт 1 - DVD title, то создадутся 2 элемента, каждый из которых вызовет нестандартный обработчик. Если выбрать Viewed, то он создаст 5 элементов и, опять же, каждый вызовет нестандартный обработчик adjustName. До меня очень долго доходило, что trigger применяется к полученному обернутому набору. А в данном случае этот набор состоит из нескольких элементов. Сделал вот так: $("#addFilterButton").click(function() { var filterItem = $("<div>").addClass("filterItem") .appendTo("#filterPane") .data("suffix", "." + (filterCount++)); $("div.template.filterChooser").children() .clone() .appendTo(filterItem); filterItem.trigger("adjustName"); }); $("#filterPane").on("adjustName", ".filterItem", function() { alert("yes"); var suffix = $(this).data("suffix"); if (/(\w)+\.(\d)+$/.test($(this).attr("name"))) { return; } $(this).attr("name", "filter" + suffix); }); $(document).on("change", "select.filterChooser", function() { var filterType = $(":selected",this).attr("data-filter-type"); var filterItem = $(this).closest(".filterItem"); $(".qualifier", filterItem).remove(); $("div.template." + filterType) .children() .clone() .addClass("qualifier") .appendTo(filterItem); filterItem.trigger("adjustName"); $("option[value='']",this).remove(); }); Вроде, получил то, что хотел. |
Часовой пояс GMT +3, время: 00:38. |