Выполнение JavaScript при добавлении виджета в бэкэнд

20

У меня есть виджеты, к которым прикреплены элементы управления JavaScript.

Если виджет присутствует при загрузке страницы администратора виджета, элементы управления работают правильно.

Когда я добавляю новый виджет, они не работают правильно, я получаю разметку, но никакие события javascript не вступают в силу.

Если я сохраню новый виджет, то при перезагрузке формы элементы управления будут созданы правильно и теперь будут работать.

Обновление страницы также устраняет проблему, но только для существующих виджетов. Новые виджеты имеют эту проблему до сих пор.

В частности, я запускаю выборку на выбранных входах в этих точках:

  • документ готов
  • Ajaxcomplete

Я проверил, что мой код запускается для каждого события по желанию, но результаты не такие, как ожидалось.

Вот тестовый плагин, который демонстрирует проблему:

https://gist.github.com/Tarendai/8466299

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

Примечания:

  • Когда страница виджета загружается, я вижу увеличение счетчика в консоли JS, как и ожидалось
  • Когда я добавляю новый виджет, код запускается, однако он не может найти какие-либо элементы выбора, на которых он может работать, как показано в find.length, равном 0. Это не должно иметь место, так как каждый новый виджет этого типа должен есть элемент select
  • У элементов select есть класс для их идентификации, этот класс удаляется после применения библиотеки selectize для предотвращения дублирования и повторной обработки в существующих виджетах.
  • До использования selectize я использовал Select2, который имел ту же проблему
  • Комментируя код AJAX, я ожидаю, что новые виджеты будут иметь стандартный ввод select. Они не. Я не знаю, почему это так

Итак, как мне заставить работать элемент управления selectize, не сказав пользователю обновить или нажать «сохранить» перед внесением изменений?

Том Дж Новелл
источник
Это проблема делегирования события. Вам нужно будет изучить использование .on()метода jQuerys . Что требует от вас привязать событие к документу. Однако какое событие будет уместным, я не уверен прямо сейчас. В конечном итоге это потому, что ваши исходные привязки представляют начальную версию DOM, когда страница была загружена, и по большей части не видят новые элементы (содержимое виджетов), которые добавляются через ajax. Надеюсь, это укажет вам правильное направление, если нет, я смогу ответить лучше, когда буду на работе.
Это то, что я ожидал, и почему я добавил jQuery( document ).ajaxStop( function() {часть, чтобы я мог инициализировать элементы управления во вновь загруженных виджетах. Однако, если бы я удалил эту строку, я ожидал бы, что новые виджеты будут иметь стандартные входные данные выбора HTML, но они не = s
Том Дж Новелл
Как @ комментирует Арон-Холбрук, его подход является чистейшая один, используя widget-updatedи widget-addedсобытия. Также я хочу подчеркнуть в коде @michaeljames использование идентификатора элемента #widgets-right. Обязательно используйте его для нацеливания на активные элементы виджетов внутри вашего JS-кода, иначе вы можете получить дубликаты элементов, так как ваш код может также выбрать скрытые неактивные элементы виджета в левой части экрана (и те будут клонированы при добавлении виджета).
Жюльен

Ответы:

12

Отличные новости,

Я исправил это.

Извиняюсь за то, что упустил ваш смысл в моем первоначальном комментарии и дал вам ответ, который вы уже реализовали Это научит меня отвечать по телефону, пока я в поезде!

Вы используете ajaxstop правильно. Черт, JS по большей части работает правильно, вы могли видеть инициализируемые стили CSS и изменения в DOM.

На самом деле проблема заключается в вашем селекторе.

Это связано с тем, что содержимое виджета не загружается через ajax, на самом деле оно клонирует его из левого столбца, где он скрыт, а затем запускает вызов ajax для сохранения позиции виджета в правом столбце. Это объясняет, почему ajaxstop создает удовольствие, даже если клонированное содержание. Однако, поскольку в левом столбце есть скрытая версия виджета, ваш JS создает для этого экземпляр. Таким образом, когда вы перетаскиваете его в правый столбец, вы получаете искаженный клон скрытого виджета.

Таким образом, вам нужно выбрать тот, что слева. Ниже приведен исправленный код:

<script>
jQuery( document ).ready( function( $ ) {
    function runSelect() {
        var found = $( '#widgets-right select.testselectize' );
        found.each( function( index, value ) {

            $( value ).selectize();
                .removeClass( 'testselectize' )
                .addClass( 'run-' + window.counter );

            console.log( $val );
            window.counter++;
        } );
    }

    window.counter = 1;

    runSelect();

    $( document ).ajaxStop( function() {
        runSelect();
    } );
} );
</script>
кайзер
источник
Боже мой, мне нужно пойти проверить это <3
Том Дж. Новелл
Очень элегантное решение для головной боли!
Боско
3
Я бы посоветовал не запускать каждое отдельное событие «ajaxStop» и вместо этого предлагать использовать как «добавленные виджеты», так и события «обновленные виджеты».
Tyrun
16

Как заметил @ aaron-holbrook, более чистый подход заключается в следующем:

jQuery(document).on('widget-updated widget-added', function(){
    // your code to run
});

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

function handle_widget_loading(){
   // your code to run
}
jQuery(document).ready( handle_widget_loading );
jQuery(document).on('widget-updated widget-added', handle_widget_loading );

Просто вставьте сюда для справки, так как ответы намного легче найти, что комментарии

chifliiiii
источник
2
вероятно, следует использовать jQuery вместо $
Марк Каплун