У меня есть приложение HTML5, которое использует jquery 3.2.1.
В части приложения - функция поиска - я делаю запрос ajax. Ответ от запроса ajax - это HTML, и это включает <script>
который ссылается на файл js, который размещен на том же сервере, что и приложение.
Таким образом, код ajax выглядит так: для создания запроса ajax и записи ответа на div с идентификатором #ajaxContent
:
$.ajax({
url: $('#searchRegulations').attr('action'),
type: 'post',
cache: false,
data: $('#searchRegulations').serialize()
}).done(function (response, status, xhr) {
if (response) {
$('main .content').hide();
$('#ajaxContent').html(response).show();
return false;
}
}
});
Если я проверяю #ajaxContent
я вижу, что <script>
включен в ответ ajax:
Я также проверил вкладку "Моя сеть", чтобы убедиться, что /js/search_regulations.js
загружается правильно, и это дает ответ 200:
Внутри search_regulations.js
есть некоторый jquery, который переключает некоторые фильтры, которые присутствуют в #ajaxContent
.
Проблема в том, что этот код работает только около 50% времени. Когда он будет работать, он переключит состояние некоторых кнопок фильтра, добавив/удалив класс.
.active
для элементов внутри.browse-ctp__filters-data
а затем записывает их в скрытую форму с идентификатором#tmpFilters
.
Чтобы убедиться, что сценарий "стрелял", я ввел в строку console.log('search_regulations.js firing');
и, конечно же, это отображается в консоли каждый раз независимо от того, функционирует ли скрипт или нет.
Что странно, если я вырезал/вставлял код в свою консоль после того, как на страницу была написана ответ ajax, она всегда работает так, как ожидалось.
Это какая-то проблема с тем, как сценарий вводится на страницу?
Я вставил скрипт ниже, но я не думаю, что это проблема с кодом в нем, скорее, как обрабатывается ответ browser/ajax:
$(function() {
console.log('search_regulations.js firing');
/* toggle the active (applied) state on browse by filters */
/* @link https://stackoverflow.com/info/48662677/switch-active-class-between-groups-of-include-exclude-buttons */
$(document).on('click', '.browse-ctp__filters-data .include, .exclude', function(){
var $this = $(this);
// Split name into array (e.g. "find_355" == ["find", "355"])
var arr = $this.attr('name').split('_');
// Toggle active class
$this.toggleClass("active");
if ($this.siblings().hasClass("active")) {
$this.siblings().removeClass("active")
}
// Remove any existing instances of the filter from hidden form
$('#tmpFilters input[value="exclude_'+arr[1]+'"]').remove();
$('#tmpFilters input[value="find_'+arr[1]+'"]').remove();
// If a filter has been applied then add it to hidden form
if ($this.hasClass('active')) {
$('#tmpFilters').append('<input type="hidden" name="tmpFilter[]" value="'+$this.attr('name')+'">');
}
});
});
Заметки о Bounty:
Я предложил щедрость, потому что это не тривиальная проблема, которую нужно решить, - продемонстрировал тот факт, что никто не дал обоснованного ответа. Я ожидаю правильного ответа на:
- Будьте очевидны с помощью jsfiddle или эквивалента.
- Объясните, как это работает.
- Поймите, что ответ ajax - это HTML и js. Js действует на элементы HTML в ответе. Поэтому как HTML, так и js необходимо включить в ответ - в отличие от высказывания "просто добавьте js в глобальный файл" (я не хочу, чтобы js был глобальным, потому что он специфичен для ответа HTML-ответа и могут различаться в разных частях приложения).
- Не следует использовать таймаут (
setTimeout
или что-то еще). Если пользователь взаимодействует с элементами пользовательского интерфейса - например, кнопками - возвращается в ответе HTML до истечения таймаута и, следовательно, js запускается..., что просто приводит к той же проблеме, что и сейчас. Так что это не приемлемое решение, насколько мне известно. - Если эту проблему невозможно решить в HTML5/jquery, объясните, почему и предлагайте любые альтернативные способы ее устранения.
jsfiddle, показывающий тег HTML и скрипта, возвращаемый через ajax:
Несколько человек попросили скрипку или демонстрацию. Нет двух человек, получавших одинаковый результат - и это очень важно, поэтому я не делал этого изначально. #ajaxContent
HTML, который записывается в #ajaxContent
, показан здесь: http://jsfiddle.net/v4t9j32g/1/ - это то, что dev-инструменты в браузере показывают после ответа ajax. Обратите внимание, что длина возвращаемого содержимого может меняться, поскольку это ответ на средство поиска по ключевым словам, которое возвращает загрузку кнопок фильтра. Также обратите внимание, что этот ответ HTML содержит строку <script src="/js/search_regulations.js"></script>
. Именно там находится проблематичное js, и полное содержание этого выше показано в этом вопросе - бит, который включает console.log('search_regulations.js firing')