0

Currently, I'm using the jQuery Form plugin to handle multiple AJAX forms on a Magento product listing via .ajaxForm({});. Now, the solution I'm using works, but it is super clunky and would love to know if there is a better way to approach this problem.

I will shorten my code a bit for brevity:

<?php foreach ($_productCollection as $_product): ?>
<form action="<?php echo $this->getSubmitUrl($_product) ?>" method="post" class="derp" id="derp-<?php echo $_iterator; ?>">
    <div class="quanitybox">
        <label for="qty"><?php echo $this->__('Quantity:') ?></label>
        <input type="button" class="quantity_box_button_down" />         
        <input type="text" name="qty" maxlength="12" value="1" title="<?php echo $this->__('Qty') ?>" class="input-text qty" />
        <input type="button" class="quantity_box_button_up" />
    </div>
    <button type="submit" title="Add to Cart" class="button btn-cart" ><span><span>Add to Cart</span></span></button>
 </form>

 <script type="text/javascript">
    var productAddToCartForm = new VarienForm('derp-<?php echo $_iterator ?>');

    jQuery('#derp-<?php echo $_iterator ?>').ajaxForm({
                url: jQuery('#derp-<?php echo $_iterator ?>').attr('action').replace("checkout/cart","ajax/index"),
                data: {'isAjax':1},
                dataType: 'json',
                beforeSubmit: function(){    
                    if(productAddToCartForm.validator.validate()){
                        windowOver.show();
                        windowBox.show().css({
                            backgroundImage: "url('<?php echo $this->getSkinUrl('images/loading.gif')?>')"
                        });                    
                    }else{
                        return false;
                    }
                },
                error: function(data){
                    windowBox.css({
                          backgroundImage: 'none'
                    }).html('<?php echo $this->__('Error') ?>');                       
                    windowOver.one('click',function(){
                        hidewindow(windowBox,windowOver);                    
                    });        

                    jQuery('#hidewindow').click(function(){
                        hidewindow(windowBox,windowOver);                    
                    });
                },
                success : function(data,statusText,xhr ){
                    if(data.status == 'SUCCESS'){
                        if(jQuery('.block-cart')){
                            jQuery('.block-cart').replaceWith(data.sidebar);
                        }
                        if(jQuery('.header .block-cart-header')){
                            jQuery('.header .block-cart-header').replaceWith(data.topcart);
                        }     
                        msgHtml = '<div class="added-content"><div style="float:left;">' + productImg + '</div><em>' + titleForBox<?php echo $_iterator ?> + '</em> <?php echo $this->__('was successfully added to your shopping cart.') ?><div style="clear:both;"></div><a id="hidewindow" href="javascript:void(0);"><?php echo $this->__('Continue shopping') ?></a>&nbsp;<a href="<?php echo $this->getUrl('checkout/cart')?>"><?php echo $this->__('View cart & checkout') ?></a></div>';             
                    }else{
                        msgHtml = '<div class="added-content"><p class="error-msg" style="margin-bottom:15px;">' + data.message + '</p><a id="hidewindow" href="javascript:void(0);"><?php echo $this->__('Continue shopping') ?></a>&nbsp;<a href="<?php echo $this->getUrl('checkout/cart')?>"><?php echo $this->__('View cart & checkout') ?></a></div>';
                    }                      

                    windowBox.css({
                          backgroundImage: 'none'
                    }).html(msgHtml);                      
                    windowOver.one('click',function(){
                        hidewindow(windowBox,windowOver);                    
                    });        

                    jQuery('#hidewindow').click(function(){
                        hidewindow(windowBox,windowOver);                    
                    });    
                }
            });
</script>
<?php endforeach; ?>

The unfortunate part of this code is I'm generating a bunch of duplicate JavasScript at the bottom of each product.

I don't really see a way around this because I need to generate a new VarienForm() for each product for validation, which only takes a form id (unless I'm mistaken).

I'm doing this using the built in $_iterator, which increments per foreach() loop (ie: derp-1, derp-2, derp-3), and adding an incrementing id for each form.

I know that I can target each form by using a class selector, such as jQuery('.derp').ajaxForm({}); However I'd still need to be able to correlate this to a VarienForm.

