[Решен] [Решено] Drupal.behaviors не работает с модулем UC Ajax Cart

Втр, 10/01/2017 - 11:40

Доброго времени всем. Столкнулся с проблемой, бьюсь третий день, застопорился на одном месте и ни в какую( В гугле скоро забанят, наверное, за чрезмерную активность.)

Суть в следующем: Есть Drupal 7 + Udercart 3 + модуль UC Ajax Cart (он же UC Driven Cart). Модифицировал форму корзины через хук pizznroll_form_uc_cart_view_form_alter, с целью добавить кнопки + и - в строку количества, тут проблем нет, кнопки появились с нужными мне айдишниками. Для управления их поведением использую jQuery, файл скрипта checkout.js загруженный через .info файл темы. Все работает ровно до того момента, пока не нажмешь либо "обновить корзину" либо" удалить строку товара" из корзины, т.е. после выполнения ajax запроса модулем UC Ajax Cart. Нагуглил решение(эту инфу похоже блоггеры просто передирают друг у друга:)) использовать обертку Drupal.behaviors.
Что в итоге получил: никакой разницы. Скрипт отрабатывает только один раз, пробовал писать слово behaviours c ошибкой - скрипт не работает совсем, значит синтаксис верный.

Далее плюнул на страницу корзины, очистил скрипт, убрав всю логику, и сделал просто кусок кода для проверки чтобы посмотреть как он будет работать на других страницах:

(function ($, Drupal)
{Drupal.behaviors.my_theme ={
    attach:function(context, settings){      
     
      //$('#edit-continue-shopping').val('НЕВАЛЯШКА'); // для теста изменим название кнопки "Продолжить покупки"
      $('#edit-continue-shopping', context).val('НЕВАЛЯШКА'); // при загрузке страницы текст меняется, но после первой отработки ajax модуля возвращается в исходное состояние
      $('#ajaxCartToggleView').html('Мусорка'); // переименовал блок корзины, чтобы сразу видеть, что скрипт отрабатывает, эта строка работает, ajax его не обновляет, поэтому текст остается неизменным
      alert('test');   // срабатывает ТОЛЬКО ОДИН РАЗ при загрузке страницы  
    }
  }  
})(jQuery, Drupal);

И вот что обнаружил: на странице ноды, у меня это страница товара, есть радиокнопки выбора атрибутов товара(при изменении атрибута меняется цена с помощью ajax), эта штатная возможность уберкарта, так вот при выборе атрибута, вышеуказанный скрипт нормально отрабатывает, несколько раз выскакивает alert(), т.е. конструкция вполне работоспособна. Но при нажатии кнопки "Добавить в корзину" - ничего не происходит, т.е. товар то в корзину динамически добавляется, но скрипт не запускается, эта кнопка динамически добавляет в корзину посредством модуля UC Ajax Cart, т.е. получается что мой скрипт не дружит с модулем UC Ajax Cart, а с Ubercart работает нормально. Т.е. необходимо как-то заставить скрипт обновляться при изменении страницы с помощью модуля UC Ajax Cart.

Читал про attachBehavior, какие только варианты не перепробовал, никак не хочет работать, чуствую, что решение где-то рядом, но мозг уже взорван на куски,
как это использовать? Есть у кого-нибудь варианты что делать, может кто сталкивался?

0 Спасибо

Лучший ответ

Аватар пользователя petrowsb
2 months 2 недели назад petrowsb #

Работает и так и так, я просто спросил в чем неточность, я пока еще путаюсь в понятиях jQuery.
Исправляю по вашей подсказке и помечаю как окончательное решение.

(function ($, Drupal)
{Drupal.behaviors.my_theme =
  {attach:function(context, settings)
    {
      $(document).ajaxComplete(function(event, xhr, settings) {
             // какой-то код
      });
    }
  }  
})(jQuery, Drupal);
0 Спасибо

Комментарии

Аватар пользователя petrowsb
2 months 2 недели назад petrowsb #

Кажется заработала следующая конструкция:

(function ($, Drupal)
{Drupal.behaviors.my_theme =
  {attach:function(context, settings)
    {
      jQuery(document).ajaxComplete(function(event, xhr, settings) {
      $('#edit-continue-shopping', context).val('НЕВАЛЯШКА'); // работает
      $('#ajaxCartToggleView').html('Мусорка'); // работает
      alert('test');   // работает
      });
    }
  }  
})(jQuery, Drupal);

Подсказку нашел Здесь.

