<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NemoPS &#187; cart</title>
	<atom:link href="http://nemops.com/tag/cart/feed/" rel="self" type="application/rss+xml" />
	<link>http://nemops.com</link>
	<description>Prestashop Tutorials, Modules and More!</description>
	<lastBuildDate>Wed, 05 Dec 2018 13:25:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.35</generator>
	<item>
		<title>Creating a “Clear cart” button in PrestaShop 1.7</title>
		<link>http://nemops.com/prestashop-1-7-clear-cart-button/</link>
		<comments>http://nemops.com/prestashop-1-7-clear-cart-button/#comments</comments>
		<pubDate>Mon, 06 Nov 2017 13:09:06 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[prestashop 1.7]]></category>
		<category><![CDATA[products]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=3093</guid>
		<description><![CDATA[<p>Let&#8217; see how to create a button to empty the PrestaShop 1.7 shopping cart in one click! Version used: Prestashop 1.7.2.4 In this tutorial we will see how to apply my previous guide on Creating a “Clear cart” button in PrestaShop to PrestaShop 1.7, as it doesn&#8217;t work out of the box because of the [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-1-7-clear-cart-button/">Creating a “Clear cart” button in PrestaShop 1.7</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Let&#8217; see how to create a button to empty the PrestaShop 1.7 shopping cart in one click!<br />
<span id="more-3093"></span></p>
<ul>
<li>Version used: <strong>Prestashop 1.7.2.4</strong></li>
</ul>
<p>In this tutorial we will see how to apply my previous guide on <a href="http://nemops.com/clear-cart-button-prestashop">Creating a “Clear cart” button in PrestaShop</a> to PrestaShop 1.7, as it doesn&#8217;t work out of the box because of the new template.</p>
<p>The basic code still works, and the process is more or less the same, though the files needing modifications are totally different. For this tutorial, I will be using the classic (or standard) template, so wherever you read &#8220;themename&#8221;, just put <strong>classic</strong>. As a side not, please notice some files might be different if you use a custom PrestaShop theme.</p>
<h2>Adding the button to the cart page in PrestaShop 1.7</h2>
<p>The PrestaShop 1.7 template structure is quite different from 1.6, so we need to account for that. The main view for the cart is now located at <em>themes/*themename*/templates/checkout/</em>, and it&#8217;s called <strong>cart.tpl</strong>. Open it up, and locat the following block:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
      {block name='cart_overview'}
        {include file='checkout/_partials/cart-detailed.tpl' cart=$cart}
      {/block}
</pre>
<p>This represents the products list block, and we want to add the button right after it:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
    &lt;a class=&quot;btn btn-primary&quot; style=&quot;float:right&quot; id=&quot;removeAll&quot; href=&quot;javascript:void(0)&quot;&gt;
      Empty Cart
    &lt;/a&gt;
</pre>
<p>At this point, unlike 1.6 where we could add our code directly to the template, with PrestaShop 1.7 we have to use a new file, named <strong>custom.js</strong>.</p>
<div class="separator"></div>
<h2>Adding new javascript to a PrestaShop 1.7 template</h2>
<p>Open up <strong>custom.js</strong>, located in <em>themes/*themename*/assets/js</em>.<br />
It&#8217;s empty by default, so if not (as in the case of custom templates), just add the code at the end.</p>
<p>This file is loaded on all pages, and since we only want to run it on the cart one, we have to wrap our snippet with a condition:</p>
<pre class="brush: jscript; title: ; notranslate">
if(prestashop.page.page_name == 'cart')
{}
</pre>
<p>The <strong>prestashop</strong> javascript variable is a new global available in all pages of the shop, which contains a number of useful data that can be used in scripts. In this case, we use the current page name.</p>
<p>Here is all the rest of the code we need:</p>
<pre class="brush: jscript; title: ; notranslate">
$(document).ready(function() {

	    $('#removeAll').click(function(e) {
	        e.preventDefault()
	        $.ajax({
	            type: 'POST',
	            headers: { &quot;cache-control&quot;: &quot;no-cache&quot; },
	            url: prestashop.urls.base_url + &quot;cart&quot;,
	            async: true,
	            cache: false,
	            data: 'deleteAll=1&amp;token=' + prestashop.token + '&amp;ajax=true',
	            success: function(data){	
	                window.location.reload();
	            }
	        })
	    });
	});	
</pre>
<p><strong>Explanation:</strong> we are using the prestashop variable again, this time to fetch the base url. The cart controller, which we will be editing shortly, can be accessed at /cart by default, so we pass this url to the ajax call.<br />
For the querystring, we pass in <strong>deleteAll</strong>, to make sure we can refer to this action in the next step, a <strong>token</strong> required by PrestaShop 1.7, and <strong>ajax=true</strong>, so that the cart know the action has to be run in ajax mode.<br />
If the call is successful, we refresh the page to show that the cart is now empty.</p>
<div class="separator"></div>
<h2>Editing the CartController</h2>
<p>PrestaShop 1.7 discourages the use of overrides, but we will use one in any case <img src="http://nemops.com/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /><br />
Create a new file in <em>override/controllers/front</em>, and name it <strong>cartController.php</strong>. Reach back the original cart controller in the main <em>controllers/front</em>, and copy the whole <strong>updateCart</strong> method, pasting it into our new file:</p>
<pre class="brush: php; title: ; notranslate">
    protected function updateCart()
    {
        // Update the cart ONLY if $this-&gt;cookies are available, in order to avoid ghost carts created by bots
        if ($this-&gt;context-&gt;cookie-&gt;exists() &amp;&amp; !$this-&gt;errors &amp;&amp; !($this-&gt;context-&gt;customer-&gt;isLogged() &amp;&amp; !$this-&gt;isTokenValid())) {
            if (Tools::getIsset('add') || Tools::getIsset('update')) {
                $this-&gt;processChangeProductInCart();
            } elseif (Tools::getIsset('delete')) {
                $this-&gt;processDeleteProductInCart();
            } elseif (CartRule::isFeatureActive()) {
                if (Tools::getIsset('addDiscount')) {
                    if (!($code = trim(Tools::getValue('discount_name')))) {
                        $this-&gt;errors[] = $this-&gt;trans('You must enter a voucher code.', array(), 'Shop.Notifications.Error');
                    } elseif (!Validate::isCleanHtml($code)) {
                        $this-&gt;errors[] = $this-&gt;trans('The voucher code is invalid.', array(), 'Shop.Notifications.Error');
                    } else {
                        if (($cartRule = new CartRule(CartRule::getIdByCode($code))) &amp;&amp; Validate::isLoadedObject($cartRule)) {
                            if ($error = $cartRule-&gt;checkValidity($this-&gt;context, false, true)) {
                                $this-&gt;errors[] = $error;
                            } else {
                                $this-&gt;context-&gt;cart-&gt;addCartRule($cartRule-&gt;id);
                            }
                        } else {
                            $this-&gt;errors[] = $this-&gt;trans('This voucher does not exist.', array(), 'Shop.Notifications.Error');
                        }
                    }
                } elseif (($id_cart_rule = (int)Tools::getValue('deleteDiscount')) &amp;&amp; Validate::isUnsignedId($id_cart_rule)) {
                    $this-&gt;context-&gt;cart-&gt;removeCartRule($id_cart_rule);
                    CartRule::autoAddToCart($this-&gt;context);
                }
            }
        } elseif (!$this-&gt;isTokenValid() &amp;&amp; Tools::getValue('action') !== 'show' &amp;&amp; !Tools::getValue('ajax')) {
            Tools::redirect('index.php');
        }
    }
</pre>
<p>All we have to do now is add our condition, as part of all those ELSEIFs:</p>
<pre class="brush: php; title: ; notranslate">
            elseif (Tools::getIsset('deleteAll')) {
                $this-&gt;context-&gt;cart-&gt;delete();
                $this-&gt;context-&gt;cookie-&gt;id_cart = 0;
                die(1);
            }
</pre>
<p>Here is the final code:</p>
<pre class="brush: php; title: ; notranslate">
    protected function updateCart()
    {
        // Update the cart ONLY if $this-&gt;cookies are available, in order to avoid ghost carts created by bots
        if ($this-&gt;context-&gt;cookie-&gt;exists() &amp;&amp; !$this-&gt;errors &amp;&amp; !($this-&gt;context-&gt;customer-&gt;isLogged() &amp;&amp; !$this-&gt;isTokenValid())) {
            if (Tools::getIsset('add') || Tools::getIsset('update')) {
                $this-&gt;processChangeProductInCart();
            } elseif (Tools::getIsset('delete')) {
                $this-&gt;processDeleteProductInCart();

            } elseif (Tools::getIsset('deleteAll')) { /* Nemo */
                $this-&gt;context-&gt;cart-&gt;delete();
                $this-&gt;context-&gt;cookie-&gt;id_cart = 0;
                die(1);
            } elseif (CartRule::isFeatureActive()) {
                if (Tools::getIsset('addDiscount')) {
                    if (!($code = trim(Tools::getValue('discount_name')))) {
                        $this-&gt;errors[] = $this-&gt;trans('You must enter a voucher code.', array(), 'Shop.Notifications.Error');
                    } elseif (!Validate::isCleanHtml($code)) {
                        $this-&gt;errors[] = $this-&gt;trans('The voucher code is invalid.', array(), 'Shop.Notifications.Error');
                    } else {
                        if (($cartRule = new CartRule(CartRule::getIdByCode($code))) &amp;&amp; Validate::isLoadedObject($cartRule)) {
                            if ($error = $cartRule-&gt;checkValidity($this-&gt;context, false, true)) {
                                $this-&gt;errors[] = $error;
                            } else {
                                $this-&gt;context-&gt;cart-&gt;addCartRule($cartRule-&gt;id);
                            }
                        } else {
                            $this-&gt;errors[] = $this-&gt;trans('This voucher does not exist.', array(), 'Shop.Notifications.Error');
                        }
                    }
                } elseif (($id_cart_rule = (int)Tools::getValue('deleteDiscount')) &amp;&amp; Validate::isUnsignedId($id_cart_rule)) {
                    $this-&gt;context-&gt;cart-&gt;removeCartRule($id_cart_rule);
                    CartRule::autoAddToCart($this-&gt;context);
                }
            }
        } elseif (!$this-&gt;isTokenValid() &amp;&amp; Tools::getValue('action') !== 'show' &amp;&amp; !Tools::getValue('ajax')) {
            Tools::redirect('index.php');
        }
    }
</pre>
<p>We are done! Reach the back office, Advanced Parameters, Performance, and hit the clear cache button on the top right, so that the override takes place.</p>
<p>Should it not work, check that <strong>Disable all overrides</strong> is set to no, right below on the same page. If it still doesn&#8217;t, try editing the core CartController.php.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-1-7-clear-cart-button/">Creating a “Clear cart” button in PrestaShop 1.7</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-1-7-clear-cart-button/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Limit the total number of products in the cart &#8211; PrestaShop 1.6</title>
		<link>http://nemops.com/limit-cart-products-prestashop/</link>
		<comments>http://nemops.com/limit-cart-products-prestashop/#comments</comments>
		<pubDate>Mon, 27 Mar 2017 09:30:01 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[products]]></category>
		<category><![CDATA[thirtybees]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2993</guid>
		<description><![CDATA[<p>In today's video we will see how to limit the maximum number of products customers can add to the cart in PrestaShop 1.6. It also works in ThirtyBees, the PrestaShop fork.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/limit-cart-products-prestashop/">Limit the total number of products in the cart &#8211; PrestaShop 1.6</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In today&#8217;s video we will see how to limit the maximum number of products customers can add to the cart in PrestaShop 1.6. It also works in ThirtyBees, the PrestaShop fork.<br />
<span id="more-2993"></span></p>
<h2>Watch the screencast</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/wAlXtr8u5Qo" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<p>The post <a rel="nofollow" href="http://nemops.com/limit-cart-products-prestashop/">Limit the total number of products in the cart &#8211; PrestaShop 1.6</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/limit-cart-products-prestashop/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Taking back the Add To Cart button in the Product list (Prestashop 1.7)</title>
		<link>http://nemops.com/prestashop-1-7-product-list-add-to-cart-button/</link>
		<comments>http://nemops.com/prestashop-1-7-product-list-add-to-cart-button/#comments</comments>
		<pubDate>Thu, 15 Dec 2016 08:20:33 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[prestashop 1.7]]></category>
		<category><![CDATA[product list]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2929</guid>
		<description><![CDATA[<p>If you started using PrestaShop 1.7 (brave!) and you miss the Add to Cart button in the product list, let&#8217;s see how to take it back with 4 lines of code!</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-1-7-product-list-add-to-cart-button/">Taking back the Add To Cart button in the Product list (Prestashop 1.7)</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>If you started using PrestaShop 1.7 (brave!) and you miss the Add to Cart button in the product list, let&#8217;s see how to take it back with 4 lines of code!<br />
<span id="more-2929"></span></p>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/9E5NVZi1oCQ" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-1-7-product-list-add-to-cart-button/">Taking back the Add To Cart button in the Product list (Prestashop 1.7)</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-1-7-product-list-add-to-cart-button/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Save Prestashop Custom fields on &#8220;Add to cart&#8221; &#8211; Part 2</title>
		<link>http://nemops.com/save-prestashop-custom-fields-add-to-cart-2/</link>
		<comments>http://nemops.com/save-prestashop-custom-fields-add-to-cart-2/#comments</comments>
		<pubDate>Wed, 06 May 2015 08:11:40 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[customization]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2406</guid>
		<description><![CDATA[<p>After tackling text fields, in this second part we will see how to add ajax uploads for file customizations in Prestashop. Version used: Prestashop 1.6 &#171; Save Prestashop Custom fields on “Add to cart” – Part 1 Demo here &#160; &#160; Continuing from what we did in the previous tutorial, instead of modifying the ajax-cart.js [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/save-prestashop-custom-fields-add-to-cart-2/">Save Prestashop Custom fields on &#8220;Add to cart&#8221; &#8211; Part 2</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>After tackling text fields, in this second part we will see how to add ajax uploads for file customizations in Prestashop.</p>
<p><span id="more-2406"></span></p>
<ul>
<li>Version used: Prestashop 1.6</li>
</ul>
<p><a href="http://nemops.com/save-prestashop-custom-fields-add-to-cart/#.VUibJfnzrmg" title="Save Prestashop Custom fields on “Add to cart” – Part 1"> &laquo; Save Prestashop Custom fields on “Add to cart” – Part 1</a></p>
<p><a class="button style1" style="float:left;" href="http://demo.nemops.com/blouses/blouse" title="Save Prestashop Custom fields - Demo">Demo here </a>&nbsp;</p>
<p>&nbsp;</p>
<p>Continuing from what we did in the previous tutorial, instead of modifying the ajax-cart.js file, this time we will handle <strong>product.js</strong>, located in the theme folder /js/. To make things easier we will also add atrigger button to fire the upload event, and modify our previously amended <strong>tools.js</strong>.</p>
<p>Before starting, it&#8217;s important to notice this kind of upload will not work for older browsers (like ie9), so you might want to add some kind of warning, or completely hide the ajax button in this case.</p>
<div class="separator"></div>
<h2>Handling ajax file uploads in Prestashop &#8211; product.js</h2>
<p>First off, let&#8217;s create our small trigger. Locate <strong>product.tpl</strong> in your theme&#8217;s folder, open it up and right before this</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
						&lt;/div&gt;
					{/if}
					{if $product-&gt;text_fields|intval}
</pre>
<p>Add the following</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
&lt;a class=&quot;btn btn-default&quot; href=&quot;javascript:void(0)&quot; id=&quot;uploadTrigger&quot;&gt;Upload&lt;/a&gt;
</pre>
<p>If your theme looks different, make sure it&#8217;s inside this conditional, at least:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
{if $product-&gt;uploadable_files|intval}
...
{/if}
</pre>
<p>Then, let&#8217;s deal with Javascript.</p>
<p>Open up <strong>product.js</strong> and make sure you put your cursor inside the very first  $(document).ready(function() block. The first thing we need to do is create a list of files that the user might want to upload, as soon as the file inputs change:</p>
<pre class="brush: jscript; title: ; notranslate">
	var files = new Array();
	$('.customizationUploadLine').find('input[type=&quot;file&quot;]').on('change', prepareUpload);
	function prepareUpload(event)
	{
	  files.push({'name' : event.target.name, 'file' :event.target.files[0]});
	}

</pre>
<p><strong>Explanation:</strong> we are taking advantage of the &#8216;files&#8217; property of the change event, which holds the file(s) currently being added to the clicked input. We want to record modifications to all our file customization fields, and push the files array with each of the possible uploads. We will need each entry to be named as the form field, so we use a new object for each file, holding the correct name in the &#8216;name&#8217; property, and the actual file content in the &#8216;file&#8217; one.</p>
<p>The original method I used came from this tutorial, in case you want to have a reference of the source code: <a href="http://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax" title="Ajax file uploads with jQuery">Ajax file uploads with jQuery</a></p>
<p>Now, let&#8217;s target the upload button&#8217;s click;</p>
<pre class="brush: jscript; title: ; notranslate">
	$('#uploadTrigger').click(function(e) {
		if(files.length &gt; 0)
		{
			// here will be out ajax
		} // end checking files length
		else alert('Nothing to upload!');
	});
</pre>
<p>We have to make sure we have at least one file to upload; otherwise it&#8217;s useless to continue with the call.</p>
<p>Since we do not know how long the file upload will take, it&#8217;s better to prevent the user from taking further actions before it&#8217;s completed. Let&#8217;s add some feedback:</p>
<pre class="brush: jscript; title: ; notranslate">

			$('&lt;div class=&quot;myoverlay&quot;&gt;&lt;/div&gt;').css({

				'position' : 'fixed',
				'top' : 0,
				'left' : 0,
				'background' : 'black',
				'background' : 'rgba(0,0,0,.5)',
				'z-index' : 5999,
				'width' : '100%',
				'height' : '100%',
				'cursor' : 'pointer'
			}).appendTo('body');
			
			$('&lt;div class=&quot;uploadingfiles&quot;&gt;Your files are being uploaded...&lt;img src=&quot;'+baseUri+'themes/default-bootstrap/img/ajax-loader.gif&quot;&gt;&lt;/div&gt;')
				.css({
					'position' : 'absolute',
					'top' : '30%',
					'left' : '50%',
					'width' : '300px',
					'margin-left' : '-150px',
					'text-align' : 'center',
					'padding' : '10px',
					'background' : 'white'
				})
				.appendTo('.myoverlay');


</pre>
<p>Now the tricky part. We will use the new HTML5, supported with XHR2 (that is why it will not work on old browsers!). Right after appending the box, add the following:</p>
<pre class="brush: jscript; title: ; notranslate">

			var data = new FormData();

		    $.each(files, function(key, obj)
		    {
		        data.append(obj.name, obj.file);
		    });

		    data.append('submitCustomizedDatas', 1);
		    data.append('ajax', 1);

</pre>
<p><strong>Explanation:</strong> as mentioned, we need a FormData object to hold our data. Then, we iterate through each of the files, assigning them to the respective name. The <strong>append</strong> method works like data.append(key, data). Lastly, since in the previous tutorial we only ran the customization scripts when having two specific queries sent to the server, we also append them to our form data. The value here is not important, as long as it&#8217;s more than 0.</p>
<h3>The ajax call</h3>
<p>Here is our code so far:</p>
<pre class="brush: jscript; title: ; notranslate">

	var files = new Array();
	$('.customizationUploadLine').find('input[type=&quot;file&quot;]').on('change', prepareUpload);
	// Grab the files and set them to our variable
	function prepareUpload(event)
	{
	  files.push({'name' : event.target.name, 'file' :event.target.files[0]});
	}
	

	$('#uploadTrigger').click(function(e) {

	
		if(files.length &gt; 0)
		{

			$('&lt;div class=&quot;myoverlay&quot;&gt;&lt;/div&gt;').css({

				'position' : 'fixed',
				'top' : 0,
				'left' : 0,
				'background' : 'black',
				'background' : 'rgba(0,0,0,.5)',
				'z-index' : 5999,
				'width' : '100%',
				'height' : '100%',
				'cursor' : 'pointer'
			}).appendTo('body');
			
			$('&lt;div class=&quot;uploadingfiles&quot;&gt;Your files are being uploaded...&lt;img src=&quot;'+baseUri+'themes/default-bootstrap/img/ajax-loader.gif&quot;&gt;&lt;/div&gt;')
				.css({
					'position' : 'absolute',
					'top' : '30%',
					'left' : '50%',
					'width' : '300px',
					'margin-left' : '-150px',
					'text-align' : 'center',
					'padding' : '10px',
					'background' : 'white'
				})
				.appendTo('.myoverlay');


			var data = new FormData();

		    $.each(files, function(key, obj)
		    {
		        data.append(obj.name, obj.file);
		    });

		    data.append('submitCustomizedDatas', 1);
		    data.append('ajax', 1);
		 

		} // end checking files length
		else alert('Nothing to upload!');
	});
</pre>
<p>Pretty long already! But we need to tackle the most important part: the ajax call. Right after appending &#8216;ajax&#8217;, add the following:</p>
<pre class="brush: jscript; title: ; notranslate">
$.ajax({
    url: $('#customizationForm').attr('action'),
    type: 'POST',
    data: data,
    cache: false,
    dataType: 'json',
    processData: false,
    contentType: false, 
    success: function(data, textStatus, jqXHR)
    {
      
    },
    error: function(jqXHR, textStatus, errorThrown)
    {
    }
});
</pre>
<p><strong>Explanation:</strong> two parts of this call deserve a better explanation; first, we are telling jQuery <strong>not to process data</strong>. Otherwise, the files array will be converted into a string, making it impossible to be further processed; then, <strong>we are setting contentType to false as well</strong>, to prevent the script to send over a normally encoded form (without files).</p>
<p>At this point, it&#8217;s worth testing out the script. It will inevitably break at some point, but you can see the upload being successful or not by refreshing the page when you see the call is complete. <strong>Make sure you keep an eye on the Network Tab</strong> in the browser&#8217;s console for this, to also troubleshoot any eventual error.</p>
<p>When it&#8217;s done, refresh the page. If everything went smoothly, the image will appear at the top of the file input!</p>
<h3>Giving some feedback to the user</h3>
<p>If we were the only ones using the site, we could as well jump to the next step. But since it&#8217;s rarely the case, let&#8217;s give our customers a bit of feedback on what&#8217;s up with files. In the &#8220;success&#8221; method of the ajax call, add the following:</p>
<pre class="brush: jscript; title: ; notranslate">

if(typeof data.errors === 'undefined')
{

	$.each(files, function(key, obj)
    {
        $('input[name=&quot;'+obj.name+'&quot;]').addClass('filled');
        previewFile($('input[name=&quot;'+obj.name+'&quot;]'), obj.file);

    });
    $('.uploadingfiles').text('Upload Complete!');
}
else
{
   $('.uploadingfiles').text('Error while uploading, please refresh the page and try again');
}
$('.myoverlay').click(function(){$(this).remove()});
</pre>
<p><strong>Explanation:</strong> first off, we must check that we don&#8217;t have any error coming back from the call. If we do, we replace our &#8220;uploading&#8221; text with the error string. If everything is ok (if(typeof data.errors === &#8216;undefined&#8217;)) we iterate through our files list, and add a preview above the list. Notice I am calling a function named  <strong>previewFile</strong>, which we do not have yet!</p>
<p>You might have noticed I added a &#8220;filled&#8221; class as well to the input. Why? We will see this shortly, when amending tools.js.</p>
<p>Make sure you always add </p>
<pre class="brush: jscript; title: ; notranslate">

$('.myoverlay').click(function(){$(this).remove()});
</pre>
<p>So that users can get rid of the overlay when needed.</p>
<h3>Adding an image Preview</h3>
<p>We are almost done! let&#8217;s create the previewFile function. Right before this:</p>
<pre class="brush: jscript; title: ; notranslate">
	$('#uploadTrigger').click(function(e) {
</pre>
<p>Add</p>
<pre class="brush: jscript; title: ; notranslate">
	function previewFile(target, file) {

		$('#uniform-'+target.attr('id')).before($('&lt;img id=&quot;preview-'+target.attr('id')+'&quot;/&gt;'));
		var preview = $('#preview-'+target.attr('id'));
		var reader  = new FileReader();

		preview.attr('width', 64);

		reader.onloadend = function () {
			preview.attr('src', reader.result);
		}

		if (file) {
			reader.readAsDataURL(file);
		} else {
			preview.attr('src', &quot;&quot;);
		}
	}

</pre>
<p><strong>Explanation:</strong> we are taking advantage of the FileReader class. First, we prepend an image tag to our input&#8217;s parent, making sure the preview box is no larger than 64 pixels. Then, we replace out image source after the reader has actually read the file, if it exists, passing in the one we got before, out of the original &#8220;files&#8221; array. It&#8217;s a bit confusing, but you can basically copy/paste to have it working. Here is the source: <a href="https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL" title="Image preview for ajax file uploads">Image preview for ajax file uploads</a></p>
<p>As a finishing touch, we might want to handle failed ajax requests as well:</p>
<pre class="brush: jscript; title: ; notranslate">
 error: function(jqXHR, textStatus, errorThrown)
{
   $('.uploadingfiles').text('ERRORS: ' + errorThrown);
    $('.myoverlay').click(function(){$(this).remove()});
}
</pre>
<div class="separator"></div>
<h2>Yet again, tools.js!</h2>
<p>Back to our beloved tools.js! Here is where we left off:</p>
<pre class="brush: jscript; title: ; notranslate">
function checkCustomizations()
{
    var pattern = new RegExp(' ?filled ?');
 
    if (typeof customizationFields != 'undefined')
        for (var i = 0; i &lt; customizationFields.length; i++)
        {
            if (parseInt(customizationFields[i][1]) == 1 &amp;&amp; ($('#' + customizationFields[i][0]).val() == ''))
  			return false;
        }
    return true;
}
</pre>
<p>Now, this will make it impossible to save our current files. In order to be able to do it, we need to modify the function as follows</p>
<pre class="brush: jscript; title: ; notranslate">
function checkCustomizations()
{
    var pattern = new RegExp(' ?filled ?');
 
    if (typeof customizationFields != 'undefined')
        for (var i = 0; i &lt; customizationFields.length; i++)
        {
            if (parseInt(customizationFields[i][1]) == 1 &amp;&amp; $('#' + customizationFields[i][0]).val() == '' &amp;&amp; !pattern.test($('#' + customizationFields[i][0]).attr('class')))
				return false;
        }
    return true;
}
</pre>
<p><strong>Explanation:</strong> remember when we added the &#8216;filled&#8217; class? Now we also want to make sure the class is not there, to return false. This way, the field will validate if it hass the &#8216;filled&#8217; class!</p>
<p>Save and try it out, it should work!</p>
<p>The final code for product.js:</p>
<pre class="brush: jscript; title: ; notranslate">

	var files = new Array();
	$('.customizationUploadLine').find('input[type=&quot;file&quot;]').on('change', prepareUpload);
	// Grab the files and set them to our variable
	function prepareUpload(event)
	{
	  files.push({'name' : event.target.name, 'file' :event.target.files[0]});
	}
	


	function previewFile(target, file) {

		$('#uniform-'+target.attr('id')).before($('&lt;img id=&quot;preview-'+target.attr('id')+'&quot;/&gt;'));
		var preview = $('#preview-'+target.attr('id'));
		var reader  = new FileReader();

		preview.attr('width', 64);

		reader.onloadend = function () {
			preview.attr('src', reader.result);
		}

		if (file) {
			reader.readAsDataURL(file);
		} else {
			preview.attr('src', &quot;&quot;);
		}
	}


	$('#uploadTrigger').click(function(e) {

	
		if(files.length &gt; 0)
		{

			$('&lt;div class=&quot;myoverlay&quot;&gt;&lt;/div&gt;').css({

				'position' : 'fixed',
				'top' : 0,
				'left' : 0,
				'background' : 'black',
				'background' : 'rgba(0,0,0,.5)',
				'z-index' : 5999,
				'width' : '100%',
				'height' : '100%',
				'cursor' : 'pointer'
			}).appendTo('body');
			
			$('&lt;div class=&quot;uploadingfiles&quot;&gt;Your files are being uploaded...&lt;img src=&quot;'+baseUri+'themes/default-bootstrap/img/ajax-loader.gif&quot;&gt;&lt;/div&gt;')
				.css({
					'position' : 'absolute',
					'top' : '30%',
					'left' : '50%',
					'width' : '300px',
					'margin-left' : '-150px',
					'text-align' : 'center',
					'padding' : '10px',
					'background' : 'white'
				})
				.appendTo('.myoverlay');


			var data = new FormData();

		    $.each(files, function(key, obj)
		    {
		        data.append(obj.name, obj.file);
		    });

		    data.append('submitCustomizedDatas', 1);
		    data.append('ajax', 1);
		    $.ajax({
		        url: $('#customizationForm').attr('action'),
		        type: 'POST',
		        data: data,
		        cache: false,
		        dataType: 'json',
		        processData: false,
		        contentType: false,
		        success: function(data, textStatus, jqXHR)
		        {
		            if(typeof data.errors === 'undefined')
		            {
		            	$.each(files, function(key, obj)
					    {
					        $('input[name=&quot;'+obj.name+'&quot;]').addClass('filled');
					        previewFile($('input[name=&quot;'+obj.name+'&quot;]'), obj.file);

					    });
					    $('.uploadingfiles').text('Upload Complete!');
		            }
		            else
		            {
		               $('.uploadingfiles').text('Error while uploading, please refresh the page and try again');
		            }
		            $('.myoverlay').click(function(){$(this).remove()});
		        },
		        error: function(jqXHR, textStatus, errorThrown)
		        {
		           $('.uploadingfiles').text('ERRORS: ' + errorThrown);
		            $('.myoverlay').click(function(){$(this).remove()});
		        }
		    });

		} // end checking files length
		else alert('Nothing to upload!');
	});

</pre>
<div class="separator"></div>
<h2>Taking it a step further</h2>
<p>Given that the previous works for you, we can try taking it a step further. If you really (really!) think your customers will never hit the upload button, you can automate the process and build it inside the ajax-cart as well. How? Opening ajax-cart.js, locate the previous code we added in part1:</p>
<pre class="brush: jscript; title: ; notranslate">

		if(addedFromProductPage &amp;&amp; $('#customizationForm').length &gt; 0)
		{
			...
		}
</pre>
<p>Right before it, add:</p>
<pre class="brush: jscript; title: ; notranslate">
	$('#uploadTrigger').click();
</pre>
<p>Then, inside product.js, <strong>make sure you also add </strong></p>
<pre class="brush: jscript; title: ; notranslate">
	async: false,
</pre>
<p>As property of the ajax call, otherwise the add to cart will run before the upload is completed!</p>
<p>The post <a rel="nofollow" href="http://nemops.com/save-prestashop-custom-fields-add-to-cart-2/">Save Prestashop Custom fields on &#8220;Add to cart&#8221; &#8211; Part 2</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/save-prestashop-custom-fields-add-to-cart-2/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Save Prestashop Custom fields on &#8220;Add to cart&#8221; &#8211; Part 1</title>
		<link>http://nemops.com/save-prestashop-custom-fields-add-to-cart/</link>
		<comments>http://nemops.com/save-prestashop-custom-fields-add-to-cart/#comments</comments>
		<pubDate>Wed, 29 Apr 2015 09:39:23 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[customization]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2390</guid>
		<description><![CDATA[<p>Having to save product customization before adding to the cart can be quite annoying. Some customers might even forget to do it if fields are not required. In the first part of this two-stage tutorial, we will see how to save customization text when the add to cart button is pressed. Version used: Prestashop 1.6 [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/save-prestashop-custom-fields-add-to-cart/">Save Prestashop Custom fields on &#8220;Add to cart&#8221; &#8211; Part 1</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Having to save product customization before adding to the cart can be quite annoying. Some customers might even forget to do it if fields are not required. In the first part of this two-stage tutorial, we will see how to save customization text when the add to cart button is pressed.<br />
<span id="more-2390"></span></p>
<ul>
<li>Version used: Prestashop 1.6</li>
</ul>
<p><a href="http://nemops.com/save-prestashop-custom-fields-add-to-cart-2/#.VUnNyfnzrmi" title="Save Prestashop Custom fields on “Add to cart” – Part 2"> Save Prestashop Custom fields on “Add to cart” – Part 2 &raquo;</a></p>
<p><a class="button style1" style="float:left;" href="http://demo.nemops.com/blouses/blouse" title="Save Prestashop Custom fields - Demo">Demo here </a>&nbsp;</p>
<div class="separator"></div>
<h2>We do need ajax</h2>
<p>Before starting, it&#8217;s important to notice we do need to activate the ajax cart, as we will be catching the fields&#8217; content and serialize it; then intercept the &#8220;add&#8221; method of the ajax cart and send another ajax request to the product controller, to save customized data before anything is added to the cart itself.<br />
That said, we need to modify two javascript files, and one controller:</p>
<ul>
<li>ajax-cart.js</li>
<li>tools.js</li>
<li>ProductController.php</li>
</ul>
<p>While we can use an override for the controller, and clone the template for the ajax-cart file, we really need to amend the original <strong>tools.js</strong>, located in the main <em>js/</em> folder.</p>
<p>That said, in this first part we will only deal with text inputs, leaving the file upload to the next tutorial.</p>
<div class="separator"></div>
<h2>Ajax-cart.php</h2>
<p>After reaching the product page (of a product having a text customization field, of course), open up <strong>themes/*yourthemename*/modules/blockcart/ajax-cart.js</strong></p>
<p>Locate the following method</p>
<pre class="brush: jscript; title: ; notranslate">
	add : function(idProduct, idCombination, addedFromProductPage, callerElement, quantity, whishlist)
</pre>
<p>It should be around line 271 in Prestashop 1.6.0.14</p>
<p>Inside it, at the very beginning, right before:</p>
<pre class="brush: jscript; title: ; notranslate">
if (addedFromProductPage &amp;&amp; !checkCustomizations())
</pre>
<p>Add the following:</p>
<pre class="brush: jscript; title: ; notranslate">
		if(addedFromProductPage &amp;&amp; $('#customizationForm').length &gt; 0)
		{
	
			$('#quantityBackup').val($('#quantity_wanted').val());
			customAction = $('#customizationForm').attr('action');
			$('body select[id^=&quot;group_&quot;]').each(function() {
				customAction = customAction.replace(new RegExp(this.id + '=\\d+'), this.id +'=' + this.value);
			});
			
		}
</pre>
<p><strong>Explanation:</strong> first, we have to make sure we are adding to the cart from the single product view (it would make no sense in the list) and that the current item does have customization fields. What comes inside is almost a 1:1 copy of the <strong>saveCustomization()</strong> method we can find in the product.js file. We need to modify the action so that it considers attributes as well. <strong>customAction</strong> is the url we will send the ajax POST to.</p>
<p>Therefore, continuing from it:</p>
<pre class="brush: jscript; title: ; notranslate">
		if(addedFromProductPage &amp;&amp; $('#customizationForm').length &gt; 0)
		{
	
			$('#quantityBackup').val($('#quantity_wanted').val());
			customAction = $('#customizationForm').attr('action');
			$('body select[id^=&quot;group_&quot;]').each(function() {
				customAction = customAction.replace(new RegExp(this.id + '=\\d+'), this.id +'=' + this.value);
			});
			// ajax to product page with custom action
			var customization_entries = $('#customizationForm').serialize();
			$.ajax({
				async:false,
				type: 'POST',
				data: customization_entries+ '&amp;ajax=1',
				dataType: 'json',
				url: customAction,
				success: function(data){
					
				}
			})	
		}
</pre>
<p><strong>Explanation:</strong> after serializing the array&#8217;s entries (remember we are only using text fields for the time being), we send them over to the actionUrl (that is, the ProductController) so it can further take care of our data. Notice I also appended <strong>&#038;ajax=1</strong> as the controller will need to know it&#8217;s receiving an ajax request. Time to move to the override!</p>
<p><strong>IMPORTANT!</strong> Make sure you set the ajax request as async:false, otherwise the add to cart will run before our customization is saved!</p>
<p><strong>Note:</strong> do not try adding the product to the cart at this stage, it will not work, saying the customization field is required.</p>
<div class="separator"></div>
<h2>The Product Controller</h2>
<p>Having our javascript all setup, let&#8217;s deal with the product controller. To make it quick, I will append the new method to the original file, but you can feel free to use an override instead. What it needs is a method that handles data before anything is outputted to screen. Fortunately, we don&#8217;t even need to create it, it&#8217;s built in, and it is named <strong>postProcess</strong>. The only issue is that the ProductController.php file doesn&#8217;t use, so we need to append it ourselves.</p>
<p>Open up <em>controllers/front/ProductController.php</em>, reach the end of the file, and add the following (make sure you are inside the class!)</p>
<pre class="brush: php; title: ; notranslate">
	public function postProcess()
	{
		if (Tools::getValue('ajax') &amp;&amp; Tools::isSubmit('submitCustomizedDatas'))
		{
			if (!$this-&gt;context-&gt;cart-&gt;id &amp;&amp; isset($_COOKIE[$this-&gt;context-&gt;cookie-&gt;getName()]))
			{
				$this-&gt;context-&gt;cart-&gt;add();
				$this-&gt;context-&gt;cookie-&gt;id_cart = (int)$this-&gt;context-&gt;cart-&gt;id;
			}

			$this-&gt;pictureUpload();
			$this-&gt;textRecord();
			$this-&gt;formTargetFormat();

			if($this-&gt;errors)
			{
				$error_list = implode('; ', $this-&gt;errors);
				die(Tools::jsonEncode(array('errors' =&gt; $error_list)));
			} else 
				die(Tools::jsonEncode(array('success' =&gt; true)));
				
		}
	}
</pre>
<p><strong>Explanation:</strong> We only need to run this method for our ajax call, and only when customization data is sent over. After checking it, we simply run the methods Prestashop uses when submitting a regular customization form:</p>
<pre class="brush: php; title: ; notranslate">

			$this-&gt;pictureUpload();
			$this-&gt;textRecord();
			$this-&gt;formTargetFormat();


</pre>
<p>Please notice <strong>pictureUpload</strong> is currently not being used, as we are not uploading anything. Also, we need to create a new cart in case it does not exist, before adding the text to it, so it has an id to deal with.</p>
<p>Then, we check for errors, sending them back to the ajax-cart.js file if there are, otherwise returning success. Since we want to make sure data has been saved, let&#8217;s go back to our JS for a second, and do something on the &#8220;success&#8221; method of the ajax call:</p>
<pre class="brush: jscript; title: ; notranslate">
		if(addedFromProductPage &amp;&amp; $('#customizationForm').length &gt; 0)
		{
	
			$('#quantityBackup').val($('#quantity_wanted').val());
			customAction = $('#customizationForm').attr('action');
			$('body select[id^=&quot;group_&quot;]').each(function() {
				customAction = customAction.replace(new RegExp(this.id + '=\\d+'), this.id +'=' + this.value);
			});
			// ajax to product page with custom action
			var customization_entries = $('#customizationForm').serialize();
			$.ajax({
				type: 'POST',
				data: customization_entries+ '&amp;ajax=1',
				dataType: 'json',
				url: customAction,
				success: function(data){
					if(typeof(data.errors) !== 'undefined')
					{
						alert('Error while saving customization data');
						return;
					}
						
				}
			})	
		}
</pre>
<p>We basically only added this part</p>
<pre class="brush: jscript; title: ; notranslate">

if(typeof(data.errors) !== 'undefined')
{
	alert('Error while saving customization data');
	return;
}

</pre>
<p>To the success handler, that triggers when the ajax call is successful. Of course, you might want to expand this, and add a further level of checks to make sure data has really been saved. However, if the field is required, your product will not be added to the cart, in any case.</p>
<p>At this point, try writing something in the field, then click add to cart. <strong>What? Not working? Why?</strong> Prestashop can be nasty to deal with; we have to perform one last modification.</p>
<div class="separator"></div>
<h2>Tools.js</h2>
<p>The last file we need to deal with might be a pain in case you upgrade. Therefore, make sure you keep a backup of the modification and/or write these steps somewhere, in case you need to apply them again. Open up <em>js/tools.js</em>. What we are interested in is the <strong>checkCustomizations</strong> method:</p>
<pre class="brush: jscript; title: ; notranslate">
function checkCustomizations()
{
	var pattern = new RegExp(' ?filled ?');

	if (typeof customizationFields != 'undefined')
		for (var i = 0; i &lt; customizationFields.length; i++)
		{
			/* If the field is required and empty then we abort */
			if (parseInt(customizationFields[i][1]) == 1 &amp;&amp; ($('#' + customizationFields[i][0]).html() == '' ||  $('#' + customizationFields[i][0]).text() != $('#' + customizationFields[i][0]).val()) &amp;&amp; !pattern.test($('#' + customizationFields[i][0]).attr('class')))
				return false;
		}
	return true;
}
</pre>
<p>Pay attention to the following line</p>
<pre class="brush: jscript; title: ; notranslate">
function checkCustomizations()
{
	if (parseInt(customizationFields[i][1]) == 1 &amp;&amp; ($('#' + customizationFields[i][0]).html() == '' ||  $('#' + customizationFields[i][0]).text() != $('#' + customizationFields[i][0]).val()) &amp;&amp; !pattern.test($('#' + customizationFields[i][0]).attr('class')))
				return false;


</pre>
<p>This is what is currently preventing us from saving our customization. Actually, it gets saved, but the product is not added to the cart.<br />
let&#8217;s get rid of a good portion of it</p>
<pre class="brush: jscript; title: ; notranslate">

	if (parseInt(customizationFields[i][1]) == 1 &amp;&amp; ($('#' + customizationFields[i][0]).val() == ''))
		return false;


</pre>
<p>The only thing we are doing to check it, is making sure it has a value. THat is all we need for now!<br />
Refresh and test, it should be working now!</p>
<div class="separator"></div>
<h2>Next up&#8230;</h2>
<p>Saving text customization fields when hitting the add to cart button was not too complicated. Things will get really nasty in the next tutorial, when we will deal with asynchronous file uploads! Stay tuned!</p>
<p><a href="http://nemops.com/save-prestashop-custom-fields-add-to-cart-2/#.VUnNyfnzrmi" title="Save Prestashop Custom fields on “Add to cart” – Part 2"> Save Prestashop Custom fields on “Add to cart” – Part 2 &raquo;</a></p>
<p>The post <a rel="nofollow" href="http://nemops.com/save-prestashop-custom-fields-add-to-cart/">Save Prestashop Custom fields on &#8220;Add to cart&#8221; &#8211; Part 1</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/save-prestashop-custom-fields-add-to-cart/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>How to show &#8220;spend X to get Free Shipping&#8221; in Prestashop</title>
		<link>http://nemops.com/prestashop-show-free-shipping/</link>
		<comments>http://nemops.com/prestashop-show-free-shipping/#comments</comments>
		<pubDate>Mon, 04 Aug 2014 10:07:28 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[free shipping]]></category>
		<category><![CDATA[order]]></category>
		<category><![CDATA[prestashop 1.6]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2107</guid>
		<description><![CDATA[<p>In this Prestashop tutorial, we will see how to boost our sales by letting customers know how much they still have to spend in order to be eligible for free shipping. Version used: Prestashop 1.6 Setting the Free Shipping amount To keep thing simple, in this tutorial we will only consider the &#8220;Free shipping starts [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-show-free-shipping/">How to show &#8220;spend X to get Free Shipping&#8221; in Prestashop</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In this Prestashop tutorial, we will see how to boost our sales by letting customers know how much they still have to spend in order to be eligible for free shipping.</p>
<p><span id="more-2107"></span></p>
<p>Version used: Prestashop 1.6</p>
<h2>Setting the Free Shipping amount</h2>
<p>To keep thing simple, in this tutorial we will only consider the &#8220;<strong>Free shipping starts at</strong>&#8221; value that we can configure in the back office, instead of dealing with all the 0-fee weight or price ranges that it&#8217;s possible to setup for each carrier.</p>
<p>Therefore, before starting, head to <strong>Shipping -> Preferences</strong> and set &#8220;<strong>Free shipping starts at</strong>&#8221; to any value you like. Please notice this represent the price in the default currency, and it&#8217;s not possible to set up one for each, at the time being.</p>
<div class="separator"></div>
<h2>Retrieving the Free shipping value &#8211; 2 approaches</h2>
<p>When dealing with an MVC pattern, the best approach is usually to keep logic and display code separated. Prestashop, however, allows us to retrieve the previously set configuration value in templates too, saving us the trouble to create an override and extend the default <strong>OrderController</strong>, in order to assign the value we need. </p>
<p>Therefore, given that <strong>the best way to go would be to create an override, grab the configuration value, and assign it to the template</strong>, for simplicity reasons I will get it directly in the template, so it&#8217;s ready to use.</p>
<div class="separator"></div>
<h2>Amending the template: shopping-cart.tpl</h2>
<p>Reach your theme folder and open up <strong>shopping-cart.tpl</strong>. We will be adding our small advertisement right below the cart summary. This is the perfect chance to apply some cross-selling principles; therefore, if you use the cross-selling module in the cart page, <strong>the best spot to maximize your cross-selling rate is right above it, before the shopping cart hook </strong>.</p>
<p>Locate:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
&lt;div id=&quot;HOOK_SHOPPING_CART&quot;&gt;{$HOOK_SHOPPING_CART}&lt;/div&gt;
</pre>
<p>And right before it, add the following</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
{assign var='freeshipping_price' value=Configuration::get('PS_SHIPPING_FREE_PRICE')}
</pre>
<p><strong>Explanation</strong>: as I mentioned before, I am grabbing the free shipping value directly from the tpl file, and assigning it to a variable that can be used within our Prestashop template.</p>
<p>Then, we need to check if it is actually holding a value</p>
<pre class="brush: php; html-script: true; title: ; notranslate">

	{assign var='freeshipping_price' value=Configuration::get('PS_SHIPPING_FREE_PRICE')}
	{if $freeshipping_price}
		{assign var='freeshipping_price_converted' value={toolsConvertPrice price=$freeshipping_price}}	
	{/if}


</pre>
<p><strong>Explanation:</strong> if the value exists, we need to convert it to the current currency (which might be other than the default). Therefore, we use the very handy <strong>toolsConvertPrice</strong> method to make sure the value is correctly set to the actual customer currency.</p>
<p>What&#8217;s next? We need to compare the total cart value without shipping to the free shipping one, and display a message in case it&#8217;s positive:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
	
	{assign var='freeshipping_price' value=Configuration::get('PS_SHIPPING_FREE_PRICE')}

	{if $freeshipping_price}
		{assign var='freeshipping_price_converted' value={toolsConvertPrice price=$freeshipping_price}}


		{math equation='a-b' a=$total_price b=$total_shipping assign='total_without_shipping'}
		{math equation='a-b' a=$freeshipping_price_converted b=$total_without_shipping assign='remaining_to_spend'}

		{if $remaining_to_spend &gt; 0}
			&lt;p&gt;{l s='Your total (without shipping) is'} {convertPrice price=$total_without_shipping}&lt;/p&gt;
			&lt;p&gt;&lt;strong&gt;{l s='You will be eligible for free shipping if you spend another'} {convertPrice price=$remaining_to_spend}&lt;/strong&gt;&lt;/p&gt;
		{/if}
	

	{/if}

</pre>
<p><strong>Explanation:</strong> first, we subtract the total shipping price from the overall total, which is the value taken in consideration by Prestashop when deciding if a cart is eligible or not, and then we simply subtract it from our minimum free shipping threshold. If the result is positive, we tell our customers how much is left to get rid of the shipping charge!</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-show-free-shipping/">How to show &#8220;spend X to get Free Shipping&#8221; in Prestashop</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-show-free-shipping/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Adding multiple products and quantities to Prestashop&#8217;s Cart</title>
		<link>http://nemops.com/prestashop-cart-multiple-products-quantities/</link>
		<comments>http://nemops.com/prestashop-cart-multiple-products-quantities/#comments</comments>
		<pubDate>Tue, 01 Oct 2013 10:41:53 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Theming]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[multiple]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=1618</guid>
		<description><![CDATA[<p>In today&#8217;s tutorial, we will see how to enable a &#8216;Bulk add to cart&#8217; functionality in Prestashop, to allow customers to add multiple products and quantities to their cart with a single click! Compatibility: Prestashop 1.5 (all versions), Prestashop 1.4 with slight changes What we will do The main purpose of this tutorial will be [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-cart-multiple-products-quantities/">Adding multiple products and quantities to Prestashop&#8217;s Cart</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In today&#8217;s tutorial, we will see how to enable a &#8216;Bulk add to cart&#8217; functionality in Prestashop, to allow customers to add multiple products and quantities to their cart with a single click!</p>
<p><span id="more-1618"></span></p>
<ul>
<li>Compatibility: <strong>Prestashop 1.5</strong> (all versions), <strong>Prestashop 1.4 with slight changes</strong></li>
</ul>
<h2>What we will do</h2>
<p>The main purpose of this tutorial will be to add checkboxes so that customers can select which products they want, and add them to cart with a single click (provided that they are on the same page!). However, since we are at it, we will also add a text input so that they can choose how many items they want to add as well. This new box will also work with the regular &#8216;Add to cart&#8217;, so feel free to follow the last step only if you want! Let&#8217;s get started.</p>
<div class="separator"></div>
<h2>The checkboxes and trigger button</h2>
<p>The very first thing we need to do is add a couple of checkboxes so that people can choose which products they want. Of course, after they do this they need to be able to add them to cart as well, therefore we also need a <strong>trigger</strong> button.</p>
<p>As always, I will be using the default theme for the demonstration, and line numbers and contents might change if you use a custom one.</p>
<p>Open up <strong>product-list.tpl</strong>, located in your theme&#8217;s folder. Choose a suitable place for the checkbox; I decided to add it right above the normal &#8216;Add to cart&#8217;. So, after line 58, or wherever else you want inside the block, add:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
&lt;span class=&quot;checktoadd&quot;&gt;
	{l s='Check to add to cart'} &lt;input type=&quot;checkbox&quot; value=&quot;{$product.id_product}&quot; class=&quot;add_me_to_cart&quot;/&gt;
&lt;/span&gt;
</pre>
<p>Save and refresh a category page, you should see something like this:</p>
<p><img src="http://nemops.com/wp-content/uploads/2013/10/FIRST.png" alt="Add multiple products to Prestashop&#039;s Cart in one click" width="540" height="503" class="alignnone size-full wp-image-1624" /></p>
<p>Yeah, it looks odd, but it&#8217;s only to demonstrate the purpose! As you can see, we are giving the checkbox a value equal to the product id, so that we know which ones are checked.</p>
<p>Let&#8217;s now add the trigger: At the very end of the file, right before this:</p>
<pre class="brush: xml; title: ; notranslate">

	&lt;!-- /Products list --&gt;
{/if}

</pre>
<p>Add this:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
	&lt;a href=&quot;javascript:void(0)&quot; class=&quot;multi_add button&quot;&gt;{l s='Add selected to cart'}&lt;/a&gt;
</pre>
<p>Nothing special here, it&#8217;s a normal button without any anchor link. We have our ground ready: let&#8217;s move on!</p>
<p>As a final touch, we need a piece of text to inform our customers if no item is checked. Add the following <strong>at the very end</strong> of product-list.tpl</p>
<pre class="brush: xml; title: ; notranslate">

&lt;script type='text/javascript'&gt;
	var noSelectionTxt = &quot;{l s='No items selected'}&quot;;
&lt;/script&gt;

</pre>
<div class="separator"></div>
<h2>The multiple &#8216;Add to cart&#8217; Javascript</h2>
<p>In order to add those products to cart at once, we need, needless to say, javascript. We will simply extend the core &#8216;Ajax add to cart&#8217; functionality; therefore, this method will not work for those who decided not to use ajax.</p>
<p>Depending on your theme, you might, or might not have the file we need in the theme&#8217;s folder. Reach it, then go to <em>js/modules</em> and look for <strong>blockcart</strong>. If it&#8217;s there already, access the folder and open <strong>ajax-cart.js</strong>. If not, as if you are using the default theme, go back to Prestashop&#8217;s root, then <em>modules/blockcart</em>, grab <strong>ajax-cart.js</strong>, copy and paste it in the previously mentioned folder. At the end, this is the file we need to edit: <strong>themes/THEMENAME/js/modules/blockcart/ajax-cart.js</strong>.</p>
<p>Open up the file, and locate the following snippet at the beginning of it:</p>
<pre class="brush: jscript; title: ; notranslate">
	//for every 'add' buttons...
	$('.ajax_add_to_cart_button').unbind('click').click(function(){
		...
	}
</pre>
<p>Right <strong>before</strong> it, let&#8217;s start adding our code:</p>
<pre class="brush: jscript; title: ; notranslate">
		$('.multi_add').unbind('click').click(function() {
				
			// get all checked items
			var checked_items = $('.add_me_to_cart:checked');

			if(checked_items.length == 0)
				alert(noSelectionTxt);
			else {
			}
			

		});
</pre>
<p>As a first step, target the click to out multi add button, and  store all check items&#8217; checkboxes inside a variable. If none is selected, we alert a message, else, let&#8217;s add them to cart!</p>
<pre class="brush: jscript; title: ; notranslate">
		$('.multi_add').unbind('click').click(function() {
				
			// get all checked items
			var checked_items = $('.add_me_to_cart:checked');

			if(checked_items.length == 0)
				alert(noSelectionTxt);
			else {
				$.each(checked_items, function(i, item) {
					 var id_prd = $(item).val(); // val of the checkbox!
					 ajaxCart.add(id_prd, null, false, $(item).parent().parent().find('.ajax_add_to_cart_button'));
					 // uncheck current element
					 $(item).removeAttr('checked');
				});
			}
			

		});
</pre>
<p>For each of the items stored in the variable, we grab the <strong>val()</strong> attribute of the checkbox, which is the product id. Then, we simply call the default  <strong>ajaxCart.add</strong> function to add them. Note the following:</p>
<pre class="brush: jscript; title: ; notranslate">

$(item).parent().parent().find('.ajax_add_to_cart_button')

</pre>
<p>We passed it as fourth parameter to the function. It is referring to the default ajax add to cart button, so that the base script can grab the product image for the &#8216;add to cart&#8217; animation.</p>
<p>In the end, we uncheck the box.</p>
<p>Save and test, we should already be done for this first step!</p>
<div class="separator"></div>
<h2>Adding multiple quantities to Prestashop&#8217;s cart</h2>
<p>As we are done with the first step, let&#8217;s take care of adding the quantity input boxes. It&#8217;s far easier than it looks. Once more, locate a suitable place for the new content. I will get rid of the &#8216;view&#8217; button of the default theme, to avoid overcrowding each product block.</p>
<p>Therefore, locate the following snippet in <strong>product-list.tpl</strong>:</p>
<pre class="brush: xml; title: ; notranslate">
	&lt;a class=&quot;button lnk_view&quot; href=&quot;{$product.link|escape:'htmlall':'UTF-8'}&quot; title=&quot;{l s='View'}&quot;&gt;{l s='View'}&lt;/a&gt;
</pre>
<p>And replace it with:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;input size=&quot;1&quot; type=&quot;text&quot; class=&quot;multi_product_quantity&quot; value=&quot;1&quot; /&gt;
</pre>
<p><img src="http://nemops.com/wp-content/uploads/2013/10/SECOND.png" alt="Add multiple product quantities to Prestashop&#039;s Cart in one click" width="534" height="543" class="alignnone size-full wp-image-1625" /></p>
<p>Messy. But once again, this is a simple demonstration.</p>
<p>Now, for the javascript part, go back to <strong>ajax-cart.js</strong> (if you haven&#8217;t followed the tutorial so far, refer back to the beginning of &#8220;The multiple &#8216;Add to cart&#8217; Javascript&#8221;). let&#8217;s first add the quantity variable to the default button, locate the following:</p>
<pre class="brush: jscript; title: ; notranslate">
	//for every 'add' buttons...
	$('.ajax_add_to_cart_button').unbind('click').click(function(){
		var idProduct =  $(this).attr('rel').replace('nofollow', '').replace('ajax_id_product_', '');
		if ($(this).attr('disabled') != 'disabled')
			ajaxCart.add(idProduct, null, false, this);
		return false;
	});
</pre>
<p>Store the chosen quantity as a variable right after the product id:</p>
<pre class="brush: jscript; title: ; notranslate">
		//for every 'add' buttons...
		$('.ajax_add_to_cart_button').unbind('click').click(function(){
			var idProduct =  $(this).attr('rel').replace('nofollow', '').replace('ajax_id_product_', '');
			var qty = $(this).parent().find('.multi_product_quantity').val();

			// if quantity is 0 or NaN, return;
			if(qty == 0 || isNaN(qty))
				return false;

			if ($(this).attr('disabled') != 'disabled')
				ajaxCart.add(idProduct, null, false, this);
			return false;
		});
</pre>
<p>If quantity is 0, or a non-numeric value, we simply do not perform the action. Lastly, add the quantity as fifth parameter to the ajaxCart.add method</p>
<pre class="brush: jscript; title: ; notranslate">
		//for every 'add' buttons...
		$('.ajax_add_to_cart_button').unbind('click').click(function(){
			var idProduct =  $(this).attr('rel').replace('nofollow', '').replace('ajax_id_product_', '');
			var qty = $(this).parent().find('.multi_product_quantity').val();

			// if quantity is 0 or NaN, return;
			if(qty == 0 || isNaN(qty))
				return false;

			if ($(this).attr('disabled') != 'disabled')
				ajaxCart.add(idProduct, null, false, this, qty);
			return false;
		});
</pre>
<p>And we are done! At this point, we can amend the previous section&#8217;s code, and <strong>allow adding multiple products and multiple quantities together</strong>.</p>
<pre class="brush: jscript; title: ; notranslate">

		$('.multi_add').unbind('click').click(function() {
				
			// get all checked items
			var checked_items = $('.add_me_to_cart:checked');

			if(checked_items.length == 0)
				alert(noSelectionTxt);
			else {
				$.each(checked_items, function(i, item) {
					 $(item).parent().parent().find('.ajax_add_to_cart_button').click();
				});
			}

		});

</pre>
<p>There is no point in calling the same code 2 times, therefore we can simply trigger the default ajax add to cart button for each product.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/prestashop-cart-multiple-products-quantities/">Adding multiple products and quantities to Prestashop&#8217;s Cart</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/prestashop-cart-multiple-products-quantities/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Quick Tip: hide shipping cost for non registered users</title>
		<link>http://nemops.com/hide-shipping-cost/</link>
		<comments>http://nemops.com/hide-shipping-cost/#comments</comments>
		<pubDate>Tue, 06 Aug 2013 10:54:47 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[shipping]]></category>
		<category><![CDATA[visitors]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=1458</guid>
		<description><![CDATA[<p>In this quick tip, we will see how to hide the shipping cost, or misleading free shipping label for non-registered customers. Watch The Screencast (text below) &#160; &#160; Hide shipping cost for non registered users You might have come across this issue if you setup zones so that carriers have a different price depending on [&#8230;]</p>
<p>The post <a rel="nofollow" href="http://nemops.com/hide-shipping-cost/">Quick Tip: hide shipping cost for non registered users</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In this quick tip, we will see how to hide the shipping cost, or misleading free shipping label for non-registered customers.</p>
<p><span id="more-1458"></span></p>
<h2>Watch The Screencast (text below)</h2>

	<div class="video-embed">
		<iframe width="640" height="360" src="http://www.youtube.com/embed/6CvOzUZ_SP4" frameborder="0" allowfullscreen></iframe><p><a href="https://www.youtube.com/user/NemoPostScriptum/videos" rel="nofollow" title="Subscribe Post Scriptum's Youtube Channel">Subscribe Post Scriptum's Youtube Channel</a></p>	</div>
<div class="separator"></div>
<p>&nbsp;</p>
<h2>Hide shipping cost for non registered users</h2>
<p>You might have come across this issue if you setup zones so that carriers have a different price depending on the customer’s address: a default shipping price, or even worse a free shipping label is shown for everybody who has not login yet.</p>
<p>This can be misleading at times, and some of your customers will definitely get angry if the price rises after adding shipping address details. Moreover, we do not want this.</p>
<p>First, let’s disable our carrier (remember to do it for all carriers if you use many) for visitors in the back office. Go to Shipping -> Carriers and click on a carrier. Then, disable it for visitors.</p>
<p><img src="http://nemops.com/wp-content/uploads/2013/08/disablecarrier.png" alt="Disable carrier for visitors" width="521" height="495" class="alignnone size-full wp-image-1461" /></p>
<p>You can also do it for guests if you disabled the guest checkout.</p>
<p>Refresh and see it says free shipping! This is even more misleading but now we can target that label and still have the total match the products total price.</p>
<p>Let’s go to <em>modules/blockcart</em> and copy <strong>blockcart.tpl</strong> in the theme folder <em>modules/blockcart</em>. Open it and locate the second script block:</p>
<pre class="brush: xml; title: ; notranslate">

&lt;script type=&quot;text/javascript&quot;&gt;
var customizationIdMessage = '{l s='Customization #' mod='blockcart' js=1}';
var removingLinkText = '{l s='Please remove this product from my cart.' mod='blockcart' js=1}';
var freeShippingTranslation = '{l s='Free shipping!' mod='blockcart' js=1}';
var freeProductTranslation = '{l s='Free!' mod='blockcart' js=1}';
var delete_txt = '{l s='Delete' mod='blockcart' js=1}';
&lt;/script&gt;

</pre>
<p>See where it reads free shipping? We need to change the block as follows</p>
<pre class="brush: php; html-script: true; title: ; notranslate">

&lt;script type=&quot;text/javascript&quot;&gt;
var customizationIdMessage = '{l s='Customization #' mod='blockcart' js=1}';
var removingLinkText = '{l s='Please remove this product from my cart.' mod='blockcart' js=1}';

var freeProductTranslation = '{l s='Free!' mod='blockcart' js=1}';
var delete_txt = '{l s='Delete' mod='blockcart' js=1}';

//&lt;![CDATA[[

	{if !$logged AND !$cart-&gt;id_customer}
		var freeShippingTranslation = '{l s='Login to see the shipping cost!' mod='blockcart' js=1}';		
	{else}
		var freeShippingTranslation = '{l s='Free shipping!' mod='blockcart' js=1}';
	{/if}

//]]&gt;
&lt;/script&gt;

</pre>
<p>As you can see, we removed the free shipping text and added it below. We used a small trick to target the unregistered customer. So, <strong>If the customer is not logged in, nor has added any shipping information</strong> (that is, no customer id exists for him), then show a different text. Else, it is okay to display the free shipping label.</p>
<p>It looks a bit ugly now, because the cart block is still displaying the shipping label. Let’s hide that as well! Locate the following at about line 154 of the same file:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
&lt;span&gt;{l s='Shipping' mod='blockcart'}&lt;/span&gt;
</pre>
<p>And change it the following way</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
{if $logged OR $cart-&gt;id_customer}
	&lt;span&gt;{l s='Shipping' mod='blockcart'}&lt;/span&gt;
{/if}	
</pre>
<p>This time, the text will only be shown if the customer is logged or has already added shipping information.</p>
<p>As a finishing touch, we can add the little information to <strong>shopping cart.tpl</strong> as well (you can find it in the theme folder once again). Locate this:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">

&lt;tr class=&quot;cart_total_delivery&quot; style=&quot;{if !isset($carrier-&gt;id) || is_null($carrier-&gt;id)}display:none;{/if}&quot;&gt;
	&lt;td colspan=&quot;5&quot;&gt;{l s='Shipping'}&lt;/td&gt;
	&lt;td colspan=&quot;2&quot; class=&quot;price&quot; id=&quot;total_shipping&quot;&gt;{l s='Free Shipping!'}&lt;/td&gt;
&lt;/tr&gt;


</pre>
<p>And change it this way</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
&lt;tr class=&quot;cart_total_delivery&quot;&gt;
	&lt;td colspan=&quot;5&quot;&gt;{l s='Shipping'}&lt;/td&gt;
	&lt;td colspan=&quot;2&quot; class=&quot;price&quot; id=&quot;total_shipping&quot;&gt;
		
		{if !$logged AND !$cart-&gt;id_customer}
			{l s='Login for the correct price'}
		{else}
			{l s='Free Shipping!'}
		{/if}
		

	&lt;/td&gt;
&lt;/tr&gt;
</pre>
<p>Note that other than adding the same condition as before, we also removed the display:none style. There is a little downside to this, as that block will always be shown, even if there are no carriers available for the destination. However, this won&#8217;t happen if you setup zones, countries and states the correct way.</p>
<p>The post <a rel="nofollow" href="http://nemops.com/hide-shipping-cost/">Quick Tip: hide shipping cost for non registered users</a> appeared first on <a rel="nofollow" href="http://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://nemops.com/hide-shipping-cost/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
