News:

You may pay someone to create your store, or you visit our seminar and become a professional yourself with the silver certification

Main Menu

Solve dynupdate.js script bugs and make vm3 the most adv. Shop solution

Started by Studio 42, March 19, 2015, 00:41:23 AM

Previous topic - Next topic

Studio 42

Hi all developpers,

The new ajax feature to update products is a very good idea, but the way it's done give at end many little bugs and in some case simply break all javascript.

The current better solution, seens jquery 1.7, is to use triggers. If you don't know how this work see http://learn.jquery.com/events/introduction-to-custom-events/

the current script is for eg :

            var el = $(data).find(Virtuemart.containerSelector);

                            if (! el.length) el = $(data).filter(Virtuemart.containerSelector);

                            if (el.length) {

                                    Virtuemart.container.html(el.html());

                Virtuemart.updateCartListener();

                Virtuemart.updateDynamicUpdateListeners();

                //Virtuemart.updateCartListener();


                                    if (Virtuemart.updateImageEventListeners) Virtuemart.updateImageEventListeners();

                                    if (Virtuemart.updateChosenDropdownLayout) Virtuemart.updateChosenDropdownLayout();

                            }

                            Virtuemart.isUpdatingContent = false;

                            if (callback && typeof(callback) === "function") {

                                    callback();

                            }


this :
QuoteVirtuemart.updateImageEventListeners
Virtuemart.updateChosenDropdownLayout
Virtuemart.updateCartListener
Virtuemart.updateDynamicUpdateListeners
are all typical triggers and ca be transformed to a simple call for all this functions with one trigger:
$(Virtuemart.containerSelector).trigger('Virtuemart::update')

And using this code to set the plugins(triggers)

$(Virtuemart.containerSelector ).on( "Virtuemart::update.image", function( event ) {
// the code here
});

// you can chain it
$(Virtuemart.containerSelector )
.on( "Virtuemart::update.Cart", function( event ) {
// the Cart code here
})
.on( "Virtuemart::update.ChosenDropdownLayout", function( event ) {
// the Chosen Dropdown code here
});


of course is very simply to remove a trigger, see http://api.jquery.com/off/
if you use namespace
using this

// remove the Chosen Dropdown code in our case
$(Virtuemart.containerSelector ).off( "Virtuemart::update.ChosenDropdownLayout");
});


And the best is so easy to add your own trigger so :


// replacethe image script code in this case
$(Virtuemart.containerSelector )
.off( "Virtuemart::update.image")
.on( "Virtuemart::update.imageZoom"), function( event ) {
// the imageZoom code here
});


If you look right, this is the same logic as joomla triggers but dynamic.
on Virtuemart::update looks for all plugins and trigger it, but with jquery you can dynamical remove,add it with ease !

This is only a sample and other codes can be changed to really make the dynupdate system more flexible.(triggering module, plugins javascript are very easy)
And another think, is that can be done with multi-product in same page, on adding some lines of code in futur releases. because you get back the event caller.

Currently you have to overite/remove many Javascript, or on update, your code does not work because ajax, with the trigger you have any problems like this.


Patrick

And another problem in this script. Read the post here : http://forum.virtuemart.net/index.php?topic=128636.msg443260#msg443260

Studio 42

A simple sample to update the breadcrumb adding your own trigger :

Quote
$(Virtuemart.containerSelector ).on( "Virtuemart::update.breadcrumb", function( event ) {
// the code here
var $this = $(this),
title = $('h1').text(),
$lastItem = $('.breadcrumb').children().last().children().eq(0);
$lastItem.text(title);
});

this update the breadcrumb when virtuemart update using a trigger. Of course the code must be more complet in case of links, but it's only a sample.


Milbo

So you are happy with the possibilites? I hope so :-)

I also noticed, to prevent double binding it is better to use the new jQuery .on and .off commands. First off and then on. Code will be more and more rewritten to use this construction. There are examples in the vmprice.js
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

Studio 42

I'm not happy with the current code. But is a good begin.

The example i wrote, is how i modify it, because i had bugs on the original code.
I think changing to on/off triggers is a great advance to simplify all dynamic dom changes, but tis is not the case in dynupdate current code.

If you change the way virtuemart do the updates, you made it easy and flexible.
Many new jquery plugins use trigger that you can hook the code.Eg Bootstrap

Studio 42

For the vmprice, this is completly wrong way :
first this code is false eg:

QuotejQuery(plus).off('click', Virtuemart.incrQuantity);
        jQuery(plus).on('click', {cart:cart}, Virtuemart.incrQuantity);
plus is already a jquery Object and can be simplified to :
Quoteplus.off('click', Virtuemart.incrQuantity);
       plus.on('click', {cart:cart}, Virtuemart.incrQuantity);
or better
Quoteplus.off('click').on('click', {cart:cart}, Virtuemart.incrQuantity);
you don't need to pass parameters when you set off

this is the right way for eg.

QuoteVirtuemart.product = function(carts) {
   carts.each(function(){
      var cart = jQuery(this),
      quantityInput=cart.find('input[name="quantity[]"]'),
      // all the element needing a refresh on change
      $toRefreshOnChange = cart.find('select:not(.no-vm-bind),input:radio:not(.no-vm-bind)'),
      quantity = cart.find('.quantity-input'),
      virtuemart_product_id = cart.find('input[name="virtuemart_product_id[]"]').val,
      Ste = parseInt(quantityInput.attr("step"));

      //Fallback for layouts lower than 2.0.18b
      if(isNaN(Ste)){
         Ste = 1;
      }

        cart.find('.quantity-plus').off('click').on('click', {cart:cart}, Virtuemart.incrQuantity);

        cart.find('.quantity-minus').off('click').on('click', {cart:cart},Virtuemart.decrQuantity);

        $toRefreshOnChange.off('change')
      .on('change', {cart:cart,virtuemart_product_id:virtuemart_product_id},Virtuemart.eventsetproducttype);

        quantity.off('keyup')
      .on('keyup', {cart:cart,virtuemart_product_id:virtuemart_product_id},Virtuemart.eventsetproducttype);

        this.action ="#";
        cart.find('input[name="addtocart"]').off('click',Virtuemart.addtocart)
      .on('click',{cart:cart},Virtuemart.addtocart);

   });
}