Там сказано, что ajaxComplete начиная с версии jQuery 1.8 должен навешиваться на document. Выставил в конфигурации 1.8 вместо 1.7, очистил кеш и вуаля). Потом поменял снова на 1.7 c очисткой кеша - снова работает. Потом убрал для проверки jQuery(document).ajaxComplete(function(event, xhr, settings) {...}, очистил кеш - не работает. Снова вернул jQuery(document).ajaxComplete, очистка кеша снова заработало. Сегодня еще потестирую, если все нормально, вопрос можно считать решенным. Блин, всегда нужно не забывать чистить кеш, даже если он отключен!

0 Спасибо
Аватар пользователя ХулиGUN
2 months 2 недели назад ХулиGUN #

А нахрена Вы используете jQuery(document), Вы же уже определили для jQuery $ ?

0 Спасибо
Аватар пользователя petrowsb
2 months 2 недели назад petrowsb #

А как правильно сделать, чтобы вышеприведенный код работал?

0 Спасибо
Аватар пользователя ХулиGUN
2 months 2 недели назад ХулиGUN #
petrowsb написал:
А как правильно сделать, чтобы вышеприведенный код работал?

Так Вы ж написали, что работает. Только зачем мешать и jQuery и $?
$(document) вместо jQuery(document) В Вашем случае это наоборот вводит в заблуждение хотя $ = jQuery

0 Спасибо
Аватар пользователя petrowsb
2 months 2 недели назад petrowsb #

Работает и так и так, я просто спросил в чем неточность, я пока еще путаюсь в понятиях jQuery.
Исправляю по вашей подсказке и помечаю как окончательное решение.

(function ($, Drupal)
{Drupal.behaviors.my_theme =
  {attach:function(context, settings)
    {
      $(document).ajaxComplete(function(event, xhr, settings) {
             // какой-то код
      });
    }
  }  
})(jQuery, Drupal);
0 Спасибо
Аватар пользователя postgres
2 months 2 недели назад postgres #

Так как вы делаете - неправильно, работать будет 1 или 2 раза - потом заглохнет.. потому что с каждым откликом вы будете навешивать обработчик еще и еще...
Сделайте так внутри вместо:

jQuery(document).ajaxComplete(function(event, xhr, settings) {
      $('#edit-continue-shopping', context).val('НЕВАЛЯШКА'); // работает
      $('#ajaxCartToggleView').html('Мусорка'); // работает
      alert('test');   // работает
      });
if (!$('#myForm').hasClass('wasInit')){
jQuery(document).ajaxComplete(function(event, xhr, settings) {
      $('#edit-continue-shopping', context).val('НЕВАЛЯШКА'); // работает
      $('#ajaxCartToggleView').html('Мусорка'); // работает
      alert('test');   // работает
      });
    $('#myForm').addClass('wasInit');
}

Суть простая - вы вешаете обработчик еще и еще раз при каждом ajax, а надо только один раз. ПОэтому либо это делать в $(document).ready() (что не Друпал типа вэй)
либо проверять, что инициализация уже была. Вешайте класс на форму и проверяйте его наличие.

0 Спасибо
Аватар пользователя Studio VIZA
2 months 2 недели назад Studio VIZA #
petrowsb написал:
и помечаю как окончательное решение.

Ну почему так? Антон, или вёрсткой разведите кнопочки, или всплывашку с пояснениями дайте, иначе это стодесятый промах, наводящий на мысли о изначально неверной логике.

0 Спасибо
Аватар пользователя ХулиGUN
2 months 2 недели назад ХулиGUN #
postgres написал:
Суть простая - вы вешаете обработчик еще и еще раз при каждом ajax, а надо только один раз. ПОэтому либо это делать в $(document).ready() (что не Друпал типа вэй)

Скажи ка, умник, какая разница между $(document).ready() и (function ($) ? Учи мат часть, бемби

0 Спасибо
Аватар пользователя postgres
2 months 2 недели назад postgres #
написал:
Скажи ка, умник, какая разница между $(document).ready() и (function ($)

зачем говорить, для этого документация есть.
Что касается глобального document - он в захват не попадает, поэтому обработчик на него повесится по любому, после каждого ajax
Понимаешь, нет? нет...

0 Спасибо
Аватар пользователя petrowsb
2 months 2 недели назад petrowsb #

Добавил проверку на класс в рабочем варианте, не буду уже выкладывать, в вашем сообщении все достаточно понятно расписано. Сегодня сдал кровь, чувствую слабость, так что боюсь лишних скобок накопипастить) Кстати эта инфа мне попадалась, пока рылся в поисках ответа:)

Также не буду выкладывать кнопочки, ведь проблема была не в них, тем более что работа еще в процессе, хотя и сдвинулась с мертвой точки, я о них упомянул лишь в контексте проблемы, думал что uc_ajax_cart надо как-то "подключить" к моему скрипту. Наоборот постарался оставить суть.

В любом случае спасибо всем отписавшимся.

PS: надеюсь я правильно сделал, просто добавив [Решено] в заголовок темы) Специальной кнопочки не нашёл)

0 Спасибо
Аватар пользователя negociant
2 months 2 недели назад negociant #
хулиган написал:

Скажи ка, умник, какая разница между $(document).ready() и (function ($) ? Учи мат часть, бемби

$(document).ready(function(){}) просто эквивалентен $(function(){}) https://api.jquery.com/ready/ (обе конструкции по сути являются DOMContentLoaded event listener, но postgres их почему то считает не drupal way),
но не (function($) {})(jQuery) (анонимная самовызывающаяся функция)
Поэтому часто наблюдаю такое недопонимание среди молодежи из-за кажущейся схожести

0 Спасибо
Аватар пользователя postgres
2 months 2 недели назад postgres #

Замечательно :))
Причем тут этот пример, не имеющий отношения к топику?
Где тут у вас в топике применяется $(function(){}) ... мы на разные экраны смотрим? :)))

0 Спасибо
Аватар пользователя bumble
2 months 2 недели назад bumble #

Немного убрался тут.
Господа! Подобные перепалки с элементами флуда - прямая дорога в бан. Напомню, что сроки удваиваются с каждым баном.

Заводите отдельные темы и обменивайтесь "любезностями" там (в рамках Drupal, естественно), ну или в ПМ...

2 Спасибо