не работает 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, время: 07:32. |