Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   не работает trigger() (https://javascript.ru/forum/jquery/43774-ne-rabotaet-trigger.html)

vertigo 20.12.2013 03:29

не работает 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>


И извините за длинное сообщение =)

danik.js 20.12.2013 06:15

Цитата:

Сообщение от vertigo
И извините за длинное сообщение =)

Не извиняем. Покажи короткий код (несколько строчек), который у тебя не работает. Упрощать умеешь? Чтобы выделить проблему. И пиши [HTML run] вместо [html]

vertigo 20.12.2013 10:42

Полный код скинул ради полной картины, но хорошо, привожу упрощенный вариант.

Не работает вот это:
$("#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] не нашел. Подставил руками - всё вывелось без обработки.

рони 20.12.2013 10:51

vertigo,
строки 33 34 35 уберите - замените на иное

рони 20.12.2013 10:55

vertigo,
убирать ненадо )))
строка 4 сделайте отмену всплытия
$("#addFilterButton").click(function(event) {  event.stopPropagation();

vertigo 22.12.2013 01:15

Цитата:

Сообщение от рони (Сообщение 287992)
vertigo,
убирать ненадо )))
строка 4 сделайте отмену всплытия
$("#addFilterButton").click(function(event) {  event.stopPropagation();

Не помогло.

vertigo 22.12.2013 01:57

При помощи точек останова понял, что после 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 здесь также не помогли.

vertigo 22.12.2013 03:19

Выходит, что количество добавленных элементов напрямую влияет на вызов нестандартного обработчика.

Например, если в селекте выбрать пункт 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.