I tried to generate the ajaxForm({}); on the fly based off of the submit button .each( function({ jQuery(this).on('click', function({ //AJAX STUFF HERE }) ); }) ); but that did not work.

Is there a more robust solution that will target each form independently, generate a VarienForm, grab any of that forms data I need, utilize the ajaxForm({}) method, and keep it all together?

2
  • 1
    Did you try stackoverflow.com/questions/3467894/…? Commented Nov 1, 2012 at 19:09
  • Thanks for the reference. It was a good read. I needed a bit more in-depth discussion as I'm still learning, though. Commented Nov 1, 2012 at 20:37

1 Answer 1

1

I would create a function that you declare once on the page. It would be used by calling it in every PHP loop iteration, by passing a few parameters that are specific to the iteration (since as you pointed out, a lot of the Javascript is duplicated). For example, the function could be:

function setupForm(form, iterator) {
    jQuery("#derp-" + iterator).ajaxForm({

    });
}

And replace every instance of your PHP code that prints the iterator with just a Javascript concatenation of iterator.

You would replace the script in the PHP loop with something like this:

var productAddToCartForm = new VarienForm('derp-<?php echo $_iterator ?>');
setupForm(productAddToCartForm, '<?php echo $_iterator ?>');

Of course, you'd have to add more arguments to the setupForm function that is specific to the loop (I will look through the code more to try to determine what they all are). That way, you make all PHP loop items print once (in the setupForm function call), and the use of them dynamic inside the setupForm function.

UDPATE:

I went through it and hopefully found everything that would need replaced, so I will paste the code after this little blurb. My concern is what these variables are:

windowBox
windowOver
productImg
titleForBox

If they are global or something, then this new update should be fine. If they are in some other context (somehow), then this might not work.

Anyways, here's what I think it might end up like:

// Use this in your PHP loop
var productAddToCartForm = new VarienForm('derp-<?php echo $_iterator ?>');
setupForm(productAddToCartForm, "<?php echo $_iterator ?>", "<?php echo $this->getSkinUrl('images/loading.gif')?>", "<?php echo $this->__('Error') ?>", "<?php echo $this->__('was successfully added to your shopping cart.') ?>", "<?php echo $this->__('Continue shopping') ?>", "<?php echo $this->getUrl('checkout/cart')?>", "<?php echo $this->__('View cart & checkout') ?>");

// Use this one time in your page
function setupForm(form, iterator, skin_url, an_error, successful_text, continue_text, checkout_url, checkout_text) {
    var the_form = jQuery("#derp-"+iterator);  // Added this (obviously)

    the_form.ajaxForm({  // Changed this line
        url: the_form.attr('action').replace("checkout/cart","ajax/index"),  // Changed this line
        data: {'isAjax':1},
        dataType: 'json',
        beforeSubmit: function(){    
            if(form.validator.validate()){  // Changed this line
                windowOver.show();
                windowBox.show().css({
                    backgroundImage: "url('" + skin_url + "')"  // Changed this line
                });                    
            }else{
                return false;
            }
        },
        error: function(data){
            windowBox.css({
                  backgroundImage: 'none'
            }).html(an_error);  // Changed this line

            windowOver.one('click',function(){
                hidewindow(windowBox,windowOver);
            });

            jQuery('#hidewindow').click(function(){
                hidewindow(windowBox,windowOver);                    
            });
        },
        success : function(data,statusText,xhr){
            var msgHtml = "";  // Added this line
            if(data.status == 'SUCCESS'){
                if(jQuery('.block-cart')){
                    jQuery('.block-cart').replaceWith(data.sidebar);
                }
                if(jQuery('.header .block-cart-header')){
                    jQuery('.header .block-cart-header').replaceWith(data.topcart);
                }
                msgHtml = '<div class="added-content"><div style="float:left;">' + productImg + '</div><em>' + titleForBox + iterator + '</em> ' + successful_text + '<div style="clear:both;"></div><a id="hidewindow" href="javascript:void(0);">' + continue_text + '</a>&nbsp;<a href="' + checkout_url + '">' + checkout_text + '</a></div>';  // Changed this line
            }else{
                msgHtml = '<div class="added-content"><p class="error-msg" style="margin-bottom:15px;">' + data.message + '</p><a id="hidewindow" href="javascript:void(0);"><?php echo $this->__('Continue shopping') ?></a>&nbsp;<a href="' + checkout_url + '">' + checkout_text + '</a></div>';  // Changed this line
            }

            windowBox.css({
                  backgroundImage: 'none'
            }).html(msgHtml);
            windowOver.one('click',function(){
                hidewindow(windowBox,windowOver);
            });

            jQuery('#hidewindow').click(function(){
                hidewindow(windowBox,windowOver);
            });
        }
    });
}

Mainly look at the comments to see where I made changes to your actual code.

Sign up to request clarification or add additional context in comments.

4 Comments

This sounds like a good idea. There is definitely more than just "iterator", but I left all that out. I'll give this a go and let you know what comes out. Thanks.
@tr3online I just updated the answer after I went through, proposing changes based on everything I could find in your code that was processed by the PHP loop. I think I covered everything, but I wouldn't be surprised if I'm forgetting something.
With a couple of changes, this worked wonderfully. I wrapped the var productAddToCartForm & setupForm in a $(document).ready() and it worked like a charm. I hate code reuse. Thanks for pointing me in the right direction!
@tr3online No problem at all! Haha yeah, and it gets a little messy when you mix it with server languages too. Anyways, glad you got it working!

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.