Мне нужно выполнить скрипт при загрузке страницы, но он выполняется при ajax действиях.

Главные вкладки

Аватар пользователя VasyOK VasyOK 7 мая 2023 в 12:50

Приветствую специалистов по фронтенду.

Есть скрипт. Перемещает элемент в другое место:

script.js

(function($) {
    Drupal.behaviors.mytheme1Behavior = {
        attach: function(context, settings) {

            $(".element").prependTo($("#another-place"));        

        }
    };
})(jQuery);

mytheme.libraries.yml

scripts_library:
  version: 1.x
  js:
    js/script.js: {}
  dependencies:
    - jquery_ui/core

Все работает, но при любом действии с ajax на странице (пейджер, фильтры) скрипт выполняется еще раз, т. е. элемент еще раз перемещается. Как этого избежать?

Комментарии

Аватар пользователя VasyOK VasyOK 7 мая 2023 в 18:14

так?

 dependencies:
    - core/jquery.once

или так (там вроде измениния какие-то обозначились https://drupalbook.org/blog/replace-jqueryonce-javascript-once-drupal-10 ):

 dependencies:
    - core/once

А в самом скрипте изменения делать? Спрашиваю потому как пока не получилось. Специально простейший скрипт для примера взял.

Аватар пользователя EvgenySorokin EvgenySorokin 7 мая 2023 в 18:50

По ссылке для друпал 10, а для 9ки, если весь депенденс приводить, то скорее всего, будет как-то так:
dependencies:
- core/jquery
- core/jquery.once
- core/drupal

Сам js, из реального проекта пример:

$('header', context).once('.region-header').each(function() {
//внутри весь код будет выполняться один раз
});

Все это внутри правильного друпальского js behaviors, вместо элементов header и .region-header - указываете свои, которые только один раз на странице присутствуют.

Аватар пользователя VasyOK VasyOK 7 мая 2023 в 21:18

Так (?):
mytheme.libraries.yml

scripts_library:
  version: 1.x
  js:
    js/script.js: {}
  dependencies:
   - core/jquery
    - core/jquery.once
    - core/drupal

script.js

(function($) {
    Drupal.behaviors.mytheme1Behavior = {
        attach: function(context, settings) {

           
            $('body', context).once('body').each(function() {
                $("#old-place .element").prependTo($("#another-place"));        
                $("#old-place .element").remove(); /* не работает эта инструкция */
            });

        }
    };
})(jQuery, Drupal, once); /*Это надо в скобки добавлять?*/

Как было с кодом, что в шапке:
элемент перемещался в другое место, после перехода ajaх-ом на другую страницу элемент дублировался в другом месте.
Как сейчас:
элемент перемещается в другое место, после перехода на другую страницу, он и на новом и на старом месте Sad

Аватар пользователя EvgenySorokin EvgenySorokin 7 мая 2023 в 21:56

VasyOK wrote: Так (?):

Да так, только лишние пробелы убрать нужно, чтобы лесенки не было.

Нужен ли once в js в конце - я не уверен, но и без него работает, вот полный вариант, можно попробовать через клонирование элемента:

(function ($, Drupal) {

  'use strict';

  Drupal.behaviors.theme = {
    attach: function (context, settings) {

      $('body', context).once('body').each(function() {

        let slogan = $('.#old-place .element').clone();
        $(slogan).prependTo($("#another-place"));
        $('#old-place .element').remove();

      });

    }
  };

})(jQuery, Drupal);

Если этот кусок кода в "$('body', context).once..." один раз отрабатывает, то именно к однократному запуску js вопросов быть не должно - это само по себе работает. А дальше разные варианты могут быть, почему, например, не удаляется - для анонима это или для авторизованного? Если ли разница? Если для анонима и все кеши включены, то этот блок может загружаться через js, тогда не

$("#old-place .element").remove();

а, проверить такой вариант -

$(document).find("#old-place .element").remove();
Аватар пользователя VasyOK VasyOK 8 мая 2023 в 11:12

Точно также. Элемент в другое место переставвляет, но после перехода по страницам - первоначальный остается в секции #old-place.

ни так не работает
$("#old-place .element").remove();
ни так
$(document).find("#old-place .element").remove();
ни у админа ни у анонимуса

Аватар пользователя EvgenySorokin EvgenySorokin 8 мая 2023 в 12:18

А если вместо .remove что-то другое делать - скрывать .hide или стилями бордер добавить, то это работает? Элемент на странице находится или нет?

Аватар пользователя VasyOK VasyOK 9 мая 2023 в 0:09

Немного проясню ситуацию.

При ajaх-листании страницы вьюхи ВНУТРИ обновляемой области находится #old-place .element.

EvgenySorokin, предложенное тобой решение - работает. 2й раз действие не происходит.
Но т.к. элемент находится ВНУТРИ - то он просто подгружается ajaх-ом. Поэтому он и виден на старом месте. И никакие .remove() или .hide() на него не действуют.

От как по уму с этим элементом работать? Стилями конечно могу скрыть.

Аватар пользователя EvgenySorokin EvgenySorokin 9 мая 2023 в 7:41

Если скрипт выполняется 1 раз, то при листании чего-то на ajax он выполняться второй, третий, n-ный раз не будет, и соответственно, элемент удален следующие разы не будет. Если при каждом ajax запросе это удаление должно происходить, то скрипт нужно каждый раз выполнять, а не один раз.
Про document.find уже писал, если вдруг обычный выбор элемента не работает.

Попробуйте вынести в функцию удаления за пределы кода, который 1 раз выполняется, чтобы при каждом ajax он срабатывал.

Аватар пользователя VasyOK VasyOK 9 мая 2023 в 11:57

Мне кажется чтобы скрипт срабатывал , его нужно вызывать прямо в области обновляемой с ajaх.
А как это сделать?
Внутри шаблона вьюхи сделать ссылку на js файл? А как тогда dependencies для этого js файла указать?