diff --git a/commerce_ajax_cart.admin.inc b/commerce_ajax_cart.admin.inc index 2de5e7d..13f35de 100644 --- a/commerce_ajax_cart.admin.inc +++ b/commerce_ajax_cart.admin.inc @@ -52,42 +52,61 @@ function commerce_ajax_cart_settings_form() { '#options' => $view_settings, '#title' => t('Shopping cart to use'), '#default_value' => variable_get('commerce_ajax_cart_view', COMMERCE_AJAX_CART_DEFAULT_VIEW), + '#description' => t('Select Shopping cart form, if you are not sure...'), ); - $behaviours = commerce_ajax_cart_script_examples(); + module_load_include('inc', 'block', 'block.admin'); + $current_theme = variable_get('theme_default', 'garland'); + $blocks = block_admin_display_prepare_blocks($current_theme); + $blocks_list = array(); + foreach ($blocks as $block) { + if ($block['module'] == 'commerce_cart') { + $blocks_list[$block['bid']] = $block['info']; + } + } - $form['commerce_ajax_cart_behaves'] = array( - '#type' => 'container', - '#tree' => TRUE, - '#title' => t('Example behaviours'), + $form['commerce_ajax_cart_block'] = array( + '#type' => 'select', + '#options' => $blocks_list, + '#title' => t('Commerce cart block'), + '#default_value' => variable_get('commerce_ajax_cart_block'), ); - $behaviours_default = variable_get('commerce_ajax_cart_behaves', array( - 'show_cart' => 0, - 'fly_to_cart' => 0, - )); + $form['commerce_ajax_cart_use_dialog'] = array( + '#type' => 'checkbox', + '#title' => t('Use dialog'), + '#default_value' => variable_get('commerce_ajax_cart_use_dialog'), + '#description ' => t('This popup dialog inform about adding to cart. If disabled, adding to cart message will appear as status message.'), + ); + $form['commerce_ajax_cart_content_name'] = array( + '#type' => 'textfield', + '#title' => t('Content id or class'), + '#default_value' => variable_get('commerce_ajax_cart_content_name', '#block-system-main'), + '#description' => t('Main container, where status message will appear. Usually, by default is #block-system-main'), + '#states' => array( + 'invisible' => array( + ':input[name="commerce_ajax_cart_use_dialog"]' => array('checked' => TRUE), + ), + ), + ); - foreach ($behaviours as $id => $b) { - $form['behaves'][$id] = array( - '#type' => 'checkbox', - '#title' => check_plain($b['title']), - '#return_value' => 1, - '#default_value' => $behaviours_default[$id], - ); - $form['behaves'][$id . '_example'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#title' => t('Show code'), - ); - $form['behaves'][$id . '_example']['code'] = array( - '#markup' => '
' . $b['content'] . '
', - ); - } + $form['commerce_ajax_cart_fly2cart'] = array( + '#type' => 'checkbox', + '#title' => t('Fly to cart'), + '#default_value' => variable_get('commerce_ajax_cart_fly2cart'), + ); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save settings'), + // TODO Bad. Better solution? + $form['commerce_ajax_cart_fly2cart_parent'] = array( + '#type' => 'textfield', + '#title' => t('Image and add to cart container classes or IDs'), + '#default_value' => variable_get('commerce_ajax_cart_fly2cart_parent'), + '#description' => t('Class or ID names of closest parent element, separated by comma in order of distance increasing, that contain both image of product and "add to cart" form
For example, .node,.views-row - .node will seeked first, then if not found, .views-row
Be sure, it shouldn\'t contain other products images and add to cart forms.'), + '#states' => array( + 'invisible' => array( + ':input[name="commerce_ajax_cart_fly2cart"]' => array('checked' => FALSE), + ), + ), ); return system_settings_form($form); diff --git a/commerce_ajax_cart.info b/commerce_ajax_cart.info index d693e0a..0dbb126 100644 --- a/commerce_ajax_cart.info +++ b/commerce_ajax_cart.info @@ -10,4 +10,3 @@ version = "7.x-1.0-beta2" core = "7.x" project = "commerce_ajax_cart" datestamp = "1389966808" - diff --git a/commerce_ajax_cart.module b/commerce_ajax_cart.module index edf0d83..d412068 100644 --- a/commerce_ajax_cart.module +++ b/commerce_ajax_cart.module @@ -7,7 +7,7 @@ */ define('COMMERCE_AJAX_CART_CACHE_PREFIX', 'commerce_ajax_cart_'); -define('COMMERCE_AJAX_CART_DEFAULT_VIEW', 'commerce_cart_block.default'); +define('COMMERCE_AJAX_CART_DEFAULT_VIEW', 'commerce_cart_form.default'); /** * Implements hook_views_api(). @@ -64,16 +64,30 @@ function commerce_ajax_cart_get_defaults() { } /** + * Implements hook_theme(). + */ +function commerce_ajax_cart_theme() { + return array( + 'commerce_ajax_cart' => array( + 'variables' => array('product_count' => NULL, 'total_quantity' => NULL, 'total_amount' => NULL, 'order' => NULL), + 'path' => drupal_get_path('module', 'commerce_ajax_cart') . '/theme', + 'template' => 'commerce-ajax-cart', + ), + 'commerce_ajax_cart_dialog' => array( + 'variables' => array('line_item' => NULL), + 'path' => drupal_get_path('module', 'commerce_ajax_cart') . '/theme', + 'template' => 'commerce-ajax-cart-dialog', + ), + ); +} + +/** * Implements hook_preprocess_block(). */ function commerce_ajax_cart_preprocess_block(&$variables) { - if ('commerce_cart' == $variables['block']->module && $variables['block_id'] == 1) { - $variables['content'] = l('' . t('Show cart') . '', 'cart', array( - 'html' => TRUE, - 'attributes' => array( - 'class' => array('commerce-ajax-cart-loader'), - ), - )); + if ($variables['block']->bid == variable_get('commerce_ajax_cart_block')) { + $params = commerce_ajax_cart_block_params(); + $variables['content'] = theme('commerce_ajax_cart', $params); } } @@ -81,8 +95,8 @@ function commerce_ajax_cart_preprocess_block(&$variables) { * Menu callback to print the contents block. */ function commerce_ajax_cart_show_contents_block() { - $content = commerce_cart_block_view('cart'); - print $content['content']; + $params = commerce_ajax_cart_block_params(); + print theme('commerce_ajax_cart', $params); } /** @@ -108,31 +122,20 @@ function commerce_ajax_cart_preprocess_html() { 'weight' => 9, )); $commerce_ajax_cart_view = commerce_ajax_cart_get_view_name(); - drupal_add_js(array( - 'commerce_ajax_cart' => array( - 'position' => $defaults, - 'update_url' => url('cart/ajax/update'), - 'form_id' => $commerce_ajax_cart_view['view'], - 'update_url_block' => url('cart/ajax/block'), - 'ajax_url' => url('cart/ajax'), - 'text' => variable_get('commerce_ajax_cart_text', t('There is no product in your cart')), - ), - ), 'setting'); - $behaves = commerce_ajax_cart_script_examples(); - $behaviours_default = variable_get('commerce_ajax_cart_behaves', array()); - foreach ($behaviours_default as $key => $status) { - if ($status == 1) { - $cmd = "jQuery(window).bind('commerce_ajax_cart_update',function(e,formId) {"; - $cmd .= $behaves[$key]['content']; - $cmd .= "});"; - drupal_add_js($cmd, array( - 'type' => 'inline', - 'scope' => 'footer', - 'weight' => 10, - )); - $cmd = ''; - } + $setting['commerce_ajax_cart']= array( + 'position' => $defaults, + 'update_url' => url('cart/ajax/update'), + 'form_id' => $commerce_ajax_cart_view['view'], + 'update_url_block' => url('cart/ajax/block'), + 'ajax_url' => url('cart/ajax'), + 'text' => variable_get('commerce_ajax_cart_text', t('There is no product in your cart')), + ); + if (variable_get('commerce_ajax_cart_fly2cart')) { + $parents = explode(',', variable_get('commerce_ajax_cart_fly2cart_parent')); + $setting['commerce_ajax_cart']['fly2cart_parent'] = $parents; } + drupal_add_js($setting, 'setting'); + } /** @@ -185,9 +188,49 @@ function commerce_ajax_cart_entity_info_alter(&$entity_info) { } /** + * Implements hook_form_alter(). + * +TODO Make views cart form ajaxable for all actions: edit quantity, remove, update. +function commerce_ajax_cart_form_alter(&$form, &$form_state, $form_id) { + $commerce_ajax_cart_view = variable_get('commerce_ajax_cart_view', COMMERCE_AJAX_CART_DEFAULT_VIEW); + // TODO Make better selection view form from settings: + if ($form_id == 'views_' . $commerce_ajax_cart_view['view'] . '_' . $commerce_ajax_cart_view['display']) { + $form['#action'] = url('cart'); + if (!empty($form['edit_delete'])) { + foreach(element_children($form['edit_delete']) as $key) { + if (!empty($form['edit_delete'][$key]['#line_item_id'])) { + $form['edit_delete'][$key]['#ajax'] = array( + 'callback' => 'commerce_ajax_cart_cart_callback', + ); + } + } + } + } +} + +function commerce_ajax_cart_cart_callback($form, &$form_state) { + global $user; + drupal_get_messages(); + $_POST = array(); + $order_id = commerce_cart_order_id($user->uid); + $cart = commerce_embed_view('commerce_cart_form', 'default', array($order_id)); + return array( + '#type' => 'ajax', + '#commands' => array( + ajax_command_replace('.view-commerce-cart-form', $cart), + ), + ); +} +*/ + +/** * Implements hook_form_FORM_ID_alter(). */ function commerce_ajax_cart_form_commerce_cart_add_to_cart_form_alter(&$form, $form_state, $form_id) { + if (variable_get('commerce_ajax_cart_use_dialog')) { + $form['#attached']['library'][] = array('system', 'ui.dialog'); + } + $form['submit']['#ajax'] = array( 'callback' => 'commerce_ajax_cart_callback', ); @@ -202,13 +245,40 @@ function commerce_ajax_cart_callback($form, &$form_state) { $form = drupal_rebuild_form($form['#form_id'], $form_state, $form); $commands[] = array('command' => 'commerce_ajax_cart_update'); - $commands[] = ajax_command_prepend('#block-system-main', theme('status_messages')); + + if (variable_get('commerce_ajax_cart_use_dialog')) { + // TODO Theme should have more control for title, content, close button + $dialog = theme('commerce_ajax_cart_dialog', array('line_item' => $form_state['line_item'])); + $commands[] = ajax_command_remove('#commerce-ajax-cart-dialog'); + $commands[] = ajax_command_append('body', '
' . $dialog . '
'); + $commands[] = ajax_command_invoke('#commerce-ajax-cart-dialog', 'dialog', array(array( + 'modal' => TRUE, + 'width' => 'auto', // TODO Fixed width on settings? + ))); + } + else { + $commands[] = ajax_command_invoke('#commerce_ajax_cart_messages', 'fadeOut'); + $commands[] = ajax_command_remove('#commerce_ajax_cart_messages'); + + // TODO if no #block-system-main? + $commands[] = ajax_command_prepend(variable_get('commerce_ajax_cart_content_name', '#block-system-main'), '
' . theme('status_messages') . '
'); + $commands[] = ajax_command_invoke('#commerce_ajax_cart_messages', 'fadeIn'); + } + $commands[] = ajax_command_replace('.' . drupal_html_class($form['#form_id']), drupal_render($form)); + $commands[] = array( 'command' => 'commerceAjaxCartFireTrigger', 'data' => $form['#form_id'], ); + if (variable_get('commerce_ajax_cart_fly2cart')) { + $commands[] = array( + 'command' => 'commerceAjaxCartFly', + 'data' => $form['#id'], + ); + } + return array( '#type' => 'ajax', '#commands' => $commands, @@ -295,43 +365,30 @@ function commerce_ajax_cart_get_view_name() { } /** - * Provides example JS snippets. + * Cart block content. */ -function commerce_ajax_cart_script_examples() { +function commerce_ajax_cart_block_params() { + global $user; + + $product_count = 0; + $total_quantity = 0; + $total_amount = 0; + + $order = commerce_cart_order_load($user->uid); + + if (!empty($order) && !empty($order->commerce_line_items)) { + $wrapper = entity_metadata_wrapper('commerce_order', $order); + $total_amount = $wrapper->commerce_order_total->value(); + foreach ($wrapper->commerce_line_items as $delta => $line_item_wrapper) { + $product_count++; + $total_quantity += $line_item_wrapper->quantity->value(); + } + } + return array( - 'show_cart' => array( - 'title' => t('Open cart'), - 'content' => "var cart = jQuery('.view-shopping-cart'); -cart.trigger('mouseenter');", - ), - 'fly_to_cart' => array( - 'title' => t('Fly to cart'), - 'content' => "var cart = jQuery('.view-shopping-cart'); -var imgtodrag = jQuery('.commerce-product-field').find('img').eq(0); -if (imgtodrag) { - var imgclone = imgtodrag.clone().offset({ - top: imgtodrag.offset().top, - left: imgtodrag.offset().left - }).css({ - 'opacity': '0.5', - 'position': 'absolute', - 'height': '150px', - 'width': '150px', - 'z-index': '100' - }).appendTo(jQuery('body')).animate({ - 'top': cart.offset().top + 10, - 'left': cart.offset().left + 10, - 'width': 75, - 'height': 75 - }, 1000); - imgclone.animate({ - 'width': 0, - 'height': 0 - }, - function () { - jQuery(this).detach(); - }); -}", - ), + 'product_count' => $product_count, + 'total_quantity' => $total_quantity, + 'total_amount' => $total_amount, + 'order' => $order, ); } diff --git a/js/commerce_ajax_cart.js b/js/commerce_ajax_cart.js index 759f529..465f809 100644 --- a/js/commerce_ajax_cart.js +++ b/js/commerce_ajax_cart.js @@ -32,7 +32,7 @@ fillCartBlock: function() { $('a.commerce-ajax-cart-loader').each(function() { $.post(Drupal.settings.commerce_ajax_cart.update_url_block, function(data) { - $('a.commerce-ajax-cart-loader').html(data); + $('a.commerce-ajax-cart-loader').parent().html(data); }); }) }, @@ -40,25 +40,19 @@ var options = { 'my': Drupal.settings.commerce_ajax_cart.position.my, 'at': Drupal.settings.commerce_ajax_cart.position.at, - 'of': $('.view-id-' + Drupal.settings.commerce_ajax_cart.form_id).parent(), + 'of': $('.commerce-ajax-cart-loader').parent(), 'collision': Drupal.settings.commerce_ajax_cart.position.collision }; $('#commerce-ajax-cart-preview').position(options); }, attach: function(context, settings) { // Call for chached sites to update block display. - var $container = $(context).find('.view-id-' + Drupal.settings.commerce_ajax_cart.form_id).parent(); + var $container = $(context).find('.commerce-ajax-cart-loader').parent(); $container.once('commerce-ajax-cart-processed', function() { Drupal.ajax.prototype.commands.commerce_ajax_cart_update(); Drupal.behaviors.commerce_add_to_cart_show_ajax_cart.fillCartBlock(context); }); - $('#dc-cart-ajax-form-wrapper form').once('commerce-ajax-cart-update', function() { - $(this).find('a').bind('click', function() { - Drupal.ajax.prototype.commands.commerce_ajax_cart_update(); - }); - }) - $container.bind('mouseenter', function(e) { e.preventDefault(); window.clearTimeout(Drupal.behaviors.commerce_add_to_cart_show_ajax_cart.timer); @@ -87,8 +81,42 @@ }); } } + Drupal.ajax.prototype.commands.commerceAjaxCartFireTrigger = function(ajax, response, status) { + $(window).trigger('commerce_ajax_cart_update', response.data); + } + Drupal.ajax.prototype.commands.commerceAjaxCartFly = function(ajax, response, status) { + var link2cart = $('.commerce-ajax-cart-loader'); + // TODO Very bad. Better solution? + $.each(Drupal.settings.commerce_ajax_cart.fly2cart_parent, function(index, value) { + var imgtodrag = $('#' + response.data).parents(value).find('img').eq(0); + if (imgtodrag.length) { + var imgclone = imgtodrag.clone().offset({ + top: imgtodrag.offset().top, + left: imgtodrag.offset().left + }).css({ + 'opacity': '0.5', + 'position': 'absolute', + 'height': imgtodrag.clientHeight, + 'width': imgtodrag.clientWidth, + 'z-index': '999' + }).appendTo($('body')).animate({ + 'top': link2cart.offset().top + 10, + 'left': link2cart.offset().left + 10, + 'width': link2cart.clientHeight, + 'height': link2cart.clientHeight + }, 1000); + imgclone.animate( + { + 'width': 0, + 'height': 0 + }, + function () { + $(this).detach(); + } + ); + // Break cycle if found and animated. + return false; + } + }); + } })(jQuery); - -Drupal.ajax.prototype.commands.commerceAjaxCartFireTrigger = function(ajax, response, status) { - jQuery(window).trigger('commerce_ajax_cart_update', response.data); -}