Commerce + Infinite Scroll

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

Аватар пользователя noobishe noobishe 25 марта 2016 в 17:03

Здрасти.
Может кто сталкивался, поскажите, пожалуйста.
Установлен коммерц, каталог вывожу через въюху. Хочу чтоб товары подгужались динамически. Ставлю инфинити скролл - вид приобретает как раз такой как хотел, но кнопка добавления товара в корзину у тех товаров, что подгружаются после, при помощи скролла не работает. А именно, при нажатии на нее, на белой страничке показывает мне

[{"command":"settings","settings":{"basePath":"\/","pathPrefix":"","ajaxPageState":{"theme":"ТЕМА","theme_token":"ТОКЕН"},"fancybox":[]},"merge":true}]

ну это ответ от views/ajax

Делаю альтер на форму добавления в корзину(или меняю жаваскриптом. результат один), чтоб экшен в форме был корректный - в результате сабмит не срабатывает, а кнопочка просто перезагружает страничку.

Сразу оговорюсь, аждакс к форме пока не прикручивал.

Кто нибудь скрещивал их или может есть более разумное решение??

Комментарии

Аватар пользователя noobishe noobishe 26 марта 2016 в 17:04

jquery_update установлен
в консоле никаких ошибок нет

Quote:
Views Load More нормально работает с Drupal.settings

В чистом виде Views Load More ведет себя так же.
может нужно что то дописать в форму? ну там пересобрать сеттингс, например?

Аватар пользователя noobishe noobishe 26 марта 2016 в 17:06

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

Аватар пользователя Andruxa Andruxa 26 марта 2016 в 19:28

Странная ситуация. Тут, однако, дебажить надо (с).
Но вместо траты времени на отладку форм, я бы посоветовал потратить его на отказ от форм добавления в корзину.

Дело вот в чем:
В друпале каждая форма имеет токен, сгенерённый на основании id сессии юзера. При сабмите формы токен сравнивается с данными из кеша форм, и в случае несовпадения - сабмит не обрабатывается.
Это, в общем-то, логично: надо добавить товар в корзину именно того юзера, который кликнул на кнопку добавления, при этом этот юзер может быть (и скорее всего - будет) анонимом, т.е. его uid=0, поэтому юзеры различаются по id их сессий.
При этом, показывая юзеру каталог из, допустим, 100 товаров - в кеш форм помещается 100 форм (и 100 форм стейтов) для одного юзера. При посещаемости 100 уников в сутки, кеш форм растёт со скоростью 100х100х2 (форма + её состояние) = 20000 записей в сутки.
При этом, невозможно кешировать страницы каталога - т.к. закешированая страница будет содержать формы с токенами на основании id сессии определённого юзера, и сабмит этих форм другими юзерами работать не станет.
В общем, моё мнение - формы добавления в корзину это плохо.

Чем тратить время на разбор полётов с формами, лучше сделать контейнер, содержащий id товара / id дисплея, при клике на который - дёргать аяксом коллбек на сервере, который будет добавлять товар в корзину.
Я делал такой коллбек как отдельный ресурс для Services, но можно и через hook_menu().
Код коллбека - чуть менеее, чем полностью был позаимствован из commerce_cart_add_to_cart_form_submit()

Аватар пользователя noobishe noobishe 27 марта 2016 в 14:47

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

Аватар пользователя noobishe noobishe 27 марта 2016 в 11:52

Спасибо, за разъяснение.
С формами разобраться всетаки стоит, ну или обработчик вешать именно на кнопку, чтоб при отключенном жаваскрипте все продолжало работать...

Аватар пользователя sas@drupal.org sas@drupal.org 28 марта 2016 в 9:36

не прикручивается обрабочик = 100%, решение лежит в плоскости .on , но там есть тонкости правильного использования, если не хотите заворачиватся, то используйте событие .on("DOMNodeInserted"

Аватар пользователя noobishe noobishe 30 марта 2016 в 23:13

Не удалось вообще никак до сабмита достучаться, пришла в голову такая мысль...
Если сделать так, какие проблемы могут быть?
я понимаю что выглядит странно, зато работает везде, включая инфинитискролл, можно добавлять аджаксовые команды и вроде с кешем все ок должно быть.


<?php
function commerce_custom_ajax_add_to_cart_menu() {
    return array(
        
'add_to_cart' => array(
            
'page callback' => 'add_to_cart',
            
'type' => MENU_NORMAL_ITEM,
            
'access callback'=>true,
        ),
    );
}

function 

commerce_custom_ajax_add_to_cart_form_alter(&$form, &$form_state$form_id) {
    if (
strpos($form_id'commerce_cart_add_to_cart_form') !== FALSE) {
        
$form['submit']['#attributes']['class'][] = 'use-ajax-submit';
        
$form['submit']['#id'] = 'sub_'.$form['#id'];
        
$form['#attached']['library'][] = array('system''jquery.form');
        
$form['#attached']['library'][] = array('system''drupal.ajax');
        
$form['#action'] = url('add_to_cart');
    }
}

function 

add_to_cart(){
    global 
$user;
    
$product commerce_product_load($_POST['product_id']);
    
$line_item commerce_product_line_item_new($product$_POST['quantity']);
    
$product_nid db_select('field_data_field_product''f')
        ->
fields('f', array('entity_id'))
        ->
condition('f.bundle''product_display')
        ->
condition('f.field_product_product_id'$_POST['product_id'])    
        ->
range(01)
        ->
execute()
        ->
fetchField();
    
$line_item->commerce_display_path['und'][0]['value'] = drupal_get_path_alias('node/'.$product_nid);
    
commerce_cart_product_add($user->uid$line_item);

    

$headers apache_request_headers();
    if (
strpos($headers['Accept'], 'javascript') !== FALSE){
        
$result = array(
            
'#type' => 'ajax',
            
'#commands' => array(),
        );
        
drupal_get_messages();
        
ajax_deliver($result);
        
drupal_exit();
    }
    else{
        
drupal_goto($_SERVER['HTTP_REFERER']);
    }
}
?>
Аватар пользователя Andruxa Andruxa 31 марта 2016 в 2:17

Осталось выбросить форму - и будет совсем хорошо.


Несколько замечаний:
'type' => MENU_NORMAL_ITEM,
надо
'type' => MENU_CALLBACK,


$product_nid = db_select
красивее через EntityFieldQuery


$line_item->commerce_display_path['und'][0]['value'] = drupal_get_path_alias('node/'.$product_nid);
я бы хранил системный путь вместо алиаса: он может измениться и ссылка на дисплей станет битой. Алиас лучше генерить "на лету" при каждом обращении к line item.