1

I am trying to create "quick buy" functionality. I have a product listing and a customer is able to click on "quick buy" for that product and then I want to be able to load up a view mode for that product display in an overlay which has a few product display fields including the add to cart field.

I can get the loading of the product display via jQuery load (or ajax) no problem, the issue is that the add to cart button is not working via ajax and the customer is instead redirected to the callback (which is now the action in the add to cart form).

Javascript code to load product display node:

$('.quick-buy:not(.ajax-processed)').addClass('ajax-processed').click(function(e) {
  e.preventDefault();
  $.ajax({
    url: '/product/get/ajax/'+$(this).attr('rel')
  }).done(function(result){
    $('#quick-buy').html(result);
    Drupal.attachBehaviors();
  });
});

Module code:

function tweaks_menu() {
  $item['product/get/ajax/%'] = array(
    'page callback' => 'tweaks_get_product_ajax',
    'page arguments' => array(3),
    'access arguments' => array('access content'),
  );
  return $items;
}

function tweaks_get_product_ajax($nid) {
  $node = node_load($nid, NULL, false);
  $node_view = node_view($node, 'product_quick_buy');
  $html = drupal_render($node_view);
  print $html;
}

I have also tried:

function tweaks_get_product_ajax($nid) {
  $node = node_load($nid, NULL, false);
  $node_view = node_view($node, 'product_quick_buy');
  $html = drupal_render($node_view);

  $settings = FALSE;
  $javascript = drupal_add_js(NULL, NULL);

  if (isset($javascript['settings'])) {
    $settings = '<script type="text/javascript">jQuery.extend(Drupal.settings, ';
    $settings .= drupal_json_encode(call_user_func_array('array_merge_recursive', $javascript['settings']['data']));
    $settings .= ');
  }

  print $html . $settings;
}

...to no avail.

1
  • This is just a guess, I've never used Commerce before. Maybe your javascript ajax code is stripping out scripts. So if the page that you're calling via ajax is using a javascript code, then that explains why it's not working. If this is the case, you would have to add something to your code so it allows to pass scripts.
    – No Sssweat
    Commented May 13, 2015 at 3:09

2 Answers 2

0

The reason why it redirects after adding to cart is because the add to cart form doesn't use ajax by default. Wich causes it to redirect the user when submitted. If you want it to use ajax you'll have to alter the submit button via a HOOK_form_FORM_ID_alter.

For more info on the form ajax functionality
FAPI ajax

However by doing so you'll alter all the add to cart button forms on your entire website to use ajax.

So a better solution might be to create a custom add to cart form just for the product_quick_buy view-mode and display that instead of the standard form. This form can then use ajax to call it's submit handler.

Also I think your ajax link implementation for the hook_menu doesn't follow the coding standards.

function tweaks_menu() {
  $item['product/get/ajax/%'] = array(
    // -- your code -- 
    'delivery callback' => 'ajax_deliver', // Tells drupal we'll be returning an ajax renderable array
  );
  return $items;
}

function tweaks_get_product_ajax($nid) {
  $node = node_load($nid, NULL, false);
  $node_view = node_view($node, 'product_quick_buy');
  $html = drupal_render($node_view);
  // Instead of printing we're generating an ajax renderable array and return that
  $commands[] = ajax_command_html('YOUR_JQUERY_SELECTOR_HERE', $html); 
  return array('#type' => 'ajax', '#commands' => $commands); 
}

More info about ajax links Tutorial on ajax links

1
  • This is kind of what I did in combination with the commerce_ajax_cart module. Thanks.
    – tzm
    Commented May 13, 2015 at 8:49
0

Ok, so there were a number of things I did to get it working, mainly with hints from:

load Ajax form in another page

Firstly, I forgot to mention that I have commerce_ajax_cart module installed which makes the add to cart buttons work with ajax.

Next, my ajax callback looks like this (super basic):

function tweaks_get_product_ajax($nid) {
    $node = node_load($nid, NULL, false);
    $nv = node_view($node), 'product_quick_buy');
    $html = drupal_render($nv);
    print $html;

}

Now I found that since there are other forms on the page I had to make sure the form didn't clash with any others so I have the following hook function:

function tweaks_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state) {
    if (stristr($form['#action'], '/product/get/ajax') !== FALSE) {
        $form['#attributes']['id'] = 'quick-buy-form';
        $form['submit']['#attributes']['id'] = 'quick-buy-submit';
        $form['submit']['#ajax']['callback'] = 'tweaks_quick_buy_callback';

    }

}

Then I copied the the commerce_ajax_cart_callback function and added in a call to my own javascript function:

function commerce_ajax_cart_callback($form, &$form_state){
    global $user;

    $form = drupal_rebuild_form($form['#form_id'], $form_state, $form);

    $commands = array();
    $commands[] = array('command' => 'commerce_ajax_cart_update') ;
    $commands[] = ajax_command_prepend('#block-system-main', theme('status_messages'));
    $commands[] = ajax_command_replace('.' . drupal_html_class($form['#form_id']), drupal_render($form));
    $commands[] = array(
            'command' => 'commerceAjaxCartFireTrigger',
            'data'    => $form['#form_id']

            );
    $commands[] = array(
            'command' => 'plQuickBuy',

            );

    return array('#type' => 'ajax', '#commands' => $commands);

}

I also had to add in the following to my template.php to get the drupal ajax form libraries into the page:

function main_preprocess_html(&$variables) {
    drupal_add_library('system', 'drupal.ajax');
    drupal_add_library('system', 'drupal.form');
    drupal_add_library('system', 'jquery.form');
    drupal_add_library('system', 'druapl.progress');

}

Lastly here is my updated js code:

    $('.quick-buy:not(.ajax-processed)').addClass('ajax-processed').click(function(e)      {
      e.preventDefault();
      $.ajax({
        url: '/product/get/ajax/'+$(this).attr('rel')
      }).done(function(result){
        $('#quick-buy').html(result);
        Drupal.settings.ajax = {
          'quick-buy-submit': {
            callback: 'tweaks_quick_buy_callback',
            event: 'mousedown',
            keypress: true,
            prevent: 'key',
            submit: {
              _triggering_element_name: 'op',
              _triggering_element_value: 'Add to cart'

            },
            url: '/system/ajax'
          }
        };
        Drupal.attachBehaviors();
  });
});

Drupal.ajax.prototype.commands.plQuickBuy = function(ajax, response, status) {
    //do what you need to do to destroy overlay etc. here
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.