Jump to content

How to remove save button for customized fields?


otzy

Recommended Posts

Working on 1.4.9.0! (without Ajax Cart)

 

It is working for 1.4.9.0 without the Ajax cart. I have created two product.tpl files that work. One is for the old stock Prestashop theme. The other is for the new Prestashop 1.5 compatible theme available for download at this link: http://addons.presta...emplate-15.html

 

The product.tpl files move the text boxes up from the bottom and eliminate the "Save" button when used with the CartController override.

 

The override/controller/CartController.php file I used was the one that Ben23 created in post #95 above.

 

Rename the files attached in the zip file to product.tpl and use the one applicable for the stock theme you use. They are named for the "old" and "new" Prestashop themes. Remember to open the blockcart module in the BO and use configure to turn off the ajax cart.

 

All that is needed now is for someone to help debug the ajax-cart.js file so the Ajax cart can be enabled again. For Ajax debug, the old theme uses the blockcart module. If you install the new Prestashop theme there is a module called blockcart2.

product.tpl.zip

Edited by Rhapsody (see edit history)
Link to comment
Share on other sites

  • 2 weeks later...

Working on 1.4.9.0! (without Ajax Cart)

 

It is working for 1.4.9.0 without the Ajax cart. I have created two product.tpl files that work. One is for the old stock Prestashop theme. The other is for the new Prestashop 1.5 compatible theme available for download at this link: http://addons.presta...emplate-15.html

 

The product.tpl files move the text boxes up from the bottom and eliminate the "Save" button when used with the CartController override.

 

The override/controller/CartController.php file I used was the one that Ben23 created in post #95 above.

 

Rename the files attached in the zip file to product.tpl and use the one applicable for the stock theme you use. They are named for the "old" and "new" Prestashop themes. Remember to open the blockcart module in the BO and use configure to turn off the ajax cart.

 

All that is needed now is for someone to help debug the ajax-cart.js file so the Ajax cart can be enabled again. For Ajax debug, the old theme uses the blockcart module. If you install the new Prestashop theme there is a module called blockcart2.

 

I copied your code from "<!-- Customizable products -->

{if $product->customizable}" to "</form>

 

{* Rhapsody moved custo..."

 

I also use Ben23's cartcontroller. But my store keeps saying that I need to save the customization. It doesnt add to cart...

 

why?

Link to comment
Share on other sites

I copied your code from "<!-- Customizable products -->

{if $product->customizable}" to "</form>

 

{* Rhapsody moved custo..."

 

I also use Ben23's cartcontroller. But my store keeps saying that I need to save the customization. It doesnt add to cart...

 

why?

1. What version of ps are you using?

2. What Theme are you using?

3. What directory did you copy Ben23's CartController.php file to?

4. Did you turn off the Ajax cart in the blockcart module?

5. Did you set in the BO performance section Force Compile to Yes and Cache to No in order to recompile your modified template?

Link to comment
Share on other sites

1. What version of ps are you using?

2. What Theme are you using?

3. What directory did you copy Ben23's CartController.php file to?

4. Did you turn off the Ajax cart in the blockcart module?

5. Did you set in the BO performance section Force Compile to Yes and Cache to No in order to recompile your modified template?

 

1. 1.4.9

2. A Theme from template monster.

3. /override/controllers

4. Yes I did

5. Yes, I see the update. And the save button is gone, but it dont work..

 

The weird thing is that the popup that says "please fill in required fields and save customization" is gone. I'm now being transfered to cart.php, and there I get a warning saying I must fill the mandatory fields and press save beforde adding to cart. I then press back and fill in the two textfields, press save, then i can add to cart.

 

--EDIT--

 

Now I dont have the textfields mandatory. But I still need to press save to add the texts to the product.

 

Do I need to modify ajax-cart.js ? as mentioned in this thread before

Edited by adameriksson (see edit history)
Link to comment
Share on other sites

.....

The weird thing is that the popup that says "please fill in required fields and save customization" is gone. I'm now being transfered to cart.php, and there I get a warning saying I must fill the mandatory fields and press save before adding to cart. I then press back and fill in the two textfields, press save, then i can add to cart.

The problem may be the theme from Template Monster. Is it based on the old or new PS theme?

Try the stock PS theme with the mod and see if it works. If so, the problem is with your theme.

If not, more troubleshooting to do.

 

I think it is related to your theme, because when you press back you mention seeing the save button. I believe the save button should be gone completely with the modified tpl file

 

Edit: Post your modified product.tpl file and I will try it on one of my installations.

Edited by Rhapsody (see edit history)
Link to comment
Share on other sites

The problem may be the theme from Template Monster. Is it based on the old or new PS theme?

Try the stock PS theme with the mod and see if it works. If so, the problem is with your theme.

If not, more troubleshooting to do.

 

I think it is related to your theme, because when you press back you mention seeing the save button. I believe the save button should be gone completely with the modified tpl file

 

Edit: Post your modified product.tpl file and I will try it on one of my installations.

 

Sorry, of course I dont see the save button. It was with my own code, sorry. I have your product.tpl code now (only the "Customizable products" part).

 

I paste the whole product.tpl code here

{include file="$tpl_dir./errors.tpl"}
{if $errors|@count == 0}
<script type="text/javascript">
// <![CDATA[
// PrestaShop internal settings
var currencySign = '{$currencySign|html_entity_decode:2:"UTF-8"}';
var currencyRate = '{$currencyRate|floatval}';
var currencyFormat = '{$currencyFormat|intval}';
var currencyBlank = '{$currencyBlank|intval}';
var taxRate = {$tax_rate|floatval};
var jqZoomEnabled = {if $jqZoomEnabled}true{else}false{/if};
//JS Hook
var oosHookJsCodeFunctions = new Array();
// Parameters
var id_product = '{$product->id|intval}';
var productHasAttributes = {if isset($groups)}true{else}false{/if};
var quantitiesDisplayAllowed = {if $display_qties == 1}true{else}false{/if};
var quantityAvailable = {if $display_qties == 1 && $product->quantity}{$product->quantity}{else}0{/if};
var allowBuyWhenOutOfStock = {if $allow_oosp == 1}true{else}false{/if};
var availableNowValue = '{$product->available_now|escape:'quotes':'UTF-8'}';
var availableLaterValue = '{$product->available_later|escape:'quotes':'UTF-8'}';
var productPriceTaxExcluded = {$product->getPriceWithoutReduct(true)|default:'null'} - {$product->ecotax};
var reduction_percent = {if $product->specificPrice AND $product->specificPrice.reduction AND $product->specificPrice.reduction_type == 'percentage'}{$product->specificPrice.reduction*100}{else}0{/if};
var reduction_price = {if $product->specificPrice AND $product->specificPrice.reduction AND $product->specificPrice.reduction_type == 'amount'}{$product->specificPrice.reduction}{else}0{/if};
var specific_price = {if $product->specificPrice AND $product->specificPrice.price}{$product->specificPrice.price}{else}0{/if};
var specific_currency = {if $product->specificPrice AND $product->specificPrice.id_currency}true{else}false{/if};
var group_reduction = '{$group_reduction}';
var default_eco_tax = {$product->ecotax};
var ecotaxTax_rate = {$ecotaxTax_rate};
var currentDate = '{$smarty.now|date_format:'%Y-%m-%d %H:%M:%S'}';
var maxQuantityToAllowDisplayOfLastQuantityMessage = {$last_qties};
var noTaxForThisProduct = {if $no_tax == 1}true{else}false{/if};
var displayPrice = {$priceDisplay};
var productReference = '{$product->reference|escape:'htmlall':'UTF-8'}';
var productAvailableForOrder = {if (isset($restricted_country_mode) AND $restricted_country_mode) OR $PS_CATALOG_MODE}'0'{else}'{$product->available_for_order}'{/if};
var productShowPrice = '{if !$PS_CATALOG_MODE}{$product->show_price}{else}0{/if}';
var productUnitPriceRatio = '{$product->unit_price_ratio}';
var idDefaultImage = {if isset($cover.id_image_only)}{$cover.id_image_only}{else}0{/if};
{*
var ipa_default = {if isset($ipa_default)}{$ipa_default}{/if};
*}
// Customizable field
var img_ps_dir = '{$img_ps_dir}';
var customizationFields = new Array();
{assign var='imgIndex' value=0}
{assign var='textFieldIndex' value=0}
{foreach from=$customizationFields item='field' name='customizationFields'}
{assign var="key" value="pictures_`$product->id`_`$field.id_customization_field`"}
customizationFields[{$smarty.foreach.customizationFields.index|intval}] = new Array();
customizationFields[{$smarty.foreach.customizationFields.index|intval}][0] = '{if $field.type|intval == 0}img{$imgIndex++}{else}textField{$textFieldIndex++}{/if}';
customizationFields[{$smarty.foreach.customizationFields.index|intval}][1] = {if $field.type|intval == 0 && isset($pictures.$key) && $pictures.$key}2{else}{$field.required|intval}{/if};
{/foreach}
// Images
var img_prod_dir = '{$img_prod_dir}';
var combinationImages = new Array();
{if isset($combinationImages)}
{foreach from=$combinationImages item='combination' key='combinationId' name='f_combinationImages'}
 combinationImages[{$combinationId}] = new Array();
 {foreach from=$combination item='image' name='f_combinationImage'}
  combinationImages[{$combinationId}][{$smarty.foreach.f_combinationImage.index}] = {$image.id_image|intval};
 {/foreach}
{/foreach}
{/if}
combinationImages[0] = new Array();
{if isset($images)}
{foreach from=$images item='image' name='f_defaultImages'}
 combinationImages[0][{$smarty.foreach.f_defaultImages.index}] = {$image.id_image};
{/foreach}
{/if}
// Translations
var doesntExist = '{l s='The product does not exist in this model. Please choose another.' js=1}';
var doesntExistNoMore = '{l s='This product is no longer in stock' js=1}';
var doesntExistNoMoreBut = '{l s='with those attributes but is available with others' js=1}';
var uploading_in_progress = '{l s='Uploading in progress, please wait...' js=1}';
var fieldRequired = '{l s='Please fill in all required fields, then save the customization.' js=1}';
{if isset($groups)}
// Combinations
{foreach from=$combinations key=idCombination item=combination}
 addCombination({$idCombination|intval}, new Array({$combination.list}), {$combination.quantity}, {$combination.price}, {$combination.ecotax}, {$combination.id_image}, '{$combination.reference|addslashes}', {$combination.unit_impact}, {$combination.minimal_quantity});
{/foreach}
// Colors
{if $colors|@count > 0}
 {if $product->id_color_default}var id_color_default = {$product->id_color_default|intval};{/if}
{/if}
{/if}
//]]>
</script>
{include file="$tpl_dir./breadcrumb.tpl"}
{if isset($confirmation) && $confirmation}
<p class="confirmation">
{$confirmation}
</p>
{/if}
<div id="primary_block" class="clearfix">
{if isset($adminActionDisplay) && $adminActionDisplay}
<div id="admin-action">
 <p>{l s='This product is not visible to your customers.'}
 <input type="hidden" id="admin-action-product-id" value="{$product->id}" />
 <input type="submit" value="{l s='Publish'}" class="exclusive" onclick="submitPublishProduct('{$base_dir}{$smarty.get.ad}', 0)"/>
 <input type="submit" value="{l s='Back'}" class="exclusive" onclick="submitPublishProduct('{$base_dir}{$smarty.get.ad}', 1)"/>
 </p>
 <div class="clear" ></div>
 <p id="admin-action-result"></p>
 </p>
</div>
{/if}
{* left column *}
<div id="pb-right-column">
{* product img *}
 <div id="image-block" class="bordercolor">
  {if $have_image}
  <img src="{$link->getImageLink($product->link_rewrite, $cover.id_image, 'large')}"
{if $jqZoomEnabled}class="jqzoom" alt="{$link->getImageLink($product->link_rewrite, $cover.id_image, 'thickbox')}"{else} title="{$product->name|escape:'htmlall':'UTF-8'}" alt="{$product->name|escape:'htmlall':'UTF-8'}" {/if} id="bigpic" width="{$largeSize.width}" height="{$largeSize.height}" />
  {else}
  <img src="{$img_prod_dir}{$lang_iso}-default-large.jpg" id="bigpic" alt="" title="{$cover.legend|escape:'htmlall':'UTF-8'}" width="{$largeSize.width}" height="{$largeSize.height}" />
  {/if}
 </div>
 {if isset($images) && count($images) > 0}
{* thumbnails *}
 <div id="views_block" {if isset($images) && count($images) < 2}class="hidden"{/if}>
 {if isset($images) && count($images) > 3}<a id="view_scroll_left" class="hidden" title="{l s='Other views'}" href="javascript:{ldelim}{rdelim}">{l s='Previous'}</a>{/if}
 <div id="thumbs_list">
  <ul id="thumbs_list_frame">
{if isset($images)}
 {foreach from=$images item=image name=thumbnails}
 {assign var=imageIds value="`$product->id`-`$image.id_image`"}
 <li id="thumbnail_{$image.id_image}" class="{if $smarty.foreach.thumbnails.last}thumb_last{/if}">
  <a href="{$link->getImageLink($product->link_rewrite, $imageIds, 'thickbox')}" rel="other-views" class="thickbox bordercolor {if (isset($image.cover) AND $image.cover == 1) OR (!isset($image.cover) AND $smarty.foreach.thumbnails.first)}shown{/if}" title="{$image.legend|htmlspecialchars}">
   <img id="thumb_{$image.id_image}" src="{$link->getImageLink($product->link_rewrite, $imageIds, 'medium')}" alt="{$image.legend|htmlspecialchars}" height="{$mediumSize.height}" width="{$mediumSize.width}" />
  </a>
 </li>
 {/foreach}
{/if}
  </ul>
 </div>
 {if isset($images) && count($images) > 3}<a id="view_scroll_right" title="{l s='Other views'}" href="javascript:{ldelim}{rdelim}">{l s='Next'}</a>{/if}
 </div>
 {/if}
 {if isset($images) && count($images) > 1}<span id="wrapResetImages" style="display:none;"><div><a id="resetImages" href="{$link->getProductLink($product)}" onclick="$('span#wrapResetImages').hide('slow');return (false);">{l s='Display all pictures'}</a></div></span>{/if}
{* usefull links *}
 <ul id="usefull_link_block" class="bordercolor">
  {if $HOOK_EXTRA_LEFT}{$HOOK_EXTRA_LEFT}{/if}
  <li class="print"><a href="javascript:print();">{l s='Print'}</a></li>
  {if $have_image && !$jqZoomEnabled}
  <li class="view-size"><span id="view_full_size" class="span_link">{l s='View full size'}</span></li>
  {/if}
 </ul>
{* social icons *}
	<div class="share bordercolor"><!-- AddThis Button BEGIN -->
  <div class="addthis_toolbox addthis_default_style ">
<a class="addthis_button_facebook_like" fb:like:layout="button_count"></a>
<a class="addthis_button_tweet"></a>
<a class="addthis_button_google_plusone" g:plusone:size="medium"></a>
<a class="addthis_counter addthis_pill_style"></a>
  </div>
  <script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#pubid=ra-4f419f410efe76d3"></script>
 </div>
</div>
{* right column *}
<div id="pb-left-column">
 <h1>{$product->name|escape:'htmlall':'UTF-8'}</h1>
 {if ($product->show_price AND !isset($restricted_country_mode)) OR isset($groups) OR $product->reference OR (isset($HOOK_PRODUCT_ACTIONS) && $HOOK_PRODUCT_ACTIONS)}
 <form id="buy_block" class="bordercolor" {if $PS_CATALOG_MODE AND !isset($groups) AND $product->quantity > 0}class="hidden"{/if} action="{$link->getPageLink('cart.php')}" method="post">
{* hidden datas *}
  <p class="hidden">
<input type="hidden" name="token" value="{$static_token}" />
<input type="hidden" name="id_product" value="{$product->id|intval}" id="product_page_product_id" />
<input type="hidden" name="add" value="1" />
<input type="hidden" name="id_product_attribute" id="idCombination" value="" />
  </p>
  {if $product->show_price AND !isset($restricted_country_mode) AND !$PS_CATALOG_MODE}
<div class="price bordercolor">
 {if !$priceDisplay || $priceDisplay == 2}{assign var='productPrice' value=$product->getPrice(true, $smarty.const.NULL, 2)}{assign var='productPriceWithoutRedution' value=$product->getPriceWithoutReduct(false, $smarty.const.NULL)}{elseif $priceDisplay == 1}{assign var='productPrice' value=$product->getPrice(false, $smarty.const.NULL, 2)}{assign var='productPriceWithoutRedution' value=$product->getPriceWithoutReduct(true, $smarty.const.NULL)}{/if}
{* price *}
 <span class="our_price_display">
  {if $priceDisplay >= 0 && $priceDisplay <= 2}
  <span id="our_price_display" class="price">{convertPrice price=$productPrice}</span>
  {if $tax_enabled && ((isset($display_tax_label) && $display_tax_label == 1) OR !isset($display_tax_label))}
   <span class="our_price_display_tax">{if $priceDisplay == 1}{l s='tax excl.'}{else}{l s='tax incl.'}{/if}</span>
  {/if}
  {/if}
 </span>
{* tax excl *}
 {if $priceDisplay == 2}
  <span id="pretaxe_price"><span id="pretaxe_price_display">{convertPrice price=$product->getPrice(false, $smarty.const.NULL, 2)}</span> {l s='tax excl.'}</span>
 {/if}
{* add to cart btn *}
 <p id="add_to_cart" {if (!$allow_oosp && $product->quantity <= 0) OR !$product->available_for_order OR (isset($restricted_country_mode) AND $restricted_country_mode) OR $PS_CATALOG_MODE} style="display:none;"{/if}>
  <a class="exclusive" href="javascript:document.getElementById('add2cartbtn').click();">{l s='Add to cart'}</a>
  <input id="add2cartbtn" type="submit" name="Submit" value="{l s='Add to cart'}" />
 </p>
{* quantity wanted *}
 <p id="quantity_wanted_p"{if (!$allow_oosp && $product->quantity == 0) OR $virtual OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none;"{/if}>
  <input type="text" name="qty" id="quantity_wanted" class="text" value="{if isset($quantityBackup)}{$quantityBackup|intval}{else}{if $product->minimal_quantity > 1}{$product->minimal_quantity}{else}1{/if}{/if}" size="2" maxlength="3" {if $product->minimal_quantity > 1}onkeyup="checkMinimalQuantity({$product->minimal_quantity});"{/if} />
  <label>{l s='Quantity :'}</label>
 </p>
</div>
{* minimal quantity wanted *}
<p id="minimal_quantity_wanted_p" class="bordercolor"{if $product->minimal_quantity <= 1 OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display:none;"{/if}>{l s='You must add '}<b id="minimal_quantity_label">{$product->minimal_quantity}</b>{l s=' as a minimum quantity to buy this product.'}</p>
{if $product->minimal_quantity > 1}<script type="text/javascript">checkMinimalQuantity();</script>{/if}
  {/if}
<div class="other_options bordercolor">
  {if $product->show_price AND !isset($restricted_country_mode) AND !$PS_CATALOG_MODE}
<div id="other_prices">
 {if $product->specificPrice AND $product->specificPrice.reduction}
{* old price *}
 <p id="old_price">
  {if $priceDisplay >= 0 && $priceDisplay <= 2}
   {if $productPriceWithoutRedution > $productPrice}
	<span id="old_price_display">{convertPrice price=$productPriceWithoutRedution}</span>
	{if $tax_enabled}{if $priceDisplay == 1}{l s='tax excl.'}{else}{l s='tax incl.'}{/if}{/if}
   {/if}
  {/if}
 </p>
 {/if}
{* reduction percent *}
 {if $product->specificPrice AND $product->specificPrice.reduction_type == 'percentage'}
 <p id="reduction_percent">{l s='(price reduced by'} <span id="reduction_percent_display">{$product->specificPrice.reduction*100}</span> %{l s=')'}</p>
 {/if}
{* pack price *}
 {if $packItems|@count}
 <p class="pack_price">{l s='instead of'} <span style="text-decoration: line-through;">{convertPrice price=$product->getNoPackPrice()}</span></p>
 {/if}
{* price ecotax *}
 {if $product->ecotax != 0}
 <p class="price-ecotax">{l s='include'} <span id="ecotax_price_display">{if $priceDisplay == 2}{$ecotax_tax_exc|convertAndFormatPrice}{else}{$ecotax_tax_inc|convertAndFormatPrice}{/if}</span> {l s='for green tax'}
  {if $product->specificPrice AND $product->specificPrice.reduction}<br />{l s='(not impacted by the discount)'}{/if}
 </p>
 {/if}
{* unit price *}
 {if !empty($product->unity) && $product->unit_price_ratio > 0.000000}
  {math equation="pprice / punit_price"  pprice=$productPrice  punit_price=$product->unit_price_ratio assign=unit_price}
  <p class="unit-price"><span id="unit_price_display" class="price">{convertPrice price=$unit_price}</span> {l s='per'} {$product->unity|escape:'htmlall':'UTF-8'}</p>
 {/if}
{* online only *}
 {if $product->online_only}<p class="online_only">{l s='Online only'}!</p>{/if}
{* number of item in stock *}
 {if ($display_qties == 1 && !$PS_CATALOG_MODE && $product->available_for_order)}
 <p id="pQuantityAvailable"  {if $product->quantity <= 0} style="display:none;"{/if} >
  <span id="quantityAvailable">{$product->quantity|intval}</span>
  <span {if $product->quantity > 1} style="display:none;"{/if} id="quantityAvailableTxt">{l s='item in stock'}</span>
  <span {if $product->quantity == 1} style="display:none;"{/if} id="quantityAvailableTxtMultiple">{l s='items in stock'}</span>
 </p>
 {/if}
{* last quantities *}
 <p id="last_quantities"{if ($product->quantity > $last_qties OR $product->quantity <= 0) OR $allow_oosp OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display:none;"{/if} >{l s='Warning: Last items in stock!'}</p>
{* product reference *}
 <p id="product_reference" {if isset($groups) OR !$product->reference}style="display:none;"{/if}><label for="product_reference">{l s='Reference :'} </label><span class="editable">{$product->reference|escape:'htmlall':'UTF-8'}</span></p>
{* availability *}
 <p id="availability_statut"{if ($product->quantity <= 0 && !$product->available_later && $allow_oosp) OR ($product->quantity > 0 && !$product->available_now) OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display:none;"{/if}>
  <span id="availability_label">{l s='Availability:'}</span>
  <span id="availability_value"{if $product->quantity <= 0} class="warning_inline"{/if}>
   {if $product->quantity <= 0}{if $allow_oosp}{$product->available_later}{else}{l s='This product is no longer in stock'}{/if}{else}{$product->available_now}{/if}
  </span>
 </p>
</div>
{*close if for show price*}
  {/if}
  <div id="attributes">
{* ON SALE *}
{if $product->on_sale}<span class="on_sale">{l s='On sale!'}</span>{elseif $product->specificPrice AND $product->specificPrice.reduction AND $productPriceWithoutRedution > $productPrice}<span class="discount">{l s='Reduced price!'}</span>{/if}
<div class="clearblock"></div>
{* attributes *}
{if isset($groups)}
{foreach from=$groups key=id_attribute_group item=group}
{if $group.attributes|@count}
<p>
 {assign var="groupName" value="group_$id_attribute_group"}
 <select name="{$groupName}" id="group_{$id_attribute_group|intval}" onchange="javascript:findCombination();{if $colors|@count > 0}$('#wrapResetImages').show('slow');{/if};">
  {foreach from=$group.attributes key=id_attribute item=group_attribute}
   <option value="{$id_attribute|intval}"{if (isset($smarty.get.$groupName) && $smarty.get.$groupName|intval == $id_attribute) || $group.default == $id_attribute} selected="selected"{/if} title="{$group_attribute|escape:'htmlall':'UTF-8'}">{$group_attribute|escape:'htmlall':'UTF-8'}</option>
  {/foreach}
 </select>
 <label for="group_{$id_attribute_group|intval}">{$group.name|escape:'htmlall':'UTF-8'}:</label>
</p>
{/if}
{/foreach}
{/if}
  </div>
<div class="clearblock"></div>
</div>

{* short descriptions *}
 {if $product->description_short}
 <div id="short_description_block" class="bordercolor" style="display:none;">
  {if $product->description_short}
<div id="short_description_content" class="rte align_justify">{$product->description_short}</div>
  {/if}
  {if $product->description}
  <p class="buttons_bottom_block"><a href="javascript:{ldelim}{rdelim}" class="button">{l s='More details'}</a></p>
  {/if}
 </div>
 {/if}
{* pack content *}
 {if $packItems|@count > 0}
 <div class="pack_content bordercolor bgcolor">
  <h3>{l s='Pack content'}</h3>
  <ul>
  {foreach from=$packItems item=packItem}
<li>
 {$packItem.pack_quantity} x <a href="{$link->getProductLink($packItem.id_product, $packItem.link_rewrite, $packItem.category)}">{$packItem.name|escape:'htmlall':'UTF-8'}</a>
 <p>{$packItem.description_short|truncate:100:'...'}</p>
</li>
  {/foreach}
  </ul>
 </div>
 {/if}
{* Out of stock hook *}
 {if !$allow_oosp}
 <p id="oosHook"{if $product->quantity > 0} style="display: none;"{/if}>{$HOOK_PRODUCT_OOS}</p>
 {/if}
{* colors *}
 {if isset($colors) && $colors}
 <div id="color_picker" class="bgcolor bordercolor">
  <h3>{l s='Pick a color:' js=1}</h3>
  <ul id="color_to_pick_list">
  {foreach from=$colors key='id_attribute' item='color'}
<li><a id="color_{$id_attribute|intval}" class="color_pick" style="background:{$color.value};" onclick="updateColorSelect({$id_attribute|intval});$('#wrapResetImages').show('slow');" title="{$color.name}">{if file_exists($col_img_dir|cat:$id_attribute|cat:'.jpg')}<img src="{$img_col_dir}{$id_attribute}.jpg" alt="{$color.name}" width="20" height="20" />{/if}</a></li>
  {/foreach}
  </ul>
 </div>
 {/if}
 {if isset($HOOK_PRODUCT_ACTIONS) && $HOOK_PRODUCT_ACTIONS}{$HOOK_PRODUCT_ACTIONS}{/if}
 <div class="clearblock"></div>
 </form>
 {/if}
<!-- Rhapsody moved customizable fields in this section -->

<!-- Customizable products -->
{if $product->customizable}
<ul class="idTabs">
 <li><a style="cursor: pointer">{l s='Product customization'}</a></li>
</ul>
<div class="customization_block">
{* Rhapsody comment out this section
 <form method="post" action="{$customizationFormTarget}" enctype="multipart/form-data" id="customizationForm">
  <p>
<img src="{$img_dir}icon/infos.gif" alt="Informations" />
{l s='After saving your customized product, remember to add it to your cart.'}
{if $product->uploadable_files}<br />{l s='Allowed file formats are: GIF, JPG, PNG'}{/if}
  </p>
Rhapsody Commented out  *}
  {if $product->uploadable_files|intval}
  <h2>{l s='Pictures'}</h2>
  <ul id="uploadable_files">
{counter start=0 assign='customizationField'}
{foreach from=$customizationFields item='field' name='customizationFields'}
 {if $field.type == 0}
  <li class="customizationUploadLine{if $field.required} required{/if}">{assign var='key' value='pictures_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field}
   {if isset($pictures.$key)}<div class="customizationUploadBrowse">
	 <img src="{$pic_dir}{$pictures.$key}_small" alt="" />
	 <a href="{$link->getProductDeletePictureLink($product, $field.id_customization_field)}" title="{l s='Delete'}" >
	  <img src="{$img_dir}icon/delete.gif" alt="{l s='Delete'}" class="customization_delete_icon" width="11" height="13" />
	 </a>
	</div>{/if}
   <div class="customizationUploadBrowse"><input type="file" name="file{$field.id_customization_field}" id="img{$customizationField}" class="customization_block_input {if isset($pictures.$key)}filled{/if}" />{if $field.required}<sup>*</sup>{/if}
   <div class="customizationUploadBrowseDescription">{if !empty($field.name)}{$field.name}{else}{l s='Please select an image file from your hard drive'}{/if}</div></div>
  </li>
  {counter}
 {/if}
{/foreach}
  </ul>
  {/if}
  <div class="clear"></div>
  {if $product->text_fields|intval}
  <h2>{l s='Texts'}</h2>
  <ul id="text_fields">
{counter start=0 assign='customizationField'}
{foreach from=$customizationFields item='field' name='customizationFields'}
 {if $field.type == 1}
  <li class="customizationUploadLine{if $field.required} required{/if}">{assign var='key' value='textFields_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field}
   {if !empty($field.name)}{$field.name}{/if}{if $field.required}<sup>*</sup>{/if}<textarea type="text" name="textField{$field.id_customization_field}" id="textField{$customizationField}" rows="1" cols="40" class="customization_block_input" />{if isset($textFields.$key)}{$textFields.$key|stripslashes}{/if}</textarea>
  </li>
  {counter}
 {/if}
{/foreach}
  </ul>
  {/if}
  <p style="clear: left;" id="customizedDatas">
<input type="hidden" name="ipa_customization" id="ipa_customization" value="{$ipa_customization}" />
<input type="hidden" name="quantityBackup" id="quantityBackup" value="" />
<input type="hidden" name="submitCustomizedDatas" value="1" />
 <p class="clear required"><sup>*</sup> {l s='required fields'}</p>

{* Rhapsody hid save button in next line
<input type="button" class="button" value="{l s='Save'}" onclick="javascript:saveCustomization()" />
* * * * end of comment *}
<span id="ajax-loader" style="display:none"><img src="{$img_ps_dir}loader.gif" alt="loader" /></span>
  </p>
 </form>
</div>
{/if}
{* Rhapsody moved customization block above  *}

  </form>
{* Rhapsody moved customization block above - need to capture the /form also *}
 {if $HOOK_EXTRA_RIGHT}{$HOOK_EXTRA_RIGHT}{/if}
</div>
</div>
{* quantity discount *}
{if $quantity_discounts}
<div id="quantityDiscount" class="bgcolor bordercolor">
 <h3>{l s='Quantity discount'}</h3>
 <table>
  <tr>
{foreach from=$quantity_discounts item='quantity_discount' name='quantity_discounts'}
 <th class="bordercolor">{$quantity_discount.quantity|intval}
 {if $quantity_discount.quantity|intval > 1}
  {l s='quantities'}
 {else}
  {l s='quantity'}
 {/if}
 </th>
{/foreach}
  </tr>
  <tr>
{foreach from=$quantity_discounts item='quantity_discount' name='quantity_discounts'}
 <td>
 {if $quantity_discount.price != 0 OR $quantity_discount.reduction_type == 'amount'}
  -{convertPrice price=$quantity_discount.real_value|floatval}
 {else}
  -{$quantity_discount.real_value|floatval}%
 {/if}
 </td>
{/foreach}
  </tr>
 </table>
</div>
{/if}
{* description and features *}
{if $product->description || $features || $accessories || $HOOK_PRODUCT_TAB || $attachments}
<div id="more_info_block" class="clear">
 <ul id="more_info_tabs" class="idTabs idTabsShort">
  {if $product->description}<li><a id="more_info_tab_more_info" href="#idTab1">{l s='More info'}</a></li>{/if}
  {if $features}<li><a id="more_info_tab_data_sheet" href="#idTab2">{l s='Data sheet'}</a></li>{/if}
  {if $attachments}<li><a id="more_info_tab_attachments" href="#idTab9">{l s='Download'}</a></li>{/if}
  {if isset($accessories) AND $accessories}<li><a href="#idTab4">{l s='Accessories'}</a></li>{/if}
  {$HOOK_PRODUCT_TAB}
 </ul>
 <div id="more_info_sheets" class="bgcolor bordercolor">
 {if $product->description}
{* full description *}
  <div id="idTab1"><div>{$product->description}</div></div>
 {/if}
 {if $features}
{* product's features *}
  <ul id="idTab2" class="bullet">
  {foreach from=$features item=feature}
<li><span>{$feature.name|escape:'htmlall':'UTF-8'}</span> {$feature.value|escape:'htmlall':'UTF-8'}</li>
  {/foreach}
  </ul>
 {/if}
 {if $attachments}
{* product's attachments *}
  <ul id="idTab9" class="bullet">
  {foreach from=$attachments item=attachment}
<li><a href="{$link->getPageLink('attachment.php', true)}?id_attachment={$attachment.id_attachment}">{$attachment.name|escape:'htmlall':'UTF-8'}</a><br />{$attachment.description|escape:'htmlall':'UTF-8'}</li>
  {/foreach}
  </ul>
 {/if}
 {if isset($accessories) AND $accessories}
{* accessories *}
  <ul id="idTab4">
{foreach from=$accessories item=accessory name=accessories_list}
{assign var='accessoryLink' value=$link->getProductLink($accessory.id_product, $accessory.link_rewrite, $accessory.category)}
<li class="bordercolor ajax_block_product {if $smarty.foreach.accessories_list.first}first_item{elseif $smarty.foreach.accessories_list.last}last_item{else}item{/if} product_accessories_description">
 <div class="accessories_desc">
  <a class="accessory_image product_img_link bordercolor" href="{$accessoryLink|escape:'htmlall':'UTF-8'}" title="{$accessory.legend|escape:'htmlall':'UTF-8'}"><img src="{$link->getImageLink($accessory.link_rewrite, $accessory.id_image, 'medium')}" alt="{$accessory.legend|escape:'htmlall':'UTF-8'}" /></a>
  <h5><a class="product_link" href="{$accessoryLink|escape:'htmlall':'UTF-8'}">{$accessory.name|truncate:22:'...':true|escape:'htmlall':'UTF-8'}</a></h5>
  <a class="product_descr" href="{$accessoryLink|escape:'htmlall':'UTF-8'}" title="{l s='More'}">{$accessory.description_short|strip_tags|truncate:70:'...'}</a>
 </div>
 <div class="accessories_price bordercolor">
  {if $accessory.show_price AND !isset($restricted_country_mode) AND !$PS_CATALOG_MODE}<span class="price">{if $priceDisplay != 1}{displayWtPrice p=$accessory.price}{else}{displayWtPrice p=$accessory.price_tax_exc}{/if}</span>{/if}
  {if ($accessory.allow_oosp || $accessory.quantity > 0) AND $accessory.available_for_order AND !isset($restricted_country_mode) AND !$PS_CATALOG_MODE}
   <a class="exclusive button ajax_add_to_cart_button" href="{$link->getPageLink('cart.php')}?qty=1&id_product={$accessory.id_product|intval}&token={$static_token}&add" rel="ajax_id_product_{$accessory.id_product|intval}" title="{l s='Add to cart'}">{l s='Add to cart'}</a>
  {else}
   <span class="exclusive">{l s='Add to cart'}</span>
  {/if}
 </div>
</li>
{/foreach}
  </ul>
 {/if}
 {$HOOK_PRODUCT_TAB_CONTENT}
 </div>
</div>
{/if}
{$HOOK_PRODUCT_FOOTER}
{* pack items list *}
{if $packItems|@count > 0}
 <div id="pack_product_list">
  <h2>{l s='Pack content'}</h2>
  {include file="$tpl_dir./product-list-pack.tpl" products=$packItems}
 </div>
{/if}
{/if}

 

The template Is built for 1.4.8, but I use it with 1.4.9. Everything else is working so...

Edited by adameriksson (see edit history)
Link to comment
Share on other sites

I have confirmed the problem is with your product.tpl file when I try it with a stock ps theme on one of my 1.4.9.0 test installations. With your file I get the message.

 

There is 1 error :

  1. Please fill in all required fields, then save the customization.

Try using the product.tpl file I modified from the old template in your theme and see if it works, then go from there for any other mods.

 

A good tool to use to compare the files and make the changes is called WinMerge.

Link to comment
Share on other sites

I have confirmed the problem is with your product.tpl file when I try it with a stock ps theme on one of my 1.4.9.0 test installations. With your file I get the message.

 

There is 1 error :

  1. Please fill in all required fields, then save the customization.

Try using the product.tpl file I modified from the old template in your theme and see if it works, then go from there for any other mods.

 

A good tool to use to compare the files and make the changes is called WinMerge.

 

Okey, Thanks for your help! The sad thing is when i Use your code, everyting looks weird, I dont even see a add to cart button..

 

Well, I think I'm stuck with the save button then, If I'm not able to modify your tpl file to have it look like my themes tpl

Link to comment
Share on other sites

No problem. Seriously - create another theme folder and make changes to the stock PS theme which should be as easy as copying the product.tpl file that I posted. Once that works, use WinMerge to compare those files with your theme and that should help you find where / why there are differences.

Link to comment
Share on other sites

No problem. Seriously - create another theme folder and make changes to the stock PS theme which should be as easy as copying the product.tpl file that I posted. Once that works, use WinMerge to compare those files with your theme and that should help you find where / why there are differences.

 

That's a good idea.

 

I just duplicated standard theme, overvrited the product.tpl file with yours. I have the modified controller file.

 

But it doesnt work anyway, the text isn't in the cart. Maybe it is something with my templatemonster modules...

Link to comment
Share on other sites

does Template Monster modify the blockcart module?

 

Yeah The do, they have a modified ajax-cart.js. But I dont use their file yet. I don't know what it does.

 

Do you think it would work better if I use it?

 

I see now that I also have "blockcart-json.tpl" and "blockcart.tpl" in my themes/modules folder. So templatemonster have modified the cart module...

 

I did a comparison, looks like they only have customized it for design purpose, they have not changed core functions

Edited by adameriksson (see edit history)
Link to comment
Share on other sites

Yeah The do, they have a modified ajax-cart.js. But I dont use their file yet. I don't know what it does. Do you think it would work better if I use it? I see now that I also have "blockcart-json.tpl" and "blockcart.tpl" in my themes/modules folder. So templatemonster have modified the cart module... I did a comparison, looks like they only have customized it for design purpose, they have not changed core functions

I moved some code around in your monster template file and got it to work, but am not sure if it formats correctly since I don't have your entire theme. Try the attached file and unzip it to product.tpl

product.zip

Link to comment
Share on other sites

I moved some code around in your monster template file and got it to work, but am not sure if it formats correctly since I don't have your entire theme. Try the attached file and unzip it to product.tpl

 

IT WORKS!!!!!!

 

Thank you so much, you are the best! May I ask you what U think was the problem in the code? Was it the position of some code, or did you modify something else?

 

Thank so much, I'm so glad!

Link to comment
Share on other sites

  • 1 month later...

Hi everybody,

Thanks for this solution, works perfectly.

I would like it to work well with file fields, you can help me?

Regards

edit:

I use the Prestashop version 1.4.9, with the Prestashop_new theme.

And I've gotten it to work with ajax cart, deleting the code between "//for every 'add' buttons..." and "//for 'delete' buttons in the cart block.." in the ajax-cart.js theme's file.

Edited by franmille (see edit history)
Link to comment
Share on other sites

when I do all the said, the customization is saved but the attributes aren't.

 

when the line

 

<input type="hidden" name="submitCustomizedDatas" value="1" />

 

is in the product.tpl, the customization is saved but the attributes arent. if it is not, the attributes are saved but the customizations arent.

 

I'm on ps 1.4.8.2

 

pulling my hair here...

Edited by cagrie (see edit history)
Link to comment
Share on other sites

  • 1 month later...

Figured out a way to do it granted it's not the correct way and I'm on too short of a deadline to make it clean. Also, only for text fields. I didn't need image upload so I didnt even try with that.

 

See attached. Tested on 1.5.2. Put the file in /overrides/controllers/front/

 

Requires .tpl modifcation that is fairly straightforward: Remove the save button and put the following code in the form which submits to the cart:

{if $product->text_fields|intval}
   {counter start=0 assign='customizationField'}
   {foreach from=$customizationFields item='field' name='customizationFields'}
       {if $field.type == 1}
           <label for ="textField{$customizationField}">{assign var='key' value='textFields_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field} {if !empty($field.name)}{$field.name}{/if}{if $field.required}<sup>*</sup>{/if}</label>
           <textarea type="text" name="textField{$field.id_customization_field}" id="textField{$customizationField}" rows="1" cols="40" class="customization_block_input" />{if isset($textFields.$key)}{$textFields.$key|stripslashes}{/if}</textarea>
           {counter}
       {/if}
   {/foreach}
{/if}
<input type="hidden" name="quantityBackup" id="quantityBackup" value="" />
<input type="hidden" name="submitCustomizedDatas" value="1" />

 

Of course all you really need are the inputs. The code is stolen from the other customization area on the page and minified a little. Nothing changed. Be sure to remove the customization form as well.

CartController.php

  • Like 1
Link to comment
Share on other sites

Figured out a way to do it granted it's not the correct way and I'm on too short of a deadline to make it clean. Also, only for text fields. I didn't need image upload so I didnt even try with that.

 

See attached. Tested on 1.5.2. Put the file in /overrides/controllers/front/

 

Requires .tpl modifcation that is fairly straightforward: Remove the save button and put the following code in the form which submits to the cart:

{if $product->text_fields|intval}
{counter start=0 assign='customizationField'}
{foreach from=$customizationFields item='field' name='customizationFields'}
	{if $field.type == 1}
		<label for ="textField{$customizationField}">{assign var='key' value='textFields_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field} {if !empty($field.name)}{$field.name}{/if}{if $field.required}<sup>*</sup>{/if}</label>
		<textarea type="text" name="textField{$field.id_customization_field}" id="textField{$customizationField}" rows="1" cols="40" class="customization_block_input" />{if isset($textFields.$key)}{$textFields.$key|stripslashes}{/if}</textarea>
		{counter}
	{/if}
{/foreach}
{/if}
<input type="hidden" name="quantityBackup" id="quantityBackup" value="" />
<input type="hidden" name="submitCustomizedDatas" value="1" />

 

Of course all you really need are the inputs. The code is stolen from the other customization area on the page and minified a little. Nothing changed. Be sure to remove the customization form as well.

 

I tried on my PS 1.5.2 but no luck.

Can you help me out, did you change some else as well or just change the CartController.php file. I mean did you make changes ajax-cart.js too.

 

Regards,

Naeem

Link to comment
Share on other sites

This worked great on 1.5.3.1

 

How do I make it compatible with ajax cart?

 

Figured out a way to do it granted it's not the correct way and I'm on too short of a deadline to make it clean. Also, only for text fields. I didn't need image upload so I didnt even try with that.

 

See attached. Tested on 1.5.2. Put the file in /overrides/controllers/front/

 

Requires .tpl modifcation that is fairly straightforward: Remove the save button and put the following code in the form which submits to the cart:

{if $product->text_fields|intval}
{counter start=0 assign='customizationField'}
{foreach from=$customizationFields item='field' name='customizationFields'}
	{if $field.type == 1}
		<label for ="textField{$customizationField}">{assign var='key' value='textFields_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field} {if !empty($field.name)}{$field.name}{/if}{if $field.required}<sup>*</sup>{/if}</label>
		<textarea type="text" name="textField{$field.id_customization_field}" id="textField{$customizationField}" rows="1" cols="40" class="customization_block_input" />{if isset($textFields.$key)}{$textFields.$key|stripslashes}{/if}</textarea>
		{counter}
	{/if}
{/foreach}
{/if}
<input type="hidden" name="quantityBackup" id="quantityBackup" value="" />
<input type="hidden" name="submitCustomizedDatas" value="1" />

 

Of course all you really need are the inputs. The code is stolen from the other customization area on the page and minified a little. Nothing changed. Be sure to remove the customization form as well.

Link to comment
Share on other sites

  • 4 weeks later...
  • 3 weeks later...
  • 2 weeks later...

Hi Everyone,

 

Sorry, had to edit my post. I think I have it working using shamun's CartController.php in Prestashop 1.5.2 with the default theme.

 

I moved the entire <!-- Customizable products --> content to where the add to cart button is. Removed the Save button and added onclick="javascript:saveCustomization()" to the add to cart input button.

 

It works and just need some CSS adjustments. But, I'm not quite sure if it won't affect other modules or features. Anyway, I achieved my goal in removing the save button and make sure the input data will display after clicking the add to cart button.

 

Thank you all! To Rhapsody and shamun, very useful post :)

Edited by dOnkSkie (see edit history)
Link to comment
Share on other sites

Working 1.5.3.1 Mod to remove save button! (without Ajax Cart)

 

The Zip file attached includes what is needed to modify the basic "default" theme on Prestashop 1.5.3.1 to eliminate the save button so you can add to cart directly. Thanks to shamun who got this to work on version 1.5.2 in post #124 above, the CartController.php override file has been updated with 1.5.3.1 code.

 

1. Put the CartController.php file in the override/controllers/front directory

2. Put the product.tpl file in your default theme directory (or the theme directory you created from the default theme).

3. In the BO under modules, set the Cart block configuration to deactivate the Ajax cart

4. In the BO on the Advnaced Parameters menu, select performance, Turn off the smarty cache and compile templates, then try it in the front office. It should work. Then reenable the smarty cache and turn compile off in the BO.

 

If anyone is able to accomplish the following that is NOT incorporated in this mod, please post in this thread:

1. update to include uploading of files & images

2. Get the Ajax cart working with this mod

1.5.3.1 Mod to eliminate svae button.zip

  • Like 3
Link to comment
Share on other sites

Hello Rhapsody, thanks for your time. It seems to be working but I have a problem:

 

With the new files (product.tpl and CartController.php in the override), the button to remove products in the cart redirect to the homepage and the product isn't removed from the cart.

 

I'm using prestashop 1.5 and the theme "Free Template PS001" from http://www.uhupage.com/

 

where could it be the problem? any idea about solving this?

 

Thanks.

Link to comment
Share on other sites

  • 2 weeks later...

hey, many thanks to all the contributors, was really stuck on this one ...

i managed to extend rhapsodys working 1.5 mod to also work with files, was actually pretty simple.

Just add the following in overrides/controllers/front/CartCOntroller.php

$this->pictureUpload($product);

below

$this->textRecord($product);

and add the slightly modified pictureUpload function from the productscontroller

protected function pictureUpload($product)
{
 if (!$field_ids = $product->getCustomizationFieldIds())
  return false;
 $authorized_file_fields = array();
 foreach ($field_ids as $field_id)
  if ($field_id['type'] == Product::CUSTOMIZE_FILE)
   $authorized_file_fields[(int)$field_id['id_customization_field']] = 'file'.(int)$field_id['id_customization_field'];
 $indexes = array_flip($authorized_file_fields);
 foreach ($_FILES as $field_name => $file)
  if (in_array($field_name, $authorized_file_fields) && isset($file['tmp_name']) && !empty($file['tmp_name']))
  {
   $file_name = md5(uniqid(rand(), true));
   if ($error = ImageManager::validateUpload($file, (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE')))
 $this->errors[] = $error;
   $product_picture_width = (int)Configuration::get('PS_PRODUCT_PICTURE_WIDTH');
   $product_picture_height = (int)Configuration::get('PS_PRODUCT_PICTURE_HEIGHT');
   $tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS');
   if ($error || (!$tmp_name || !move_uploaded_file($file['tmp_name'], $tmp_name)))
 return false;
   /* Original file */
   if (!ImageManager::resize($tmp_name, _PS_UPLOAD_DIR_.$file_name))
 $this->errors[] = Tools::displayError('An error occurred during the image upload process.');
   /* A smaller one */
   elseif (!ImageManager::resize($tmp_name, _PS_UPLOAD_DIR_.$file_name.'_small', $product_picture_width, $product_picture_height))
 $this->errors[] = Tools::displayError('An error occurred during the image upload process.');
   elseif (!chmod(_PS_UPLOAD_DIR_.$file_name, 0777) || !chmod(_PS_UPLOAD_DIR_.$file_name.'_small', 0777))
 $this->errors[] = Tools::displayError('An error occurred during the image upload process.');
   else
 $this->context->cart->addPictureToProduct($product->id, $indexes[$field_name], Product::CUSTOMIZE_FILE, $file_name);
   unlink($tmp_name);
  }
 return true;
}

 

then all you have to do id add

enctype="multipart/form-data"

to the add-to-cart form in product.tpl

 

Pretty easy to figure out, still hope it helps someone maybe.

 

Am still trying to get this to work with the ajax-cart, no luck so far.

Link to comment
Share on other sites

oh, right i should've been more specific. The enctype snippet needs to be in the "buy-block" form so:

 

<form id="buy_block" {if $PS_CATALOG_MODE AND !isset($groups) AND $product->quantity > 0}class="hidden"{/if} action="{$link->getPageLink('cart')}" method="post"  enctype="multipart/form-data">

 

let me know if this works :)

Link to comment
Share on other sites

  • 1 month later...

@huduydesign : I guess you figured it out? When i enter customizations, they are being saved to the cart. Or do you want to move the customizations out of the tab region? To achieve that you need to keep the form itself intact and move it around as a whole. You can switch around the individual parts to your liking but you need to keep all inputs and the submit (add to cart in this case) in the form.

Link to comment
Share on other sites

Defuzed I did finally get it to work but not using Rhapsody's method but one in post #132. Rhapsody's method I could not find right combinations to make it work so resorted to using the "save" function in the add to cart function, ajax off & the one cart file from Rhapsody's download is in there, not sure it's doing anything. This is same set up I used earlier but stopped it stopped working, possibly because I had ajax on or something went wacko when moving to VPS hosting. Hoping it continues to work.

Link to comment
Share on other sites

  • 3 weeks later...
  • 2 weeks later...

aaronjpitts, have you tried using rhapsody's code in 1.5.4.1? I'm using my modified version (with file-upload) and i didn't have to change anything when upgrading to 1.5.4.1 ( i don't think that update changed anything in the relevant files).

Link to comment
Share on other sites

yes friends try this...

 

add : function(idProduct, idCombination,addedFromProductPage, callerElement, quantity, whishlist){
if (addedFromProductPage)
       {
           $('#add_to_cart input').attr('disabled', true).removeClass('exclusive').addClass('exclusive_disabled');
           $('.filled').removeClass('filled');
       }
       else
           $(callerElement).attr('disabled', true);

       if ($('#cart_block_list').hasClass('collapsed'))
           this.expand();
       var formData = $('#customizationForm').serialize();

               $.ajax({
               url: $('#customizationForm').attr('action'),
               type: 'POST',
               data: formData,
               async: false,
                success: function (data) {
                    $.ajax({
                           type: 'POST',
                           url: baseUri,
                           async: true,
                           cache: false,
                           dataType : "json",
                           data: 'controller=cart&add=1&ajax=true&qty=' + ((quantity && quantity != null) ? quantity : '1') + '&id_product=' + idProduct + '&token=' + static_token + ( (parseInt(idCombination) && idCombination != null) ? '&ipa=' + parseInt(idCombination): ''),
                           success: function(jsonData,textStatus,jqXHR)
                           {
                               // add appliance to whishlist module
                               if (whishlist && !jsonData.errors)
                                   WishlistAddProductCart(whishlist[0], idProduct, idCombination, whishlist[1]);

                               // add the picture to the cart
                               var $element = $(callerElement).parent().parent().find('a.product_image img,a.product_img_link img');
                               if (!$element.length)
                                   $element = $('#bigpic');
                               var $picture = $element.clone();
                               var pictureOffsetOriginal = $element.offset();

                               if ($picture.size())
                                   $picture.css({'position': 'absolute', 'top': pictureOffsetOriginal.top, 'left': pictureOffsetOriginal.left});

                               var pictureOffset = $picture.offset();
                               if ($('#cart_block').offset().top && $('#cart_block').offset().left)
                                   var cartBlockOffset = $('#cart_block').offset();
                               else
                                   var cartBlockOffset = $('#shopping_cart').offset();

                               // Check if the block cart is activated for the animation
                               if (cartBlockOffset != undefined && $picture.size())
                               {
                                   $picture.appendTo('body');
                                   $picture.css({ 'position': 'absolute', 'top': $picture.css('top'), 'left': $picture.css('left'), 'z-index': 4242 })
                                   .animate({ 'width': $element.attr('width')*0.66, 'height': $element.attr('height')*0.66, 'opacity': 0.2, 'top': cartBlockOffset.top + 30, 'left': cartBlockOffset.left + 15 }, 1000)
                                   .fadeOut(100, function() {
                                       ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
                                   });
                               }
                               else
                                   ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
                           },
                           error: function(XMLHttpRequest, textStatus, errorThrown)
                           {
                               alert("Impossible to add the product to the cart.\n\ntextStatus: '" + textStatus + "'\nerrorThrown: '" + errorThrown + "'\nresponseText:\n" + XMLHttpRequest.responseText);
                               //reactive the button when adding has finished
                               if (addedFromProductPage)
                                   $('#add_to_cart input').removeAttr('disabled').addClass('exclusive').removeClass('exclusive_disabled');
                               else
                                   $(callerElement).removeAttr('disabled');
                           }
                       });
	        }
    });

it is work for me..

  • Like 5
Link to comment
Share on other sites

sorry ...

modules/blockcart/ajax-cart.js file

 

find the this

add : function(idProduct, idCombination,addedFromProductPage, callerElement, quantity, whishlist)

 

Works perfectly, thanks for sharing saved me tons of banging my head :))

for clarity, before the

remove : function(idProduct, idCombination, customizationId, idAddressDelivery)

starts theres a

},

missing, but thats pretty obvious

Link to comment
Share on other sites

  • 2 weeks later...
  • 4 weeks later...
  • 4 weeks later...
  • 2 weeks later...

Could anyone confirm if they have this modification working with the latest prestashop version (doesn't have to work with ajax cart). I had been using rhapsody's mod before but now with a clean install of prestashop 1.5.5.0 when clicking the add to cart button (with the customisation field inputted) I get an error on the cart page: 

  1. Please fill in all of the required fields, and then save your customizations.

So it's obviously not saving the fields anymore. Can anyone please help with this?

 

Many thanks

Link to comment
Share on other sites

  • 1 month later...
  • 3 months later...

Hey guys,

 

I managed to get it working with P.S 1.5.4.1 and AJAX on.

 

If i'm not wrong, in the original version, the user has to save the customised data first then the adding to the cart will work is because when adding to the cart, the script checks whether there is customised data saved in the MySQL database first ( check for id_customization and its data).

 

In the product page, the customised datas are sent to the ProductController's textRecord() and pictureUpload() function to process and to update the database, this is sent using the form id called customizationForm. 

 

The add to cart button originally interacts with the CartController and not the ProductController and is separated from the customizationForm's form. Even when you add textRecord() function in the CartController, the values in the customised fields are not recorded as the $_POST values for both CartController and ProductController are different.

 

Basically the solution is like this, I first submit the customised field values with the help of AJAX and then call another AJAX query to add the product to the cart when the customised field values have been updated in the database already. For the text validation, I used jQuery to check for empty textfields instead.

 

The code is here, just edit the file modules\blockcart\ajax-cart.js and the method add : function around line 177 with this, remember to backup your original copy in case.

// add a product in the cart via ajax
	add : function(idProduct, idCombination, addedFromProductPage, callerElement, quantity, whishlist){
		var addBtn_val = $('#add_to_cart input').val();
		if (addedFromProductPage)
		{
			//button change, disable and do status text
			$('#add_to_cart input').attr('disabled', true).removeClass('exclusive').addClass('exclusive_disabled').val("Processing...");
			$('.filled').removeClass('filled');
			//not depending on php backend to do validation but jquery
			$("form#customizationForm .required :input").each(function()
			{
				if ($.trim($(this).val()).length == 0) {
					$(this).css("border", "red 1px solid");
					$form_verify = false;
					
					$('#add_to_cart input').val(addBtn_val).removeAttr('disabled').addClass('exclusive').removeClass('exclusive_disabled');
					
				}
				else
				{
					$(this).removeAttr("style");
					$(this).css("height", "30px");
					$form_verify = true;
				}
			});
			if($form_verify)
			{
				var cform = $("form#customizationForm");
				var cform_data = cform.serialize();
				var cform_action = cform.attr("action");
				var cform_method = cform.attr("method");
				var cform_enctype = cform.attr("enctype");
				
				//use ajax send the customizationForm data, will still be successful even though there is error on PHP side.
				$.ajax({
					type: cform_method,
					headers: { "cache-control": "no-cache" },
					url: cform_action,
					cache: false,
					data: cform_data,
					success: function(response)
					{
						//when customizationForm is successfully submitted, proceed to adding product to cart
						emptyCustomizations();
						// adding product now
						$.ajax({
							type: 'POST',
							headers: { "cache-control": "no-cache" },
							url: baseUri + '?rand=' + new Date().getTime(),
							async: true,
							cache: false,
							dataType : "json",
							data: 'controller=cart&add=1&ajax=true&qty=' + ((quantity && quantity != null) ? quantity : '1') + '&id_product=' + idProduct + '&token=' + static_token + ( (parseInt(idCombination) && idCombination != null) ? '&ipa=' + parseInt(idCombination): ''),
							success: function(jsonData,textStatus,jqXHR)
							{
								// add appliance to whishlist module
								if (whishlist && !jsonData.errors)
									WishlistAddProductCart(whishlist[0], idProduct, idCombination, whishlist[1]);

								// add the picture to the cart
								var $element = $(callerElement).parent().parent().find('a.product_image img,a.product_img_link img');
								if (!$element.length)
									$element = $('#bigpic');
								var $picture = $element.clone();
								var pictureOffsetOriginal = $element.offset();

								if ($picture.size())
									$picture.css({'position': 'absolute', 'top': pictureOffsetOriginal.top, 'left': pictureOffsetOriginal.left});

								var pictureOffset = $picture.offset();
								if ($('#cart_block')[0] && $('#cart_block').offset().top && $('#cart_block').offset().left)
									var cartBlockOffset = $('#cart_block').offset();
								else
									var cartBlockOffset = $('#shopping_cart').offset();

								// Check if the block cart is activated for the animation
								if (cartBlockOffset != undefined && $picture.size())
								{
									$picture.appendTo('body');
									$picture.css({ 'position': 'absolute', 'top': $picture.css('top'), 'left': $picture.css('left'), 'z-index': 4242 })
									.animate({ 'width': $element.attr('width')*0.66, 'height': $element.attr('height')*0.66, 'opacity': 0.2, 'top': cartBlockOffset.top + 30, 'left': cartBlockOffset.left + 705 }, 1000)
									.fadeOut(100, function() {
										ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
									});
								}
								else
									ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
								$('#add_to_cart input').val("Successfully Added!").css("background-color","#74bd00").delay(2000).queue(function(){
									$(this).val(addBtn_val).css("background-color","black");
								});
							},
							error: function(XMLHttpRequest, textStatus, errorThrown)
							{
								alert("Impossible to add the product to the cart.\n\ntextStatus: '" + textStatus + "'\nerrorThrown: '" + errorThrown + "'\nresponseText:\n" + XMLHttpRequest.responseText);
								//reactive the button when adding has finished
								if (addedFromProductPage)
									$('#add_to_cart input').removeAttr('disabled').addClass('exclusive').removeClass('exclusive_disabled');
								else
									$(callerElement).removeAttr('disabled');
							}
						});
					},
					error: function(response)
					{
						alert("error: " + response.error);
					}
				});
			}
			else 
			{
				alert("Please fill in the required fields");
			}
			
		}
		else
		{
			$(callerElement).attr('disabled', true);
		}
		
		if ($('#cart_block_list').hasClass('collapsed'))
			this.expand();
		
	},

Here is my ajax-cart.js file for reference.

Cheers

ajax-cart.zip

Edited by ZenVisuals (see edit history)
Link to comment
Share on other sites

Hey guys,

 

I managed to get it working with P.S 1.5.4.1 and AJAX on.

 

..........

 

Here is my ajax-cart.js file for reference.

Cheers

ZenVisuals,

 

Thanks for that!  I tried it on my test shop using 1.5.6.2 and it works with the default theme.  I have made enough changes on my custom theme that I believe take out all the ajax calls, so it doesn't work there.I plan on going back to the custom theme and restoring that code.

 

Have you checked operation with the mobile theme?  I found there were some things on the default mobile theme that didn't work, so I significantly customized it to meet my needs.

 

Nice work!

Link to comment
Share on other sites

Hey guys,

 

@Rhapsody: Thanks for the feedback! Yeah I didn't bother about the non ajax operation so it didn't work. Good point about the mobile operation, I totally neglected it! I'm glad you updated your codes on the custom theme and got it working :) I was looking at the non ajax operation and figuring out how the CartController works.

 

Anyway, these are my findings:

 

Since the forms for the customised fields and the other inputs such as the quantity and combination are different and they are posted to ProductController and CartController respectively. To have them submit as one, I combined the inputs into one single form and post it to the CartController only. 

 

The CartController then retrieves the $_POST values of all the inputs in the product page including the customised fields. I then override the processChangeProductInCart() method and proceeded with updating the database with the customised fields first then the other inputs. I took codes from the textRecord() in ProductController and changed it to fit the process.

 

It should work without AJAX. However, I didn't update my ajax-cart.js for this so if AJAX is on, I don't think it will work. Perhaps the original ajax-cart.js might work. Another thing is only text-fields and areas will work, the image upload will not work as I never included codes from pictureUpload(). 

 

This code should be placed in override/modules/front/CartController.php

class CartController extends CartControllerCore
{

	/**
	 * This process add or update a product in the cart
	 */
	 
	protected function processChangeProductInCart()
	{
		$mode = (Tools::getIsset('update') && $this->id_product) ? 'update' : 'add';

		if ($this->qty == 0)
			$this->errors[] = Tools::displayError('Null quantity.');
		else if (!$this->id_product)
			$this->errors[] = Tools::displayError('Product not found');

		$product = new Product($this->id_product, true, $this->context->language->id);
		if (!$product->id || !$product->active)
		{
			$this->errors[] = Tools::displayError('This product is no longer available.', false);
			return;
		}

		// Check product quantity availability
		if ($this->id_product_attribute)
		{
			if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $this->qty))
				$this->errors[] = Tools::displayError('There isn\'t enough product in stock.');
		}
		else if ($product->hasAttributes())
		{
			$minimumQuantity = ($product->out_of_stock == 2) ? !Configuration::get('PS_ORDER_OUT_OF_STOCK') : !$product->out_of_stock;
			$this->id_product_attribute = Product::getDefaultAttribute($product->id, $minimumQuantity);
			// @todo do something better than a redirect admin !!
			if (!$this->id_product_attribute)
				Tools::redirectAdmin($this->context->link->getProductLink($product));
			else if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $this->qty))
				$this->errors[] = Tools::displayError('There isn\'t enough product in stock.');
		}
		else if (!$product->checkQty($this->qty))
			$this->errors[] = Tools::displayError('There isn\'t enough product in stock.');

		// If no errors, process product addition
		if (!$this->errors && $mode == 'add')
		{
			// Add cart if no cart found
			if (!$this->context->cart->id)
			{
				if (Context::getContext()->cookie->id_guest)
				{
					$guest = new Guest(Context::getContext()->cookie->id_guest);
					$this->context->cart->mobile_theme = $guest->mobile_theme;
				}
				$this->context->cart->add();
				if ($this->context->cart->id)
					$this->context->cookie->id_cart = (int)$this->context->cart->id;
			}
			// Process customizable fields first
			
			//get product's customized text fields and input them to $field_ids
			if (!$field_ids = $product->getCustomizationFieldIds())
				return false;
				$authorized_text_fields = array();
				$required_fields = $product->getRequiredCustomizableFields();
				$required_fieldsArray = array();
			
			//get required field ids
			foreach ($required_fields as $requiredfield_id)
				if ($requiredfield_id['type'] == Product::CUSTOMIZE_TEXTFIELD)			
					$required_fieldsArray[(int)$requiredfield_id['id_customization_field']] = 'textField'.(int)$requiredfield_id['id_customization_field'];
			
			//$authorized_text_fields[int] = textField[int of id_customization_field];
			foreach ($field_ids as $field_id)
				if ($field_id['type'] == Product::CUSTOMIZE_TEXTFIELD)			
					$authorized_text_fields[(int)$field_id['id_customization_field']] = 'textField'.(int)$field_id['id_customization_field'];
					
			//values 1,2,3,4,5,6,7 put into array[textField1,2,3,4,5,6,7]
			$indexes = array_flip($authorized_text_fields);
			foreach ($_POST as $field_name => $value)
			{
				//filter required fields
				
					if (in_array($field_name, $required_fieldsArray) && empty($value))
					{
						// stop and make sure user enters required fields
						//p(Customization::getLabel($indexes[$field_name],1)) - gets the label of the id_customization_field with id_lang = 1, 1 is English i assume
						$this->errors[] = Tools::displayError('Please fill this field:' . Customization::getLabel($indexes[$field_name],1));
					}
					else
					{
						if (!Validate::isMessage($value))
							$this->errors[] = Tools::displayError('Invalid message');
					}
				
			}
			// if all required fields are filled, then proceed to add custom fields to database
			if (!$this->errors)
			{
				foreach ($_POST as $field_name => $value)
				{
					if (in_array($field_name, $authorized_text_fields))
					{
						$this->context->cart->addTextFieldToProduct($product->id, $indexes[$field_name], Product::CUSTOMIZE_TEXTFIELD, $value);
					}
				}
			}

			if (!$this->errors)
			{
				$cart_rules = $this->context->cart->getCartRules();
				$update_quantity = $this->context->cart->updateQty($this->qty, $this->id_product, $this->id_product_attribute, $this->customization_id, Tools::getValue('op', 'up'), $this->id_address_delivery);
				if ($update_quantity < 0)
				{
					// If product has attribute, minimal quantity is set with minimal quantity of attribute
					$minimal_quantity = ($this->id_product_attribute) ? Attribute::getAttributeMinimalQty($this->id_product_attribute) : $product->minimal_quantity;
					$this->errors[] = sprintf(Tools::displayError('You must add %d minimum quantity', false), $minimal_quantity);
				}
				elseif (!$update_quantity)
					$this->errors[] = Tools::displayError('You already have the maximum quantity available for this product.', false);
				elseif ((int)Tools::getValue('allow_refresh'))
				{
					// If the cart rules has changed, we need to refresh the whole cart
					$cart_rules2 = $this->context->cart->getCartRules();
					if (count($cart_rules2) != count($cart_rules))
						$this->ajax_refresh = true;
					else
					{
						$rule_list = array();
						foreach ($cart_rules2 as $rule)
							$rule_list[] = $rule['id_cart_rule'];
						foreach ($cart_rules as $rule)
							if (!in_array($rule['id_cart_rule'], $rule_list))
							{
								$this->ajax_refresh = true;
								break;
							}
					}
				}
			}
		}

		$removed = CartRule::autoRemoveFromCart();
		CartRule::autoAddToCart();
		if (count($removed) && (int)Tools::getValue('allow_refresh'))
			$this->ajax_refresh = true;
	}
	
}

I combined both forms in product.tpl

<!-- Customizable products combined with standard inputs-->
		{if ($product->show_price AND !isset($restricted_country_mode)) OR isset($groups) OR $product->reference OR (isset($HOOK_PRODUCT_ACTIONS) && $HOOK_PRODUCT_ACTIONS)}
		<!-- add to cart form-->
		<form id="buy_block" {if $PS_CATALOG_MODE AND !isset($groups) AND $product->quantity > 0}class="hidden"{/if} action="{$link->getPageLink('cart')}" method="post" enctype="multipart/form-data">

			<!-- hidden datas -->
			<p class="hidden">
				<input type="hidden" name="token" value="{$static_token}" />
				<input type="hidden" name="id_product" value="{$product->id|intval}" id="product_page_product_id" />
				<input type="hidden" name="add" value="1" />
				<input type="hidden" name="id_product_attribute" id="idCombination" value="" />
			</p>

			<div class="product_attributes">
				{if isset($groups)}
				<!-- attributes -->
				<div id="attributes">
				<div class="clear"></div>
				{foreach from=$groups key=id_attribute_group item=group}
					{if $group.attributes|@count}
						<fieldset class="attribute_fieldset">
							<label class="attribute_label" for="group_{$id_attribute_group|intval}">{$group.name|escape:'htmlall':'UTF-8'} : </label>
							{assign var="groupName" value="group_$id_attribute_group"}
							<div class="attribute_list">
							{if ($group.group_type == 'select')}
								<select name="{$groupName}" id="group_{$id_attribute_group|intval}" class="attribute_select" onchange="findCombination();getProductAttribute();">
									{foreach from=$group.attributes key=id_attribute item=group_attribute}
										<option value="{$id_attribute|intval}"{if (isset($smarty.get.$groupName) && $smarty.get.$groupName|intval == $id_attribute) || $group.default == $id_attribute} selected="selected"{/if} title="{$group_attribute|escape:'htmlall':'UTF-8'}">{$group_attribute|escape:'htmlall':'UTF-8'}</option>
									{/foreach}
								</select>
							{elseif ($group.group_type == 'color')}
								<ul id="color_to_pick_list" class="clearfix">
									{assign var="default_colorpicker" value=""}
									{foreach from=$group.attributes key=id_attribute item=group_attribute}
									<li{if $group.default == $id_attribute} class="selected"{/if}>
										<a id="color_{$id_attribute|intval}" class="color_pick{if ($group.default == $id_attribute)} selected{/if}" style="background: {$colors.$id_attribute.value};" title="{$colors.$id_attribute.name}" onclick="colorPickerClick(this);getProductAttribute();">
											{if file_exists($col_img_dir|cat:$id_attribute|cat:'.jpg')}
												<img src="{$img_col_dir}{$id_attribute}.jpg" alt="{$colors.$id_attribute.name}" width="20" height="20" /><br />
											{/if}
										</a>
									</li>
									{if ($group.default == $id_attribute)}
										{$default_colorpicker = $id_attribute}
									{/if}
									{/foreach}
								</ul>
								<input type="hidden" class="color_pick_hidden" name="{$groupName}" value="{$default_colorpicker}" />
							{elseif ($group.group_type == 'radio')}
								<ul>
									{foreach from=$group.attributes key=id_attribute item=group_attribute}
										<li>
											<input type="radio" class="attribute_radio" name="{$groupName}" value="{$id_attribute}" {if ($group.default == $id_attribute)} checked="checked"{/if} onclick="findCombination();getProductAttribute();" />
											<span>{$group_attribute|escape:'htmlall':'UTF-8'}</span>
										</li>
									{/foreach}
								</ul>
							{/if}
							</div>
						</fieldset>
					{/if}
				{/foreach}
				</div>
			{/if}
			<p id="product_reference" {if isset($groups) OR !$product->reference}style="display: none;"{/if}>
				<label for="product_reference">{l s='Reference:'} </label>
				<span class="editable">{$product->reference|escape:'htmlall':'UTF-8'}</span>
			</p>

			<!-- quantity wanted -->
            {if $product->id == 6}{else}
			<p id="quantity_wanted_p"{if (!$allow_oosp && $product->quantity <= 0) OR $virtual OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none;"{/if}>
				<label>{l s='Quantity:'}</label>
				<input type="text" name="qty" id="quantity_wanted" class="text" value="{if isset($quantityBackup)}{$quantityBackup|intval}{else}{if $product->minimal_quantity > 1}{$product->minimal_quantity}{else}1{/if}{/if}" size="2" maxlength="3" {if $product->minimal_quantity > 1}onkeyup="checkMinimalQuantity({$product->minimal_quantity});"{/if} />
			</p>
{/if}
			<!-- minimal quantity wanted -->
			<p id="minimal_quantity_wanted_p"{if $product->minimal_quantity <= 1 OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none;"{/if}>
				{l s='This product is not sold individually. You must select at least'} <b id="minimal_quantity_label">{$product->minimal_quantity}</b> {l s='quantity for this product.'}
			</p>
			{if $product->minimal_quantity > 1}
			<script type="text/javascript">
				checkMinimalQuantity();
			</script>
			{/if}

			<!-- availability -->
			<p id="availability_statut"{if ($product->quantity <= 0 && !$product->available_later && $allow_oosp) OR ($product->quantity > 0 && !$product->available_now) OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none;"{/if}>
				<span id="availability_label">{l s='Availability:'}</span>
				<span id="availability_value"{if $product->quantity <= 0} class="warning_inline"{/if}>{if $product->quantity <= 0}{if $allow_oosp}{$product->available_later}{else}{l s='This product is no longer in stock'}{/if}{else}{$product->available_now}{/if}</span>				
			</p>
			<p id="availability_date"{if ($product->quantity > 0) OR !$product->available_for_order OR $PS_CATALOG_MODE OR !isset($product->available_date) OR $product->available_date < $smarty.now|date_format:'%Y-%m-%d'} style="display: none;"{/if}>
				<span id="availability_date_label">{l s='Availability date:'}</span>
				<span id="availability_date_value">{dateFormat date=$product->available_date full=false}</span>
			</p>
			<!-- number of item in stock -->
			{if ($display_qties == 1 && !$PS_CATALOG_MODE && $product->available_for_order)}
			<p id="pQuantityAvailable"{if $product->quantity <= 0} style="display: none;"{/if}>
				<span id="quantityAvailable">{$product->quantity|intval}</span>
				<span {if $product->quantity > 1} style="display: none;"{/if} id="quantityAvailableTxt">{l s='Item in stock'}</span>
				<span {if $product->quantity == 1} style="display: none;"{/if} id="quantityAvailableTxtMultiple">{l s='Items in stock'}</span>
			</p>
			{/if}

			<!-- Out of stock hook -->
			<div id="oosHook"{if $product->quantity > 0} style="display: none;"{/if}>
				{$HOOK_PRODUCT_OOS}
			</div>

			<p class="warning_inline" id="last_quantities"{if ($product->quantity > $last_qties OR $product->quantity <= 0) OR $allow_oosp OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none"{/if} >{l s='Warning: Last items in stock!'}</p>
		</div>

		<div class="content_prices clearfix">
			<!-- prices -->
			{if $product->show_price AND !isset($restricted_country_mode) AND !$PS_CATALOG_MODE}

			{if $product->online_only}
			<p class="online_only">{l s='Online only'}</p>
			{/if}

			<div class="price">
				<p class="our_price_display">
				{if $priceDisplay >= 0 && $priceDisplay <= 2}
					<span id="our_price_display">{convertPrice price=$productPrice}</span>
					<!--{if $tax_enabled  && ((isset($display_tax_label) && $display_tax_label == 1) OR !isset($display_tax_label))}
						{if $priceDisplay == 1}{l s='tax excl.'}{else}{l s='tax incl.'}{/if}
					{/if}-->
				{/if}
				</p>

				{if $product->on_sale}
					<img src="{$img_dir}onsale_{$lang_iso}.gif" alt="{l s='On sale'}" class="on_sale_img"/>
					<span class="on_sale">{l s='On sale!'}</span>
				{elseif $product->specificPrice AND $product->specificPrice.reduction AND $productPriceWithoutReduction > $productPrice}
					<span class="discount">{l s='Reduced price!'}</span>
				{/if}
				{if $priceDisplay == 2}
					<br />
					<span id="pretaxe_price"><span id="pretaxe_price_display">{convertPrice price=$product->getPrice(false, $smarty.const.NULL)}</span> {l s='tax excl.'}</span>
				{/if}
			</div>
			<p id="reduction_percent" {if !$product->specificPrice OR $product->specificPrice.reduction_type != 'percentage'} style="display:none;"{/if}><span id="reduction_percent_display">{if $product->specificPrice AND $product->specificPrice.reduction_type == 'percentage'}-{$product->specificPrice.reduction*100}%{/if}</span></p>
			<p id="reduction_amount" {if !$product->specificPrice OR $product->specificPrice.reduction_type != 'amount' || $product->specificPrice.reduction|intval ==0} style="display:none"{/if}>
				<span id="reduction_amount_display">
				{if $product->specificPrice AND $product->specificPrice.reduction_type == 'amount' AND $product->specificPrice.reduction|intval !=0}
					-{convertPrice price=$productPriceWithoutReduction-$productPrice|floatval}
				{/if}
				</span>
			</p>
			{if $product->specificPrice AND $product->specificPrice.reduction && $product->specificPrice.reduction > 0}
				<p id="old_price"><span class="bold">
				{if $priceDisplay >= 0 && $priceDisplay <= 2}
					{if $productPriceWithoutReduction > $productPrice}
						<span id="old_price_display">{convertPrice price=$productPriceWithoutReduction}</span>
						<!-- {if $tax_enabled && $display_tax_label == 1}
							{if $priceDisplay == 1}{l s='tax excl.'}{else}{l s='tax incl.'}{/if}
						{/if} -->
					{/if}
				{/if}
				</span>
				</p>
			{/if}
			{if $packItems|@count && $productPrice < $product->getNoPackPrice()}
				<p class="pack_price">{l s='Instead of'} <span style="text-decoration: line-through;">{convertPrice price=$product->getNoPackPrice()}</span></p>
				<br class="clear" />
			{/if}
			{if $product->ecotax != 0}
				<p class="price-ecotax">{l s='Include'} <span id="ecotax_price_display">{if $priceDisplay == 2}{$ecotax_tax_exc|convertAndFormatPrice}{else}{$ecotax_tax_inc|convertAndFormatPrice}{/if}</span> {l s='For green tax'}
					{if $product->specificPrice AND $product->specificPrice.reduction}
					<br />{l s='(not impacted by the discount)'}
					{/if}
				</p>
			{/if}
			{if !empty($product->unity) && $product->unit_price_ratio > 0.000000}
				 {math equation="pprice / punit_price"  pprice=$productPrice  punit_price=$product->unit_price_ratio assign=unit_price}
				<p class="unit-price"><span id="unit_price_display">{convertPrice price=$unit_price}</span> {l s='per'} {$product->unity|escape:'htmlall':'UTF-8'}</p>
			{/if}
			{*close if for show price*}
			{/if}
			
			{if isset($HOOK_PRODUCT_ACTIONS) && $HOOK_PRODUCT_ACTIONS}{$HOOK_PRODUCT_ACTIONS}{/if}

			<div class="clear"></div>
		</div>
		
		{/if}
		{if isset($HOOK_EXTRA_RIGHT) && $HOOK_EXTRA_RIGHT}{$HOOK_EXTRA_RIGHT}{/if}
        {if isset($product) && $product->customizable}
            <div id="idTab10" class="bullet customization_block">
                    <p class="infoCustomizable">
                        {l s='After saving your customized product, remember to add it to your cart.'}
                        {if $product->uploadable_files}<br />{l s='Allowed file formats are: GIF, JPG, PNG'}{/if}
                    </p>
                    {if $product->uploadable_files|intval}
                    <div class="customizableProductsFile">
                        <!--<h3>{l s='Pictures'}</h3>-->
                        <ul id="uploadable_files" class="clearfix">
                            {counter start=0 assign='customizationField'}
                            {foreach from=$customizationFields item='field' name='customizationFields'}
                                {if $field.type == 0}
                                    <li class="customizationUploadLine{if $field.required} required{/if}">{assign var='key' value='pictures_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field}
                                        {if isset($pictures.$key)}
                                        <div class="customizationUploadBrowse">
                                            <img src="{$pic_dir}{$pictures.$key}_small" alt="" />
                                            <a href="{$link->getProductDeletePictureLink($product, $field.id_customization_field)}" title="{l s='Delete'}" >
                                                <img src="{$img_dir}icon/delete.gif" alt="{l s='Delete'}" class="customization_delete_icon" width="11" height="13" />
                                            </a>
                                        </div>
                                        {/if}
                                        <div class="customizationUploadBrowse">
                                            <label class="customizationUploadBrowseDescription">{if !empty($field.name)}{$field.name}{else}{l s='Please select an image file from your computer'}{/if}{if $field.required}<sup>*</sup>{/if}</label>
                                            <input type="file" name="file{$field.id_customization_field}" id="img{$customizationField}" class="customization_block_input {if isset($pictures.$key)}filled{/if}" />
                                        </div>
                                    </li>
                                    {counter}
                                {/if}
                            {/foreach}
                        </ul>
                    </div>
                    {/if}
                    {if $product->text_fields|intval}
                    <div class="customizableProductsText">
                        <!--<h3>{l s='Text'}</h3>-->
                        <ul id="text_fields">
                        {counter start=0 assign='customizationField'}
                        {foreach from=$customizationFields item='field' name='customizationFields'}
                            {if $field.type == 1}
                            <li class="customizationUploadLine{if $field.required} required{/if}">
                                <label for ="textField{$customizationField}">{assign var='key' value='textFields_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field} {if !empty($field.name)}{$field.name}{/if}{if $field.required}<sup>*</sup>{/if}</label>
                                <textarea style="height: 30px;" type="text" name="textField{$field.id_customization_field}" id="textField{$customizationField}" rows="1" cols="40" class="customization_block_input">{if isset($textFields.$key)}{$textFields.$key|stripslashes}{/if}</textarea>
                            </li>
                            {counter}
                            {/if}
                        {/foreach}
                        </ul>
                    </div>
                    {/if}
                    <p id="customizedDatas">
                        <input type="hidden" name="quantityBackup" id="quantityBackup" value="" />
                        <input type="hidden" name="submitCustomizedDatas" value="1" />
                        {if (!$allow_oosp && $product->quantity <= 0) OR !$product->available_for_order OR (isset($restricted_country_mode) AND $restricted_country_mode) OR $PS_CATALOG_MODE}
				<span class="exclusive">
					<span></span>
					{l s=''}
				</span>
			{else}
				<p id="add_to_cart" class="buttons_bottom_block">
					<span></span>
					<input type="submit" name="Submit" value="{l s='Add to cart'}" class="add_to_cart_ft" />
				</p>
			{/if}
                        <span id="ajax-loader" style="display:none"><img src="{$img_ps_dir}loader.gif" alt="loader" /></span>
                    </p>
                </form>
                <p class="clear required"><sup>*</sup> {l s='required fields'}</p>
            </div>
        {/if}

Attached are the files for product.tpl and CartController.php for references

 

There might be some layout problems with the product.tpl because I just copied and paste the containers for the forms. Do adjust accordinly to fit your theme.

 

NOTE: This will not work with the ajax-cart.js that i came up with, it is only for non-ajax cart.

 

Cheers

CartController.zip

product_combinedform.zip

Edited by ZenVisuals (see edit history)
  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Hey guys,

 

@Rhapsody: Thanks for the feedback! Yeah I didn't bother about the non ajax operation so it didn't work. Good point about the mobile operation, I totally neglected it! I'm glad you updated your codes on the custom theme and got it working :) I was looking at the non ajax operation and figuring out how the CartController works.

 

Anyway, these are my findings:

 

Since the forms for the customised fields and the other inputs such as the quantity and combination are different and they are posted to ProductController and CartController respectively. To have them submit as one, I combined the inputs into one single form and post it to the CartController only. 

 

The CartController then retrieves the $_POST values of all the inputs in the product page including the customised fields. I then override the processChangeProductInCart() method and proceeded with updating the database with the customised fields first then the other inputs. I took codes from the textRecord() in ProductController and changed it to fit the process.

 

It should work without AJAX. However, I didn't update my ajax-cart.js for this so if AJAX is on, I don't think it will work. Perhaps the original ajax-cart.js might work. Another thing is only text-fields and areas will work, the image upload will not work as I never included codes from pictureUpload(). 

 

This code should be placed in override/modules/front/CartController.php

class CartController extends CartControllerCore
{

	/**
	 * This process add or update a product in the cart
	 */
	 
	protected function processChangeProductInCart()
	{
		$mode = (Tools::getIsset('update') && $this->id_product) ? 'update' : 'add';

		if ($this->qty == 0)
			$this->errors[] = Tools::displayError('Null quantity.');
		else if (!$this->id_product)
			$this->errors[] = Tools::displayError('Product not found');

		$product = new Product($this->id_product, true, $this->context->language->id);
		if (!$product->id || !$product->active)
		{
			$this->errors[] = Tools::displayError('This product is no longer available.', false);
			return;
		}

		// Check product quantity availability
		if ($this->id_product_attribute)
		{
			if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $this->qty))
				$this->errors[] = Tools::displayError('There isn\'t enough product in stock.');
		}
		else if ($product->hasAttributes())
		{
			$minimumQuantity = ($product->out_of_stock == 2) ? !Configuration::get('PS_ORDER_OUT_OF_STOCK') : !$product->out_of_stock;
			$this->id_product_attribute = Product::getDefaultAttribute($product->id, $minimumQuantity);
			// @todo do something better than a redirect admin !!
			if (!$this->id_product_attribute)
				Tools::redirectAdmin($this->context->link->getProductLink($product));
			else if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $this->qty))
				$this->errors[] = Tools::displayError('There isn\'t enough product in stock.');
		}
		else if (!$product->checkQty($this->qty))
			$this->errors[] = Tools::displayError('There isn\'t enough product in stock.');

		// If no errors, process product addition
		if (!$this->errors && $mode == 'add')
		{
			// Add cart if no cart found
			if (!$this->context->cart->id)
			{
				if (Context::getContext()->cookie->id_guest)
				{
					$guest = new Guest(Context::getContext()->cookie->id_guest);
					$this->context->cart->mobile_theme = $guest->mobile_theme;
				}
				$this->context->cart->add();
				if ($this->context->cart->id)
					$this->context->cookie->id_cart = (int)$this->context->cart->id;
			}
			// Process customizable fields first
			
			//get product's customized text fields and input them to $field_ids
			if (!$field_ids = $product->getCustomizationFieldIds())
				return false;
				$authorized_text_fields = array();
				$required_fields = $product->getRequiredCustomizableFields();
				$required_fieldsArray = array();
			
			//get required field ids
			foreach ($required_fields as $requiredfield_id)
				if ($requiredfield_id['type'] == Product::CUSTOMIZE_TEXTFIELD)			
					$required_fieldsArray[(int)$requiredfield_id['id_customization_field']] = 'textField'.(int)$requiredfield_id['id_customization_field'];
			
			//$authorized_text_fields[int] = textField[int of id_customization_field];
			foreach ($field_ids as $field_id)
				if ($field_id['type'] == Product::CUSTOMIZE_TEXTFIELD)			
					$authorized_text_fields[(int)$field_id['id_customization_field']] = 'textField'.(int)$field_id['id_customization_field'];
					
			//values 1,2,3,4,5,6,7 put into array[textField1,2,3,4,5,6,7]
			$indexes = array_flip($authorized_text_fields);
			foreach ($_POST as $field_name => $value)
			{
				//filter required fields
				
					if (in_array($field_name, $required_fieldsArray) && empty($value))
					{
						// stop and make sure user enters required fields
						//p(Customization::getLabel($indexes[$field_name],1)) - gets the label of the id_customization_field with id_lang = 1, 1 is English i assume
						$this->errors[] = Tools::displayError('Please fill this field:' . Customization::getLabel($indexes[$field_name],1));
					}
					else
					{
						if (!Validate::isMessage($value))
							$this->errors[] = Tools::displayError('Invalid message');
					}
				
			}
			// if all required fields are filled, then proceed to add custom fields to database
			if (!$this->errors)
			{
				foreach ($_POST as $field_name => $value)
				{
					if (in_array($field_name, $authorized_text_fields))
					{
						$this->context->cart->addTextFieldToProduct($product->id, $indexes[$field_name], Product::CUSTOMIZE_TEXTFIELD, $value);
					}
				}
			}

			if (!$this->errors)
			{
				$cart_rules = $this->context->cart->getCartRules();
				$update_quantity = $this->context->cart->updateQty($this->qty, $this->id_product, $this->id_product_attribute, $this->customization_id, Tools::getValue('op', 'up'), $this->id_address_delivery);
				if ($update_quantity < 0)
				{
					// If product has attribute, minimal quantity is set with minimal quantity of attribute
					$minimal_quantity = ($this->id_product_attribute) ? Attribute::getAttributeMinimalQty($this->id_product_attribute) : $product->minimal_quantity;
					$this->errors[] = sprintf(Tools::displayError('You must add %d minimum quantity', false), $minimal_quantity);
				}
				elseif (!$update_quantity)
					$this->errors[] = Tools::displayError('You already have the maximum quantity available for this product.', false);
				elseif ((int)Tools::getValue('allow_refresh'))
				{
					// If the cart rules has changed, we need to refresh the whole cart
					$cart_rules2 = $this->context->cart->getCartRules();
					if (count($cart_rules2) != count($cart_rules))
						$this->ajax_refresh = true;
					else
					{
						$rule_list = array();
						foreach ($cart_rules2 as $rule)
							$rule_list[] = $rule['id_cart_rule'];
						foreach ($cart_rules as $rule)
							if (!in_array($rule['id_cart_rule'], $rule_list))
							{
								$this->ajax_refresh = true;
								break;
							}
					}
				}
			}
		}

		$removed = CartRule::autoRemoveFromCart();
		CartRule::autoAddToCart();
		if (count($removed) && (int)Tools::getValue('allow_refresh'))
			$this->ajax_refresh = true;
	}
	
}

I combined both forms in product.tpl

<!-- Customizable products combined with standard inputs-->
		{if ($product->show_price AND !isset($restricted_country_mode)) OR isset($groups) OR $product->reference OR (isset($HOOK_PRODUCT_ACTIONS) && $HOOK_PRODUCT_ACTIONS)}
		<!-- add to cart form-->
		<form id="buy_block" {if $PS_CATALOG_MODE AND !isset($groups) AND $product->quantity > 0}class="hidden"{/if} action="{$link->getPageLink('cart')}" method="post" enctype="multipart/form-data">

			<!-- hidden datas -->
			<p class="hidden">
				<input type="hidden" name="token" value="{$static_token}" />
				<input type="hidden" name="id_product" value="{$product->id|intval}" id="product_page_product_id" />
				<input type="hidden" name="add" value="1" />
				<input type="hidden" name="id_product_attribute" id="idCombination" value="" />
			</p>

			<div class="product_attributes">
				{if isset($groups)}
				<!-- attributes -->
				<div id="attributes">
				<div class="clear"></div>
				{foreach from=$groups key=id_attribute_group item=group}
					{if $group.attributes|@count}
						<fieldset class="attribute_fieldset">
							<label class="attribute_label" for="group_{$id_attribute_group|intval}">{$group.name|escape:'htmlall':'UTF-8'} : </label>
							{assign var="groupName" value="group_$id_attribute_group"}
							<div class="attribute_list">
							{if ($group.group_type == 'select')}
								<select name="{$groupName}" id="group_{$id_attribute_group|intval}" class="attribute_select" onchange="findCombination();getProductAttribute();">
									{foreach from=$group.attributes key=id_attribute item=group_attribute}
										<option value="{$id_attribute|intval}"{if (isset($smarty.get.$groupName) && $smarty.get.$groupName|intval == $id_attribute) || $group.default == $id_attribute} selected="selected"{/if} title="{$group_attribute|escape:'htmlall':'UTF-8'}">{$group_attribute|escape:'htmlall':'UTF-8'}</option>
									{/foreach}
								</select>
							{elseif ($group.group_type == 'color')}
								<ul id="color_to_pick_list" class="clearfix">
									{assign var="default_colorpicker" value=""}
									{foreach from=$group.attributes key=id_attribute item=group_attribute}
									<li{if $group.default == $id_attribute} class="selected"{/if}>
										<a id="color_{$id_attribute|intval}" class="color_pick{if ($group.default == $id_attribute)} selected{/if}" style="background: {$colors.$id_attribute.value};" title="{$colors.$id_attribute.name}" onclick="colorPickerClick(this);getProductAttribute();">
											{if file_exists($col_img_dir|cat:$id_attribute|cat:'.jpg')}
												<img src="{$img_col_dir}{$id_attribute}.jpg" alt="{$colors.$id_attribute.name}" width="20" height="20" /><br />
											{/if}
										</a>
									</li>
									{if ($group.default == $id_attribute)}
										{$default_colorpicker = $id_attribute}
									{/if}
									{/foreach}
								</ul>
								<input type="hidden" class="color_pick_hidden" name="{$groupName}" value="{$default_colorpicker}" />
							{elseif ($group.group_type == 'radio')}
								<ul>
									{foreach from=$group.attributes key=id_attribute item=group_attribute}
										<li>
											<input type="radio" class="attribute_radio" name="{$groupName}" value="{$id_attribute}" {if ($group.default == $id_attribute)} checked="checked"{/if} onclick="findCombination();getProductAttribute();" />
											<span>{$group_attribute|escape:'htmlall':'UTF-8'}</span>
										</li>
									{/foreach}
								</ul>
							{/if}
							</div>
						</fieldset>
					{/if}
				{/foreach}
				</div>
			{/if}
			<p id="product_reference" {if isset($groups) OR !$product->reference}style="display: none;"{/if}>
				<label for="product_reference">{l s='Reference:'} </label>
				<span class="editable">{$product->reference|escape:'htmlall':'UTF-8'}</span>
			</p>

			<!-- quantity wanted -->
            {if $product->id == 6}{else}
			<p id="quantity_wanted_p"{if (!$allow_oosp && $product->quantity <= 0) OR $virtual OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none;"{/if}>
				<label>{l s='Quantity:'}</label>
				<input type="text" name="qty" id="quantity_wanted" class="text" value="{if isset($quantityBackup)}{$quantityBackup|intval}{else}{if $product->minimal_quantity > 1}{$product->minimal_quantity}{else}1{/if}{/if}" size="2" maxlength="3" {if $product->minimal_quantity > 1}onkeyup="checkMinimalQuantity({$product->minimal_quantity});"{/if} />
			</p>
{/if}
			<!-- minimal quantity wanted -->
			<p id="minimal_quantity_wanted_p"{if $product->minimal_quantity <= 1 OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none;"{/if}>
				{l s='This product is not sold individually. You must select at least'} <b id="minimal_quantity_label">{$product->minimal_quantity}</b> {l s='quantity for this product.'}
			</p>
			{if $product->minimal_quantity > 1}
			<script type="text/javascript">
				checkMinimalQuantity();
			</script>
			{/if}

			<!-- availability -->
			<p id="availability_statut"{if ($product->quantity <= 0 && !$product->available_later && $allow_oosp) OR ($product->quantity > 0 && !$product->available_now) OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none;"{/if}>
				<span id="availability_label">{l s='Availability:'}</span>
				<span id="availability_value"{if $product->quantity <= 0} class="warning_inline"{/if}>{if $product->quantity <= 0}{if $allow_oosp}{$product->available_later}{else}{l s='This product is no longer in stock'}{/if}{else}{$product->available_now}{/if}</span>				
			</p>
			<p id="availability_date"{if ($product->quantity > 0) OR !$product->available_for_order OR $PS_CATALOG_MODE OR !isset($product->available_date) OR $product->available_date < $smarty.now|date_format:'%Y-%m-%d'} style="display: none;"{/if}>
				<span id="availability_date_label">{l s='Availability date:'}</span>
				<span id="availability_date_value">{dateFormat date=$product->available_date full=false}</span>
			</p>
			<!-- number of item in stock -->
			{if ($display_qties == 1 && !$PS_CATALOG_MODE && $product->available_for_order)}
			<p id="pQuantityAvailable"{if $product->quantity <= 0} style="display: none;"{/if}>
				<span id="quantityAvailable">{$product->quantity|intval}</span>
				<span {if $product->quantity > 1} style="display: none;"{/if} id="quantityAvailableTxt">{l s='Item in stock'}</span>
				<span {if $product->quantity == 1} style="display: none;"{/if} id="quantityAvailableTxtMultiple">{l s='Items in stock'}</span>
			</p>
			{/if}

			<!-- Out of stock hook -->
			<div id="oosHook"{if $product->quantity > 0} style="display: none;"{/if}>
				{$HOOK_PRODUCT_OOS}
			</div>

			<p class="warning_inline" id="last_quantities"{if ($product->quantity > $last_qties OR $product->quantity <= 0) OR $allow_oosp OR !$product->available_for_order OR $PS_CATALOG_MODE} style="display: none"{/if} >{l s='Warning: Last items in stock!'}</p>
		</div>

		<div class="content_prices clearfix">
			<!-- prices -->
			{if $product->show_price AND !isset($restricted_country_mode) AND !$PS_CATALOG_MODE}

			{if $product->online_only}
			<p class="online_only">{l s='Online only'}</p>
			{/if}

			<div class="price">
				<p class="our_price_display">
				{if $priceDisplay >= 0 && $priceDisplay <= 2}
					<span id="our_price_display">{convertPrice price=$productPrice}</span>
					<!--{if $tax_enabled  && ((isset($display_tax_label) && $display_tax_label == 1) OR !isset($display_tax_label))}
						{if $priceDisplay == 1}{l s='tax excl.'}{else}{l s='tax incl.'}{/if}
					{/if}-->
				{/if}
				</p>

				{if $product->on_sale}
					<img src="{$img_dir}onsale_{$lang_iso}.gif" alt="{l s='On sale'}" class="on_sale_img"/>
					<span class="on_sale">{l s='On sale!'}</span>
				{elseif $product->specificPrice AND $product->specificPrice.reduction AND $productPriceWithoutReduction > $productPrice}
					<span class="discount">{l s='Reduced price!'}</span>
				{/if}
				{if $priceDisplay == 2}
					<br />
					<span id="pretaxe_price"><span id="pretaxe_price_display">{convertPrice price=$product->getPrice(false, $smarty.const.NULL)}</span> {l s='tax excl.'}</span>
				{/if}
			</div>
			<p id="reduction_percent" {if !$product->specificPrice OR $product->specificPrice.reduction_type != 'percentage'} style="display:none;"{/if}><span id="reduction_percent_display">{if $product->specificPrice AND $product->specificPrice.reduction_type == 'percentage'}-{$product->specificPrice.reduction*100}%{/if}</span></p>
			<p id="reduction_amount" {if !$product->specificPrice OR $product->specificPrice.reduction_type != 'amount' || $product->specificPrice.reduction|intval ==0} style="display:none"{/if}>
				<span id="reduction_amount_display">
				{if $product->specificPrice AND $product->specificPrice.reduction_type == 'amount' AND $product->specificPrice.reduction|intval !=0}
					-{convertPrice price=$productPriceWithoutReduction-$productPrice|floatval}
				{/if}
				</span>
			</p>
			{if $product->specificPrice AND $product->specificPrice.reduction && $product->specificPrice.reduction > 0}
				<p id="old_price"><span class="bold">
				{if $priceDisplay >= 0 && $priceDisplay <= 2}
					{if $productPriceWithoutReduction > $productPrice}
						<span id="old_price_display">{convertPrice price=$productPriceWithoutReduction}</span>
						<!-- {if $tax_enabled && $display_tax_label == 1}
							{if $priceDisplay == 1}{l s='tax excl.'}{else}{l s='tax incl.'}{/if}
						{/if} -->
					{/if}
				{/if}
				</span>
				</p>
			{/if}
			{if $packItems|@count && $productPrice < $product->getNoPackPrice()}
				<p class="pack_price">{l s='Instead of'} <span style="text-decoration: line-through;">{convertPrice price=$product->getNoPackPrice()}</span></p>
				<br class="clear" />
			{/if}
			{if $product->ecotax != 0}
				<p class="price-ecotax">{l s='Include'} <span id="ecotax_price_display">{if $priceDisplay == 2}{$ecotax_tax_exc|convertAndFormatPrice}{else}{$ecotax_tax_inc|convertAndFormatPrice}{/if}</span> {l s='For green tax'}
					{if $product->specificPrice AND $product->specificPrice.reduction}
					<br />{l s='(not impacted by the discount)'}
					{/if}
				</p>
			{/if}
			{if !empty($product->unity) && $product->unit_price_ratio > 0.000000}
				 {math equation="pprice / punit_price"  pprice=$productPrice  punit_price=$product->unit_price_ratio assign=unit_price}
				<p class="unit-price"><span id="unit_price_display">{convertPrice price=$unit_price}</span> {l s='per'} {$product->unity|escape:'htmlall':'UTF-8'}</p>
			{/if}
			{*close if for show price*}
			{/if}
			
			{if isset($HOOK_PRODUCT_ACTIONS) && $HOOK_PRODUCT_ACTIONS}{$HOOK_PRODUCT_ACTIONS}{/if}

			<div class="clear"></div>
		</div>
		
		{/if}
		{if isset($HOOK_EXTRA_RIGHT) && $HOOK_EXTRA_RIGHT}{$HOOK_EXTRA_RIGHT}{/if}
        {if isset($product) && $product->customizable}
            <div id="idTab10" class="bullet customization_block">
                    <p class="infoCustomizable">
                        {l s='After saving your customized product, remember to add it to your cart.'}
                        {if $product->uploadable_files}<br />{l s='Allowed file formats are: GIF, JPG, PNG'}{/if}
                    </p>
                    {if $product->uploadable_files|intval}
                    <div class="customizableProductsFile">
                        <!--<h3>{l s='Pictures'}</h3>-->
                        <ul id="uploadable_files" class="clearfix">
                            {counter start=0 assign='customizationField'}
                            {foreach from=$customizationFields item='field' name='customizationFields'}
                                {if $field.type == 0}
                                    <li class="customizationUploadLine{if $field.required} required{/if}">{assign var='key' value='pictures_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field}
                                        {if isset($pictures.$key)}
                                        <div class="customizationUploadBrowse">
                                            <img src="{$pic_dir}{$pictures.$key}_small" alt="" />
                                            <a href="{$link->getProductDeletePictureLink($product, $field.id_customization_field)}" title="{l s='Delete'}" >
                                                <img src="{$img_dir}icon/delete.gif" alt="{l s='Delete'}" class="customization_delete_icon" width="11" height="13" />
                                            </a>
                                        </div>
                                        {/if}
                                        <div class="customizationUploadBrowse">
                                            <label class="customizationUploadBrowseDescription">{if !empty($field.name)}{$field.name}{else}{l s='Please select an image file from your computer'}{/if}{if $field.required}<sup>*</sup>{/if}</label>
                                            <input type="file" name="file{$field.id_customization_field}" id="img{$customizationField}" class="customization_block_input {if isset($pictures.$key)}filled{/if}" />
                                        </div>
                                    </li>
                                    {counter}
                                {/if}
                            {/foreach}
                        </ul>
                    </div>
                    {/if}
                    {if $product->text_fields|intval}
                    <div class="customizableProductsText">
                        <!--<h3>{l s='Text'}</h3>-->
                        <ul id="text_fields">
                        {counter start=0 assign='customizationField'}
                        {foreach from=$customizationFields item='field' name='customizationFields'}
                            {if $field.type == 1}
                            <li class="customizationUploadLine{if $field.required} required{/if}">
                                <label for ="textField{$customizationField}">{assign var='key' value='textFields_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field} {if !empty($field.name)}{$field.name}{/if}{if $field.required}<sup>*</sup>{/if}</label>
                                <textarea style="height: 30px;" type="text" name="textField{$field.id_customization_field}" id="textField{$customizationField}" rows="1" cols="40" class="customization_block_input">{if isset($textFields.$key)}{$textFields.$key|stripslashes}{/if}</textarea>
                            </li>
                            {counter}
                            {/if}
                        {/foreach}
                        </ul>
                    </div>
                    {/if}
                    <p id="customizedDatas">
                        <input type="hidden" name="quantityBackup" id="quantityBackup" value="" />
                        <input type="hidden" name="submitCustomizedDatas" value="1" />
                        {if (!$allow_oosp && $product->quantity <= 0) OR !$product->available_for_order OR (isset($restricted_country_mode) AND $restricted_country_mode) OR $PS_CATALOG_MODE}
				<span class="exclusive">
					<span></span>
					{l s=''}
				</span>
			{else}
				<p id="add_to_cart" class="buttons_bottom_block">
					<span></span>
					<input type="submit" name="Submit" value="{l s='Add to cart'}" class="add_to_cart_ft" />
				</p>
			{/if}
                        <span id="ajax-loader" style="display:none"><img src="{$img_ps_dir}loader.gif" alt="loader" /></span>
                    </p>
                </form>
                <p class="clear required"><sup>*</sup> {l s='required fields'}</p>
            </div>
        {/if}

Attached are the files for product.tpl and CartController.php for references

 

There might be some layout problems with the product.tpl because I just copied and paste the containers for the forms. Do adjust accordinly to fit your theme.

 

NOTE: This will not work with the ajax-cart.js that i came up with, it is only for non-ajax cart.

 

Cheers

 

Nice!

 

Wich versions are supported for this mod?

 

Anyway, hope someone try to mod it for ajax-cart soon!  :)

Link to comment
Share on other sites

  • 3 weeks later...

I would also like to add that I downloaded and tried the files above provided by ZenVisuals and it did not work. It added the product to the cart but ignored the customisation field.

 

Just for reference, I tried this on version 1.5.6.1 with Ajax turned off.

Link to comment
Share on other sites

  • 2 weeks later...

I am using the Prestashop 1.5.4.1 with default theme and non-ajax cart. The problem is, I've made several customizations to the product page, even though I've added a module to move the product customization elements before the add to cart button. Furthermore, I've added some ajax call to show customization in realtime on the image.

 

The question is: how to do that thing now?

 

Is there any step by step way to do that as I can't figure out with that long discussion.

 

My shop is: http://www.mattgeo.com/

Link to comment
Share on other sites

  • 2 weeks later...

Figured out a way to do it granted it's not the correct way and I'm on too short of a deadline to make it clean. Also, only for text fields. I didn't need image upload so I didnt even try with that.

 

See attached. Tested on 1.5.2. Put the file in /overrides/controllers/front/

 

Requires .tpl modifcation that is fairly straightforward: Remove the save button and put the following code in the form which submits to the cart:

{if $product->text_fields|intval}
    {counter start=0 assign='customizationField'}
    {foreach from=$customizationFields item='field' name='customizationFields'}
        {if $field.type == 1}
            <label for ="textField{$customizationField}">{assign var='key' value='textFields_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field} {if !empty($field.name)}{$field.name}{/if}{if $field.required}<sup>*</sup>{/if}</label>
            <textarea type="text" name="textField{$field.id_customization_field}" id="textField{$customizationField}" rows="1" cols="40" class="customization_block_input" />{if isset($textFields.$key)}{$textFields.$key|stripslashes}{/if}</textarea>
            {counter}
        {/if}
    {/foreach}
{/if}
<input type="hidden" name="quantityBackup" id="quantityBackup" value="" />
<input type="hidden" name="submitCustomizedDatas" value="1" />
Of course all you really need are the inputs. The code is stolen from the other customization area on the page and minified a little. Nothing changed. Be sure to remove the customization form as well.

 

 

Yes this worked perfectly for me in 1.6! Thanks so much I have been looking for a solution to this problem for so long! I do have an image upload but I just left that in it's original form and labeled the save button as Upload instead of save.

Link to comment
Share on other sites

Yes this worked perfectly for me in 1.6! Thanks so much I have been looking for a solution to this problem for so long! I do have an image upload but I just left that in it's original form and labeled the save button as Upload instead of save.

 

I'm still having trouble getting this to work. It seems to add it to the cart but none of the customisation seems to appear. Could you give me any advice as to what I'm doing wrong?

 

I copied the attached file into cart/controllers/front/

 

I also copied the small code snippet onto the page (under the cart submission) which creates the text input box. But when I click submit, it adds the product to the cart as if there is no customisation option.

 

Is there any advice for what I'm doing wrong? Also, probably worth mentioning that I am trying this on version 1.6.0.6.

 

P.S - Is it also necessary to place the code snippet in a specific part of the .TPL file? Could I place it in a different place in the template?

Link to comment
Share on other sites

  • 3 weeks later...

I'm working with the default theme on prestashop 1.6

 

When customers fill in the custum fields and forget to push the save button and directly push add to cart

 

we lose the information the customer filled in.

 

PS should auto save the custum fields for them when pressing add to cart!

 

this I thought should be easy but, for me, its not.

 

I hoped to edit the product.tpl and find a "click-on code" that I could copy and paste to the add to cart button. But unfortunatly  thats not a slolution.

 

Annybody hav a simple solution for me?

 

I would realy apriciate it!

 

Anybody please

Edited by guidor (see edit history)
Link to comment
Share on other sites

  • 2 weeks later...

I'm working with the default theme on prestashop 1.6

 

When customers fill in the custum fields and forget to push the save button and directly push add to cart

 

we lose the information the customer filled in.

 

PS should auto save the custum fields for them when pressing add to cart!

 

this I thought should be easy but, for me, its not.

 

I hoped to edit the product.tpl and find a "click-on code" that I could copy and paste to the add to cart button. But unfortunatly  thats not a slolution.

 

Annybody hav a simple solution for me?

 

I would realy apriciate it!

 

Anybody please

anybody please

Link to comment
Share on other sites

same problem.

And I don't know how starsg38

in the last post 

Yes this worked perfectly for me in 1.6! Thanks so much I have been looking for a solution to this problem for so long! I do have an image upload but I just left that in it's original form and labeled the save button as Upload instead of save.

not wok!

Edited by serperui (see edit history)
Link to comment
Share on other sites

  • 3 weeks later...

Figured out a way to do it granted it's not the correct way and I'm on too short of a deadline to make it clean. Also, only for text fields. I didn't need image upload so I didnt even try with that.

 

See attached. Tested on 1.5.2. Put the file in /overrides/controllers/front/

 

Requires .tpl modifcation that is fairly straightforward: Remove the save button and put the following code in the form which submits to the cart:

{if $product->text_fields|intval}
    {counter start=0 assign='customizationField'}
    {foreach from=$customizationFields item='field' name='customizationFields'}
        {if $field.type == 1}
            <label for ="textField{$customizationField}">{assign var='key' value='textFields_'|cat:$product->id|cat:'_'|cat:$field.id_customization_field} {if !empty($field.name)}{$field.name}{/if}{if $field.required}<sup>*</sup>{/if}</label>
            <textarea type="text" name="textField{$field.id_customization_field}" id="textField{$customizationField}" rows="1" cols="40" class="customization_block_input" />{if isset($textFields.$key)}{$textFields.$key|stripslashes}{/if}</textarea>
            {counter}
        {/if}
    {/foreach}
{/if}
<input type="hidden" name="quantityBackup" id="quantityBackup" value="" />
<input type="hidden" name="submitCustomizedDatas" value="1" />
Of course all you really need are the inputs. The code is stolen from the other customization area on the page and minified a little. Nothing changed. Be sure to remove the customization form as well.

 

Good morning,

 

Thanks for sharing with us.

 

I'm using the latest version of prestashop 1.6 and have disabled the ajax.

 

Something is not working for me, when I give "add to cart" tells me "Please fill in all required fields, then save the customization."

 

   Does CartController.php file in 1.6 also goes in the / override/controllers/front ?

 

Now I'm testing a 1.5.6.2 and still and work but 1.6 not work :(

please i need you

Thank you

Edited by thuxu007 (see edit history)
Link to comment
Share on other sites

  • 4 weeks later...

I haven't followed this thread in a while so I'm not sure about the findings beyond page 7. But the solutions posted page 7 by Rhapsody ( http://www.prestashop.com/forums/topic/76874-how-to-remove-save-button-for-customized-fields/?p=1140428 ) [for text fields] and my addition for file uploads ( http://www.prestashop.com/forums/topic/76874-how-to-remove-save-button-for-customized-fields/?p=1185115work perfectly on 1.6 !

 

You will need to disable ajax-cart though since those solutions do not work with ajax cart. I think some modifications for getting it to work with ajax cart have been posted after page 7, just read carefully.

Edited by defuzed (see edit history)
Link to comment
Share on other sites

  • 4 weeks later...

Because of all the code snippets, ajax cart or non ajax this topic is totally unreadable :(

Can somebody post the solution for Prestashop 1.6 with ajax cart enabled?

 

Thank in advance!

 

I agree... I have no clue where to start since this thread is so old and 9 pages long.    Can anyone give a clear guide for 1.6 to accomplish this mod??   I seriously need this.   

Link to comment
Share on other sites

I agree... I have no clue where to start since this thread is so old and 9 pages long.    Can anyone give a clear guide for 1.6 to accomplish this mod??   I seriously need this.   

 

 

If you really need to hide the save button, there is a module for that, works with ajax, for any ps version, has more functions and cost 49,90 €.

 

The module is Advanced customizations and works very well:

http://addons.prestashop.com/es/aplicaciones-front-office-prestashop-modulos/6638-advanced-customizations.html

 

You can see it working in my site:

http://cincelaser.com/cristaleria/85-copa-gin-tonic-990-ml-en-cajita-regalo.html

Link to comment
Share on other sites

If you really need to hide the save button, there is a module for that, works with ajax, for any ps version, has more functions and cost 49,90 €.

 

The module is Advanced customizations and works very well:

http://addons.prestashop.com/es/aplicaciones-front-office-prestashop-modulos/6638-advanced-customizations.html

 

You can see it working in my site:

http://cincelaser.com/cristaleria/85-copa-gin-tonic-990-ml-en-cajita-regalo.html

 

 

Thank you.  That looks to be exactly what I am looking for.   Is this your module??   I need to be absolutely sure it will work with my custom paid theme if i am going to spend $70 USD on it.

 

Thanks again.

Link to comment
Share on other sites

Thank you.  That looks to be exactly what I am looking for.   Is this your module??   I need to be absolutely sure it will work with my custom paid theme if i am going to spend $70 USD on it.

 

Thanks again.

 

it's not my module, I'm a ps user like you that was looking for this a long time too. In case it doesn't work for you you can request a refund. Just only take into account that some paid templates  doesn't follow Prestashop's standards, so maybe the developer have to adapt it for you. That was happenned to me.

 

In my case, the users can't delete customized products from block cart but is a template problem that happened before installing the module. Working to solve it.

Link to comment
Share on other sites

  • 3 weeks later...

hi

Am I supposed just to download the zip with the cart.php and the ajax-cart.js and upload it to the server? Sorry if my question sound silly, but I'm not a programmer and I'm trying to solve this by my own. I've uploaded the two files to the server and nothing happens. It seems like it's not overwriting the files. I've already changes the permissions of those 2 files to 777

My shop is running the 1.3.1 version.

 

Thanks in advance

Link to comment
Share on other sites

  • 2 months later...
  • 1 month later...

This is solution for AJAX CART Prestashop 1.6.0.9 but which standard module of CART and required field :) - REMEMBER only change this file \themes\default-bootstrap\js\modules\blockcart\ajax-cart.js

 

/*
* 2007-2014 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <[email protected]>
*  @copyright  2007-2014 PrestaShop SA
*  @license    http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/
$(document).ready(function(){





    ajaxCart.overrideButtonsInThePage();

    $(document).on('click', '.block_cart_collapse', function(e){
        e.preventDefault();
        ajaxCart.collapse();
    });
    $(document).on('click', '.block_cart_expand', function(e){
        e.preventDefault();
        ajaxCart.expand();
    });

    var cart_qty = 0;
    var current_timestamp = parseInt(new Date().getTime() / 1000);

    if (typeof $('.ajax_cart_quantity').html() == 'undefined' || (typeof generated_date != 'undefined' && generated_date != null && (parseInt(generated_date) + 30) < current_timestamp))
        ajaxCart.refresh();
    else
        cart_qty = parseInt($('.ajax_cart_quantity').html());

    /* roll over cart */
    var cart_block = new HoverWatcher('#header .cart_block');
    var shopping_cart = new HoverWatcher('#header .shopping_cart');


    if ('ontouchstart' in document.documentElement)

    {
        $('.shopping_cart > a:first').on('click', function(e){
            e.preventDefault();
        });
    }

    $(document).on('touchstart', '#header .shopping_cart a:first', function(){
        if ($(this).next('.cart_block:visible').length)
            $("#header .cart_block").stop(true, true).slideUp(450);
        else
            $("#header .cart_block").stop(true, true).slideDown(450);
        e.preventDefault();
        e.stopPropagation();













    });

    $("#header .shopping_cart a:first").hover(
        function(){
            if (ajaxCart.nb_total_products > 0 || cart_qty > 0)
                $("#header .cart_block").stop(true, true).slideDown(450);
        },
        function(){
            setTimeout(function(){
                if (!shopping_cart.isHoveringOver() && !cart_block.isHoveringOver())
                    $("#header .cart_block").stop(true, true).slideUp(450);                
            }, 200);
        }
    );

    $("#header .cart_block").hover(
        function(){
        },
        function(){
            setTimeout(function(){
                if (!shopping_cart.isHoveringOver())
                    $("#header .cart_block").stop(true, true).slideUp(450);
            }, 200);
        }
    );

    $(document).on('click', '.delete_voucher', function(e){
        e.preventDefault();
        $.ajax({
            type: 'POST',
            headers: { "cache-control": "no-cache" },
            async: true,
            cache: false,
            url:$(this).attr('href') + '?rand=' + new Date().getTime()
        });
        $(this).parent().parent().remove();
        if ($('body').attr('id') == 'order' || $('body').attr('id') == 'order-opc')
        {
            if (typeof(updateAddressSelection) != 'undefined')
                updateAddressSelection();
            else
                location.reload();
        }
    });

    $(document).on('click', '#cart_navigation input', function(e){
        $(this).prop('disabled', 'disabled').addClass('disabled');
        $(this).closest("form").get(0).submit();
    });

    $(document).on('click', '#layer_cart .cross, #layer_cart .continue, .layer_cart_overlay', function(e){
        e.preventDefault();
        $('.layer_cart_overlay').hide();
        $('#layer_cart').fadeOut('fast');
    });
    
    $('#columns #layer_cart, #columns .layer_cart_overlay').detach().prependTo('#columns');
});

//JS Object : update the cart by ajax actions
var ajaxCart = {
    nb_total_products: 0,
    //override every button in the page in relation to the cart
    overrideButtonsInThePage : function(){
        //for every 'add' buttons...
        $(document).on('click', '.ajax_add_to_cart_button', function(e){
            e.preventDefault();
            var idProduct =  $(this).data('id-product');



            if ($(this).prop('disabled') != 'disabled')
                ajaxCart.add(idProduct, null, false, this);
        });
        //for product page 'add' button...
        $(document).on('click', '#add_to_cart button', function(e){
            e.preventDefault();
            ajaxCart.add($('#product_page_product_id').val(), $('#idCombination').val(), true, null, $('#quantity_wanted').val(), null);
        });

        //for 'delete' buttons in the cart block...
        $(document).on('click', '.cart_block_list .ajax_cart_block_remove_link', function(e){
            e.preventDefault();
            // Customized product management
            var customizationId = 0;
            var productId = 0;
            var productAttributeId = 0;
            var customizableProductDiv = $($(this).parent().parent()).find("div[data-id^=deleteCustomizableProduct_]");
            var idAddressDelivery = false;

            if (customizableProductDiv && $(customizableProductDiv).length)
            {
                var ids = customizableProductDiv.data('id').split('_');
                if (typeof(ids[1]) != 'undefined')
                {
                    customizationId = parseInt(ids[1]);
                    productId = parseInt(ids[2]);
                    if (typeof(ids[3]) != 'undefined')
                        productAttributeId = parseInt(ids[3]);
                    if (typeof(ids[4]) != 'undefined')
                        idAddressDelivery = parseInt(ids[4]);
                }
            }

            // Common product management
            if (!customizationId)
            {
                //retrieve idProduct and idCombination from the displayed product in the block cart
                var firstCut = $(this).parent().parent().data('id').replace('cart_block_product_', '');
                firstCut = firstCut.replace('deleteCustomizableProduct_', '');
                ids = firstCut.split('_');
                productId = parseInt(ids[0]);

                if (typeof(ids[1]) != 'undefined')
                    productAttributeId = parseInt(ids[1]);
                if (typeof(ids[2]) != 'undefined')
                    idAddressDelivery = parseInt(ids[2]);
            }

            // Removing product from the cart
            ajaxCart.remove(productId, productAttributeId, customizationId, idAddressDelivery);
        });
    },

    // try to expand the cart
    expand : function(){
        if ($('.cart_block_list').hasClass('collapsed'))
        {
            $('.cart_block_list.collapsed').slideDown({
                duration: 450,
                complete: function(){

                    $(this).addClass('expanded').removeClass('collapsed');
                }
            });

            // save the expand statut in the user cookie
            $.ajax({
                type: 'POST',
                headers: { "cache-control": "no-cache" },
                url: baseDir + 'modules/blockcart/blockcart-set-collapse.php' + '?rand=' + new Date().getTime(),
                async: true,
                cache: false,
                data: 'ajax_blockcart_display=expand',
                complete: function(){
                    $('.block_cart_expand').fadeOut('fast', function(){
                        $('.block_cart_collapse').fadeIn('fast');
                    });
                }            
            });
        }
    },

    // try to collapse the cart
    collapse : function(){
        if ($('.cart_block_list').hasClass('expanded'))
        {
            $('.cart_block_list.expanded').slideUp('slow', function(){
                $(this).addClass('collapsed').removeClass('expanded');
            });

            // save the expand statut in the user cookie
            $.ajax({
                type: 'POST',
                headers: { "cache-control": "no-cache" },
                url: baseDir + 'modules/blockcart/blockcart-set-collapse.php' + '?rand=' + new Date().getTime(),
                async: true,
                cache: false,
                data: 'ajax_blockcart_display=collapse' + '&rand=' + new Date().getTime(),
                complete: function(){
                    $('.block_cart_collapse').fadeOut('fast', function(){
                        $('.block_cart_expand').fadeIn('fast');
                    });
                }
            });
        }
    },
    // Fix display when using back and previous browsers buttons
    refresh : function(){
        $.ajax({
            type: 'POST',
            headers: { "cache-control": "no-cache" },
            url: baseUri + '?rand=' + new Date().getTime(),
            async: true,
            cache: false,
            dataType : "json",
            data: 'controller=cart&ajax=true&token=' + static_token,
            success: function(jsonData)
            {
                ajaxCart.updateCart(jsonData);
            }
        });
    },

    // Update the cart information
    updateCartInformation : function (jsonData, addedFromProductPage){
        ajaxCart.updateCart(jsonData);
        //reactive the button when adding has finished
        if (addedFromProductPage)
        {
            $('#add_to_cart button').removeProp('disabled').removeClass('disabled');
            if (!jsonData.hasError || jsonData.hasError == false)
                $('#add_to_cart button').addClass('added');
            else
                $('#add_to_cart button').removeClass('added');
        }
        else
            $('.ajax_add_to_cart_button').removeProp('disabled');
    },
    // close fancybox
    updateFancyBox : function (){},
    // add a product in the cart via ajax
    /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
    add : function(idProduct, idCombination, addedFromProductPage, callerElement, quantity, whishlist){




























        var addBtn_val = $('#add_to_cart button').val();
        if (addedFromProductPage) {
            //button change, disable and do status text
            $('#add_to_cart button').prop('disabled', 'disabled').addClass('disabled');
            //$('#add_to_cart button').attr('disabled', true).removeClass('exclusive').addClass('exclusive_disabled').val("Processing...");
            $('.filled').removeClass('filled');
            //not depending on php backend to do validation but jquery
            $("form#customizationForm .required :input").each(function() {
            if ($.trim($(this).val()).length == 0) {
            $(this).css("border", "red 1px solid");
            $form_verify = false;
            $('#add_to_cart button').val(addBtn_val).removeAttr('disabled').addClass('exclusive').removeClass('exclusive_disabled');        
        } else {
            $(this).removeAttr("style");
            $(this).css("height", "30px");
            $form_verify = true;
        }







        
        });
        if($form_verify) {
        var cform = $("form#customizationForm");
        var cform_data = cform.serialize();
        var cform_action = cform.attr("action");
        var cform_method = cform.attr("method");
        var cform_enctype = cform.attr("enctype");
        //use ajax send the customizationForm data, will still be successful even though there is error on PHP side.
        $.ajax({
        type: cform_method,
        headers: { "cache-control": "no-cache" },
        url: cform_action,
        cache: false,
        data: cform_data,
        success: function(response) {
        //when customizationForm is successfully submitted, proceed to adding product to cart
        emptyCustomizations();
        // adding product now
        $.ajax({
            type: 'POST',
            headers: { "cache-control": "no-cache" },
            url: baseUri + '?rand=' + new Date().getTime(),
            async: true,
            cache: false,
            dataType : "json",
            data: 'controller=cart&add=1&ajax=true&qty=' + ((quantity && quantity != null) ? quantity : '1') + '&id_product=' + idProduct + '&token=' + static_token + ( (parseInt(idCombination) && idCombination != null) ? '&ipa=' + parseInt(idCombination): ''),
            success: function(jsonData,textStatus,jqXHR)
            {
            
            // add appliance to whishlist module
            if (whishlist && !jsonData.errors)
            WishlistAddProductCart(whishlist[0], idProduct, idCombination, whishlist[1]);

            //== Pokazywanie okna po dodaniu do koszyka oraz wyczyszczenie listy z wgranymi fotkami
            /*----------------------------------------------------------------------------------------------------------------------*/
             if (!jsonData.hasError)
                {
                
                /*-----------------------------------------------------------------------------------------------------*/
                $('#add_to_cart').css('display','none !important');
                $('#add_to_cart button').removeProp('disabled').removeClass('disabled');    
                $('#previews div').html('');
                $('.parameters_info').removeClass('show_parameters_info');
                /*-----------------------------------------------------------------------------------------------------*/
                
                    if (contentOnly) {
                        window.parent.ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
                        
                    } else {
                        ajaxCart.updateCartInformation(jsonData, addedFromProductPage);

                    }
                    if (jsonData.crossSelling)
                        $('.crossseling').html(jsonData.crossSelling);

                    if (idCombination)
                        $(jsonData.products).each(function(){
                            if (this.id != undefined && this.id == parseInt(idProduct) && this.idCombination == parseInt(idCombination))
                                if (contentOnly)
                                    window.parent.ajaxCart.updateLayer(this);    
                                else
                                    ajaxCart.updateLayer(this);
                        });
                    else
                        $(jsonData.products).each(function(){
                            if (this.id != undefined && this.id == parseInt(idProduct))
                                if (contentOnly)
                                    window.parent.ajaxCart.updateLayer(this);
                                else
                                    ajaxCart.updateLayer(this);                    
                        });
                    if (contentOnly)
                        parent.$.fancybox.close();

                        
                    
                } else {

                    if (contentOnly) {
                        window.parent.ajaxCart.updateCart(jsonData);
                    } else {
                        ajaxCart.updateCart(jsonData);    
                    }
                    if (addedFromProductPage) {
                        $('#add_to_cart button').removeProp('disabled').removeClass('disabled');                        
                    } else {
                        $(callerElement).removeProp('disabled');
                    }
                }

                /*----------------------------------------------------------------------------------------------------------------------*/
            // add the picture to the cart
            var $element = $(callerElement).parent().parent().find('a.product_image img,a.product_img_link img');
            if (!$element.length)
            $element = $('#bigpic');
            var $picture = $element.clone();
            var pictureOffsetOriginal = $element.offset();
            
            if ($picture.size())
            $picture.css({'position': 'absolute', 'top': pictureOffsetOriginal.top, 'left': pictureOffsetOriginal.left});
            
            var pictureOffset = $picture.offset();
            if ($('#cart_block')[0] && $('#cart_block').offset().top && $('#cart_block').offset().left)
            var cartBlockOffset = $('#cart_block').offset();
            else
            var cartBlockOffset = $('#shopping_cart').offset();
            
            // Check if the block cart is activated for the animation
            if (cartBlockOffset != undefined && $picture.size())
            {
            $picture.appendTo('body');
            $picture.css({ 'position': 'absolute', 'top': $picture.css('top'), 'left': $picture.css('left'), 'z-index': 4242 })
            .animate({ 'width': $element.attr('width')*0.66, 'height': $element.attr('height')*0.66, 'opacity': 0.2, 'top': cartBlockOffset.top + 30, 'left': cartBlockOffset.left + 705 }, 1000)
            .fadeOut(100, function() {
            ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
            });
            }
            else
            ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
            $('#add_to_cart button').val("Successfully Added!").css("background-color","#74bd00").delay(2000).queue(function(){
            $(this).val(addBtn_val).css("background-color","black");
            });
            },
            error: function(XMLHttpRequest, textStatus, errorThrown)
            {
            alert("Impossible to add the product to the cart.\n\ntextStatus: '" + textStatus + "'\nerrorThrown: '" + errorThrown + "'\nresponseText:\n" + XMLHttpRequest.responseText);













                            //reactive the button when adding has finished
                            if (addedFromProductPage)
                                $('#add_to_cart button').removeProp('disabled').removeClass('disabled');
                            else
                                $(callerElement).removeProp('disabled');
            }
            });
            },
            error: function(response)
            {
            alert("error: " + response.error);
            }
        });
        } else {
        alert("Please fill in the required fields");
        }
        } else {
            $(callerElement).attr('disabled', true);
        }
        if ($('#cart_block_list').hasClass('collapsed'))
        this.expand();
    },

    /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
    
    //remove a product from the cart via ajax
    remove : function(idProduct, idCombination, customizationId, idAddressDelivery){
        //send the ajax request to the server
        $.ajax({
            type: 'POST',
            headers: { "cache-control": "no-cache" },
            url: baseUri + '?rand=' + new Date().getTime(),
            async: true,
            cache: false,
            dataType : "json",
            data: 'controller=cart&delete=1&id_product=' + idProduct + '&ipa=' + ((idCombination != null && parseInt(idCombination)) ? idCombination : '') + ((customizationId && customizationId != null) ? '&id_customization=' + customizationId : '') + '&id_address_delivery=' + idAddressDelivery + '&token=' + static_token + '&ajax=true',
            success: function(jsonData)    {
                ajaxCart.updateCart(jsonData);
                if ($('body').attr('id') == 'order' || $('body').attr('id') == 'order-opc')
                    deleteProductFromSummary(idProduct+'_'+idCombination+'_'+customizationId+'_'+idAddressDelivery);
            },
            error: function()
            {
                var error = 'ERROR: unable to delete the product';
                if (!!$.prototype.fancybox)
                {
                    $.fancybox.open([
                        {
                            type: 'inline',
                            autoScale: true,
                            minHeight: 30,
                            content: error
                        }
                    ], {
                        padding: 0
                    });
                }
                else
                    alert(error);
            }
        });
    },

    //hide the products displayed in the page but no more in the json data
    hideOldProducts : function(jsonData){
        //delete an eventually removed product of the displayed cart (only if cart is not empty!)
        if ($('.cart_block_list:first dl.products').length > 0)
        {
            var removedProductId = null;
            var removedProductData = null;
            var removedProductDomId = null;
            //look for a product to delete...
            $('.cart_block_list:first dl.products dt').each(function(){
                //retrieve idProduct and idCombination from the displayed product in the block cart
                var domIdProduct = $(this).data('id');
                var firstCut = domIdProduct.replace('cart_block_product_', '');
                var ids = firstCut.split('_');

                //try to know if the current product is still in the new list
                var stayInTheCart = false;
                for (aProduct in jsonData.products)
                {
                    //we've called the variable aProduct because IE6 bug if this variable is called product
                    //if product has attributes
                    if (jsonData.products[aProduct]['id'] == ids[0] && (!ids[1] || jsonData.products[aProduct]['idCombination'] == ids[1]))
                    {
                        stayInTheCart = true;
                        // update the product customization display (when the product is still in the cart)
                        ajaxCart.hideOldProductCustomizations(jsonData.products[aProduct], domIdProduct);
                    }
                }
                //remove product if it's no more in the cart
                if (!stayInTheCart)
                {
                    removedProductId = $(this).data('id');
                    if (removedProductId != null)
                    {
                        var firstCut =  removedProductId.replace('cart_block_product_', '');
                        var ids = firstCut.split('_');

                        $('dt[data-id=' + removedProductId + ']').addClass('strike').fadeTo('slow', 0, function(){
                            $(this).slideUp('slow', function(){
                                $(this).remove();
                                // If the cart is now empty, show the 'no product in the cart' message and close detail
                                if($('.cart_block:first dl.products dt').length == 0)
                                {
                                    $("#header .cart_block").stop(true, true).slideUp(200);
                                    $('.cart_block_no_products:hidden').slideDown(450);
                                    $('.cart_block dl.products').remove();
                                }
                            });
                        });
                        $('dd[data-id="cart_block_combination_of_' + ids[0] + (ids[1] ? '_'+ids[1] : '') + (ids[2] ? '_'+ids[2] : '') + '"]').fadeTo('fast', 0, function(){
                            $(this).slideUp('fast', function(){
                                $(this).remove();
                            });
                        });
                    }
                }
            });
        }
    },

    hideOldProductCustomizations : function (product, domIdProduct){
        var customizationList = $('ul[data-id=customization_' + product['id] + '_' + product['idCombination'] + '"]');
        if(customizationList.length > 0)
        {
            $(customizationList).find("li").each(function(){
                $(this).find("div").each(function(){
                    var customizationDiv = $(this).data('id');
                    var tmp = customizationDiv.replace('deleteCustomizableProduct_', '');
                    var ids = tmp.split('_');
                    if ((parseInt(product.idCombination) == parseInt(ids[2])) && !ajaxCart.doesCustomizationStillExist(product, ids[0]))
                        $('div[data-id=' + customizationDiv + ']').parent().addClass('strike').fadeTo('slow', 0, function(){
                            $(this).slideUp('slow');
                            $(this).remove();
                        });
                });
            });
        }

        var removeLinks = $('.deleteCustomizableProduct[data-id=' + domIdProduct + ']').find('.ajax_cart_block_remove_link');
        if (!product.hasCustomizedDatas && !removeLinks.length)
            $('div[data-id=' + domIdProduct + ']' + ' span.remove_link').html('<a class="ajax_cart_block_remove_link" rel="nofollow" href="' + baseUri + '?controller=cart&delete=1&id_product=' + product['id'] + '&ipa=' + product['idCombination'] + '&token=' + static_token + '"> </a>');
        if (product.is_gift)
            $('div[data-id=' + domIdProduct + ']' + ' span.remove_link').html('');
    },

    doesCustomizationStillExist : function (product, customizationId){
        var exists = false;

        $(product.customizedDatas).each(function(){
            if (this.customizationId == customizationId)
            {
                exists = true;
                // This return does not mean that we found nothing but simply break the loop
                return false;
            }
        });
        return (exists);
    },

    //refresh display of vouchers (needed for vouchers in % of the total)
    refreshVouchers : function (jsonData){
        if (typeof(jsonData.discounts) == 'undefined' || jsonData.discounts.length == 0)
            $('.vouchers').hide();
        else
        {
            $('.vouchers tbody').html('');

            for (i=0;i<jsonData.discounts.length;i++)
            {
                if (parseFloat(jsonData.discounts.price_float) > 0)
                {
                    var delete_link = '';
                    if (jsonData.discounts.code.length)
                        delete_link = '<a class="delete_voucher" href="'+jsonData.discounts.link+'" title="'+delete_txt+'"><i class="icon-remove-sign"></i></a>';
                    $('.vouchers tbody').append($(
                        '<tr class="bloc_cart_voucher" data-id="bloc_cart_voucher_'+jsonData.discounts.id+'">'
                        +'    <td class="quantity">1x</td>'
                        +'    <td class="name" title="'+jsonData.discounts.description+'">'+jsonData.discounts.name+'</td>'
                        +'    <td class="price">-'+jsonData.discounts.price+'</td>'
                        +'    <td class="delete">' + delete_link + '</td>'
                        +'</tr>'
                    ));
                }
            }
            $('.vouchers').show();
        }

    },

    // Update product quantity
    updateProductQuantity : function (product, quantity){
        $('dt[data-id=cart_block_product_' + product.id + '_' + (product.idCombination ? product.idCombination : '0')+ '_' + (product.idAddressDelivery ? product.idAddressDelivery : '0') + '] .quantity').fadeTo('fast', 0, function(){
            $(this).text(quantity);
            $(this).fadeTo('fast', 1, function(){
                $(this).fadeTo('fast', 0, function(){
                    $(this).fadeTo('fast', 1, function(){
                        $(this).fadeTo('fast', 0, function(){
                            $(this).fadeTo('fast', 1);
                        });
                    });
                });
            });
        });
    },

    //display the products witch are in json data but not already displayed
    displayNewProducts : function(jsonData){
        //add every new products or update displaying of every updated products
        $(jsonData.products).each(function(){
            //fix ie6 bug (one more item 'undefined' in IE6)
            if (this.id != undefined)
            {
                //create a container for listing the products and hide the 'no product in the cart' message (only if the cart was empty)

                if ($('.cart_block:first dl.products').length == 0)
                {
                    $('.cart_block_no_products').before('<dl class="products"></dl>');
                    $('.cart_block_no_products').hide();
                }
                //if product is not in the displayed cart, add a new product's line
                var domIdProduct = this.id + '_' + (this.idCombination ? this.idCombination : '0') + '_' + (this.idAddressDelivery ? this.idAddressDelivery : '0');
                var domIdProductAttribute = this.id + '_' + (this.idCombination ? this.idCombination : '0');

                if ($('dt[data-id=cart_block_product_' + domIdProduct + ']').length == 0)
                {
                    var productId = parseInt(this.id);
                    var productAttributeId = (this.hasAttributes ? parseInt(this.attributes) : 0);
                    var content =  '<dt class="unvisible" data-id="cart_block_product_' + domIdProduct + '">';
                    var name = $.trim($('<span />').html(this.name).text());
                    name = (name.length > 12 ? name.substring(0, 10) + '...' : name);
                    content += '<a class="cart-images" href="' + this.link + '" title="' + name + '"><img  src="' + this.image_cart + '" alt="' + this.name +'"></a>';
                    content += '<div class="cart-info"><div class="product-name">' + '<span class="quantity-formated"><span class="quantity">' + this.quantity + '</span> x </span><a href="' + this.link + '" title="' + this.name + '" class="cart_block_product_name">' + name + '</a></div>';
                    if (this.hasAttributes)
                          content += '<div class="product-atributes"><a href="' + this.link + '" title="' + this.name + '">' + this.attributes + '</a></div>';
                    if (typeof(freeProductTranslation) != 'undefined')
                        content += '<span class="price">' + (parseFloat(this.price_float) > 0 ? this.priceByLine : freeProductTranslation) + '</span></div>';

                    if (typeof(this.is_gift) == 'undefined' || this.is_gift == 0)
                        content += '<span class="remove_link"><a rel="nofollow" class="ajax_cart_block_remove_link" href="' + baseUri + '?controller=cart&delete=1&id_product=' + productId + '&token=' + static_token + (this.hasAttributes ? '&ipa=' + parseInt(this.idCombination) : '') + '"> </a></span>';
                    else
                        content += '<span class="remove_link"></span>';
                    content += '</dt>';
                    if (this.hasAttributes)
                        content += '<dd data-id="cart_block_combination_of_' + domIdProduct + '" class="unvisible">';
                    if (this.hasCustomizedDatas)
                        content += ajaxCart.displayNewCustomizedDatas(this);
                    if (this.hasAttributes) content += '</dd>';

                    $('.cart_block dl.products').append(content);
                }
                //else update the product's line
                else
                {
                    var jsonProduct = this;
                    if($.trim($('dt[data-id=cart_block_product_' + domIdProduct + '] .quantity').html()) != jsonProduct.quantity || $.trim($('dt[data-id=cart_block_product_' + domIdProduct + '] .price').html()) != jsonProduct.priceByLine)
                    {
                        // Usual product
                        if (!this.is_gift)
                            $('dt[data-id=cart_block_product_' + domIdProduct + '] .price').text(jsonProduct.priceByLine);
                        else
                            $('dt[data-id=cart_block_product_' + domIdProduct + '] .price').html(freeProductTranslation);
                        ajaxCart.updateProductQuantity(jsonProduct, jsonProduct.quantity);

                        // Customized product
                        if (jsonProduct.hasCustomizedDatas)
                        {
                            customizationFormatedDatas = ajaxCart.displayNewCustomizedDatas(jsonProduct);
                            if (!$('ul[data-id=customization_' + domIdProductAttribute + ']').length)
                            {
                                if (jsonProduct.hasAttributes)
                                    $('dd[data-id=cart_block_combination_of_' + domIdProduct + ']').append(customizationFormatedDatas);
                                else
                                    $('.cart_block dl.products').append(customizationFormatedDatas);
                            }
                            else
                            {
                                $('ul[data-id=customization_' + domIdProductAttribute + ']').html('');
                                $('ul[data-id=customization_' + domIdProductAttribute + ']').append(customizationFormatedDatas);
                            }
                        }
                    }
                }
                $('.cart_block dl.products .unvisible').slideDown(450).removeClass('unvisible');

            var removeLinks = $('dt[data-id=cart_block_product_' + domIdProduct + ']').find('a.ajax_cart_block_remove_link');
            if (this.hasCustomizedDatas && removeLinks.length)
                $(removeLinks).each(function(){
                    $(this).remove();
                });
            }
        });
    },

    displayNewCustomizedDatas : function(product){
        var content = '';
        var productId = parseInt(product.id);
        var productAttributeId = typeof(product.idCombination) == 'undefined' ? 0 : parseInt(product.idCombination);
        var hasAlreadyCustomizations = $('ul[data-id=customization_' + productId + '_' + productAttributeId + ']').length;

        if (!hasAlreadyCustomizations)
        {
            if (!product.hasAttributes)
                content += '<dd data-id="cart_block_combination_of_' + productId + '" class="unvisible">';
            if ($('ul[data-id=customization_' + productId + '_' + productAttributeId + ']').val() == undefined)
                content += '<ul class="cart_block_customizations" data-id="customization_' + productId + '_' + productAttributeId + '">';
        }

        $(product.customizedDatas).each(function(){
            var done = 0;
            customizationId = parseInt(this.customizationId);
            productAttributeId = typeof(product.idCombination) == 'undefined' ? 0 : parseInt(product.idCombination);
            content += '<li name="customization"><div class="deleteCustomizableProduct" data-id="deleteCustomizableProduct_' + customizationId + '_' + productId + '_' + (productAttributeId ?  productAttributeId : '0') + '"><a rel="nofollow" class="ajax_cart_block_remove_link" href="' + baseUri + '?controller=cart&delete=1&id_product=' + productId + '&ipa=' + productAttributeId + '&id_customization=' + customizationId + '&token=' + static_token + '"></a></div>';

            // Give to the customized product the first textfield value as name
            $(this.datas).each(function(){
                if (this['type'] == CUSTOMIZE_TEXTFIELD)
                {
                    $(this.datas).each(function(){
                        if (this['index'] == 0)
                        {
                            content += ' ' + this.truncatedValue.replace(/<br \/>/g, ' ');
                            done = 1;
                            return false;
                        }
                    })
                }
            });

            // If the customized product did not have any textfield, it will have the customizationId as name
            if (!done)
                content += customizationIdMessage + customizationId;
            if (!hasAlreadyCustomizations) content += '</li>';
            // Field cleaning
            if (customizationId)
            {
                $('#uploadable_files li div.customizationUploadBrowse img').remove();
                $('#text_fields input').attr('value', '');
            }
        });

        if (!hasAlreadyCustomizations)
        {
            content += '</ul>';
            if (!product.hasAttributes) content += '</dd>';
        }
        return (content);
    },

    updateLayer : function(product){
        $('#layer_cart_product_title').text(product.name);
        $('#layer_cart_product_attributes').text('');
        if (product.hasAttributes && product.hasAttributes == true)
            $('#layer_cart_product_attributes').html(product.attributes);
        $('#layer_cart_product_price').text(product.price);
        $('#layer_cart_product_quantity').text(product.quantity);
        $('.layer_cart_img').html('<img class="layer_cart_img img-responsive" src="' + product.image + '" alt="' + product.name + '" title="' + product.name + '" />');

        var n = parseInt($(window).scrollTop()) + 'px';

        $('.layer_cart_overlay').css('width','100%');
        $('.layer_cart_overlay').css('height','100%');
        $('.layer_cart_overlay').show();
        $('#layer_cart').css({'top': n}).fadeIn('fast');
        crossselling_serialScroll();
    },

    //genarally update the display of the cart
    updateCart : function(jsonData){
        //user errors display
        if (jsonData.hasError)
        {
            var errors = '';
            for (error in jsonData.errors)
                //IE6 bug fix
                if (error != 'indexOf')
                    errors += $('<div />').html(jsonData.errors[error]).text() + "\n";
            if (!!$.prototype.fancybox)
                $.fancybox.open([
                    {
                        type: 'inline',
                        autoScale: true,
                        minHeight: 30,
                        content: '<p class="fancybox-error">' + errors + '</p>'
                    }
                ], {
                    padding: 0
                });
            else
                alert(errors);
        }
        else
        {
            ajaxCart.updateCartEverywhere(jsonData);
            ajaxCart.hideOldProducts(jsonData);
            ajaxCart.displayNewProducts(jsonData);
            ajaxCart.refreshVouchers(jsonData);

            //update 'first' and 'last' item classes
            $('.cart_block .products dt').removeClass('first_item').removeClass('last_item').removeClass('item');
            $('.cart_block .products dt:first').addClass('first_item');
            $('.cart_block .products dt:not(:first,:last)').addClass('item');
            $('.cart_block .products dt:last').addClass('last_item');
        }
    },

    //update general cart informations everywhere in the page
    updateCartEverywhere : function(jsonData){
        $('.ajax_cart_total').text($.trim(jsonData.productTotal));

        if (parseFloat(jsonData.shippingCostFloat) > 0)
            $('.ajax_cart_shipping_cost').text(jsonData.shippingCost);
        else if (typeof(freeShippingTranslation) != 'undefined')
                $('.ajax_cart_shipping_cost').html(freeShippingTranslation);

        $('.ajax_cart_tax_cost').text(jsonData.taxCost);
        $('.cart_block_wrapping_cost').text(jsonData.wrappingCost);
        $('.ajax_block_cart_total').text(jsonData.total);
        $('.ajax_block_products_total').text(jsonData.productTotal);
        $('.ajax_total_price_wt').text(jsonData.total_price_wt);

        if (parseFloat(jsonData.freeShippingFloat) > 0)
        {
            $('.ajax_cart_free_shipping').html(jsonData.freeShipping);
            $('.freeshipping').fadeIn(0);
        }
        else if (parseFloat(jsonData.freeShippingFloat) == 0)
            $('.freeshipping').fadeOut(0);

        this.nb_total_products = jsonData.nbTotalProducts;

        if (parseInt(jsonData.nbTotalProducts) > 0)
        {
            $('.ajax_cart_no_product').hide();
            $('.ajax_cart_quantity').text(jsonData.nbTotalProducts);
            $('.ajax_cart_quantity').fadeIn('slow');
            $('.ajax_cart_total').fadeIn('slow');

            if (parseInt(jsonData.nbTotalProducts) > 1)
            {
                $('.ajax_cart_product_txt').each( function (){
                    $(this).hide();
                });

                $('.ajax_cart_product_txt_s').each( function (){
                    $(this).show();
                });
            }
            else
            {
                $('.ajax_cart_product_txt').each( function (){
                    $(this).show();
                });

                $('.ajax_cart_product_txt_s').each( function (){
                    $(this).hide();
                });
            }
        }
        else
        {
            $('.ajax_cart_quantity, .ajax_cart_product_txt_s, .ajax_cart_product_txt, .ajax_cart_total').each(function(){
                $(this).hide();
            });
            $('.ajax_cart_no_product').show('slow');
        }
    }
};

function HoverWatcher(selector)
{
    this.hovering = false;
    var self = this;

    this.isHoveringOver = function(){
        return self.hovering;
    }

    $(selector).hover(function(){
        self.hovering = true;
    }, function(){
        self.hovering = false;
    })
}

function crossselling_serialScroll()
{
    if (!!$.prototype.bxSlider)
        $('#blockcart_caroucel').bxSlider({
            minSlides: 2,
            maxSlides: 4,
            slideWidth: 178,
            slideMargin: 20,
            moveSlides: 1,
            infiniteLoop: false,
              hideControlOnEnd: true,
            pager: false
        });
}

Edited by netark2 (see edit history)
Link to comment
Share on other sites

Solution for Prestashop 1.6.0.11 - AJAX CART no mod for core code aby fields in customization:

 

/*
* 2007-2015 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <[email protected]>
*  @copyright  2007-2015 PrestaShop SA
*  @license    http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/
$(document).ready(function(){





    ajaxCart.overrideButtonsInThePage();

    $(document).on('click', '.block_cart_collapse', function(e){
        e.preventDefault();
        ajaxCart.collapse();
    });
    $(document).on('click', '.block_cart_expand', function(e){
        e.preventDefault();
        ajaxCart.expand();
    });

    var cart_qty = 0;
    var current_timestamp = parseInt(new Date().getTime() / 1000);

    if (typeof $('.ajax_cart_quantity').html() == 'undefined' || (typeof generated_date != 'undefined' && generated_date != null && (parseInt(generated_date) + 30) < current_timestamp))
        ajaxCart.refresh();
    else
        cart_qty = parseInt($('.ajax_cart_quantity').html());

    /* roll over cart */
    var cart_block = new HoverWatcher('#header .cart_block');
    var shopping_cart = new HoverWatcher('#header .shopping_cart');
    var is_touch_enabled = false;

    if ('ontouchstart' in document.documentElement)
        is_touch_enabled = true;






    $(document).on('click', '#header .shopping_cart > a:first', function(e){




        e.preventDefault();
        e.stopPropagation();

        // Simulate hover when browser says device is touch based
        if (is_touch_enabled)
        {
            if ($(this).next('.cart_block:visible').length && !cart_block.isHoveringOver())
                $("#header .cart_block").stop(true, true).slideUp(450);
            else if (ajaxCart.nb_total_products > 0 || cart_qty > 0)
                $("#header .cart_block").stop(true, true).slideDown(450);

            return;
        }
        else
            window.location.href = $(this).attr('href');
    });

    $("#header .shopping_cart a:first").hover(
        function(){
            if (ajaxCart.nb_total_products > 0 || cart_qty > 0)
                $("#header .cart_block").stop(true, true).slideDown(450);
        },
        function(){
            setTimeout(function(){
                if (!shopping_cart.isHoveringOver() && !cart_block.isHoveringOver())
                    $("#header .cart_block").stop(true, true).slideUp(450);                
            }, 200);
        }
    );

    $("#header .cart_block").hover(
        function(){
        },
        function(){
            setTimeout(function(){
                if (!shopping_cart.isHoveringOver())
                    $("#header .cart_block").stop(true, true).slideUp(450);
            }, 200);
        }
    );

    $(document).on('click', '.delete_voucher', function(e){
        e.preventDefault();
        $.ajax({
            type: 'POST',
            headers: { "cache-control": "no-cache" },
            async: true,
            cache: false,
            url:$(this).attr('href') + '?rand=' + new Date().getTime()
        });
        $(this).parent().parent().remove();
        if ($('body').attr('id') == 'order' || $('body').attr('id') == 'order-opc')
        {
            if (typeof(updateAddressSelection) != 'undefined')
                updateAddressSelection();
            else
                location.reload();
        }
    });

    $(document).on('click', '#cart_navigation input', function(e){
        $(this).prop('disabled', 'disabled').addClass('disabled');
        $(this).closest("form").get(0).submit();
    });

    $(document).on('click', '#layer_cart .cross, #layer_cart .continue, .layer_cart_overlay', function(e){
        e.preventDefault();
        $('.layer_cart_overlay').hide();
        $('#layer_cart').fadeOut('fast');
    });
    
    $('#columns #layer_cart, #columns .layer_cart_overlay').detach().prependTo('#columns');
});

//JS Object : update the cart by ajax actions
var ajaxCart = {
    nb_total_products: 0,
    //override every button in the page in relation to the cart
    overrideButtonsInThePage : function(){
        //for every 'add' buttons...
        $(document).on('click', '.ajax_add_to_cart_button', function(e){
            e.preventDefault();
            var idProduct =  parseInt($(this).data('id-product'));
            var minimalQuantity =  parseInt($(this).data('minimal_quantity'));
            if (!minimalQuantity)
                minimalQuantity = 1;
            if ($(this).prop('disabled') != 'disabled')
                ajaxCart.add(idProduct, null, false, this, minimalQuantity);
        });
        //for product page 'add' button...
        $(document).on('click', '#add_to_cart button', function(e){
            e.preventDefault();
            ajaxCart.add($('#product_page_product_id').val(), $('#idCombination').val(), true, null, $('#quantity_wanted').val(), null);
        });

        //for 'delete' buttons in the cart block...
        $(document).on('click', '.cart_block_list .ajax_cart_block_remove_link', function(e){
            e.preventDefault();
            // Customized product management
            var customizationId = 0;
            var productId = 0;
            var productAttributeId = 0;
            var customizableProductDiv = $($(this).parent().parent()).find("div[data-id^=deleteCustomizableProduct_]");
            var idAddressDelivery = false;

            if (customizableProductDiv && $(customizableProductDiv).length)
            {
                var ids = customizableProductDiv.data('id').split('_');
                if (typeof(ids[1]) != 'undefined')
                {
                    customizationId = parseInt(ids[1]);
                    productId = parseInt(ids[2]);
                    if (typeof(ids[3]) != 'undefined')
                        productAttributeId = parseInt(ids[3]);
                    if (typeof(ids[4]) != 'undefined')
                        idAddressDelivery = parseInt(ids[4]);
                }
            }

            // Common product management
            if (!customizationId)
            {
                //retrieve idProduct and idCombination from the displayed product in the block cart
                var firstCut = $(this).parent().parent().data('id').replace('cart_block_product_', '');
                firstCut = firstCut.replace('deleteCustomizableProduct_', '');
                ids = firstCut.split('_');
                productId = parseInt(ids[0]);

                if (typeof(ids[1]) != 'undefined')
                    productAttributeId = parseInt(ids[1]);
                if (typeof(ids[2]) != 'undefined')
                    idAddressDelivery = parseInt(ids[2]);
            }

            // Removing product from the cart
            ajaxCart.remove(productId, productAttributeId, customizationId, idAddressDelivery);
        });
    },

    // try to expand the cart
    expand : function(){
        if ($('.cart_block_list').hasClass('collapsed'))
        {
            $('.cart_block_list.collapsed').slideDown({
                duration: 450,
                complete: function(){
                    $(this).parent().show(); // parent is hidden in global.js::accordion()
                    $(this).addClass('expanded').removeClass('collapsed');
                }
            });

            // save the expand statut in the user cookie
            $.ajax({
                type: 'POST',
                headers: { "cache-control": "no-cache" },
                url: baseDir + 'modules/blockcart/blockcart-set-collapse.php' + '?rand=' + new Date().getTime(),
                async: true,
                cache: false,
                data: 'ajax_blockcart_display=expand',
                complete: function(){
                    $('.block_cart_expand').fadeOut('fast', function(){
                        $('.block_cart_collapse').fadeIn('fast');
                    });
                }            
            });
        }
    },

    // try to collapse the cart
    collapse : function(){
        if ($('.cart_block_list').hasClass('expanded'))
        {
            $('.cart_block_list.expanded').slideUp('slow', function(){
                $(this).addClass('collapsed').removeClass('expanded');
            });

            // save the expand statut in the user cookie
            $.ajax({
                type: 'POST',
                headers: { "cache-control": "no-cache" },
                url: baseDir + 'modules/blockcart/blockcart-set-collapse.php' + '?rand=' + new Date().getTime(),
                async: true,
                cache: false,
                data: 'ajax_blockcart_display=collapse' + '&rand=' + new Date().getTime(),
                complete: function(){
                    $('.block_cart_collapse').fadeOut('fast', function(){
                        $('.block_cart_expand').fadeIn('fast');
                    });
                }
            });
        }
    },
    // Fix display when using back and previous browsers buttons
    refresh : function(){
        $.ajax({
            type: 'POST',
            headers: { "cache-control": "no-cache" },
            url: baseUri + '?rand=' + new Date().getTime(),
            async: true,
            cache: false,
            dataType : "json",
            data: 'controller=cart&ajax=true&token=' + static_token,
            success: function(jsonData)
            {
                ajaxCart.updateCart(jsonData);
            }
        });
    },

    // Update the cart information
    updateCartInformation : function (jsonData, addedFromProductPage){
        ajaxCart.updateCart(jsonData);
        //reactive the button when adding has finished
        if (addedFromProductPage)
        {
            $('#add_to_cart button').removeProp('disabled').removeClass('disabled');
            if (!jsonData.hasError || jsonData.hasError == false)
                $('#add_to_cart button').addClass('added');
            else
                $('#add_to_cart button').removeClass('added');
        }
        else
            $('.ajax_add_to_cart_button').removeProp('disabled');
    },
    // close fancybox
    updateFancyBox : function (){},
    // add a product in the cart via ajax

    /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
    add : function(idProduct, idCombination, addedFromProductPage, callerElement, quantity, whishlist) {

        var addBtn_val = $('#add_to_cart button').val();
        if (addedFromProductPage) {
            //button change, disable and do status text
            $('#add_to_cart button').prop('disabled', 'disabled').addClass('disabled');
            //$('#add_to_cart button').attr('disabled', true).removeClass('exclusive').addClass('exclusive_disabled').val("Processing...");
            $('.filled').removeClass('filled');
            
            //not depending on php backend to do validation but jquery
            $("form#customizationForm .customizationUploadLine :input").each(function() {
            
                if ($.trim($(this).val()).length == 0) {
                    $(this).css("border", "red 1px solid");
                    $form_verify = false;
                    $('#add_to_cart button').val(addBtn_val).removeAttr('disabled').addClass('exclusive').removeClass('exclusive_disabled');        
                } else {
                    $(this).removeAttr("style");
                    $(this).css("height", "30px");
                    $form_verify = true;
                }
            
            });
        
        
        if($form_verify) {
        var cform = $("form#customizationForm");
        var cform_data = cform.serialize();
        var cform_action = cform.attr("action");
        var cform_method = cform.attr("method");
        var cform_enctype = cform.attr("enctype");
        //use ajax send the customizationForm data, will still be successful even though there is error on PHP side.
        $.ajax({
        type: cform_method,
        headers: { "cache-control": "no-cache" },
        url: cform_action,
        cache: false,
        data: cform_data,
        success: function(response) {
        //when customizationForm is successfully submitted, proceed to adding product to cart
        emptyCustomizations();
        // adding product now
        $.ajax({
            type: 'POST',
            headers: { "cache-control": "no-cache" },
            url: baseUri + '?rand=' + new Date().getTime(),
            async: true,
            cache: false,
            dataType : "json",
            data: 'controller=cart&add=1&ajax=true&qty=' + ((quantity && quantity != null) ? quantity : '1') + '&id_product=' + idProduct + '&token=' + static_token + ( (parseInt(idCombination) && idCombination != null) ? '&ipa=' + parseInt(idCombination): ''),
            success: function(jsonData,textStatus,jqXHR)
            {
            
            // add appliance to whishlist module
            if (whishlist && !jsonData.errors)
            WishlistAddProductCart(whishlist[0], idProduct, idCombination, whishlist[1]);

            //== Pokazywanie okna po dodaniu do koszyka oraz wyczyszczenie listy z wgranymi fotkami
            /*----------------------------------------------------------------------------------------------------------------------*/
             if (!jsonData.hasError)
                {
                
                /*-----------------------------------------------------------------------------------------------------*/
                $('#add_to_cart').css('display','none !important');
                $('#add_to_cart button').val(addBtn_val).removeAttr('disabled').addClass('exclusive').removeClass('exclusive_disabled');    
                //$('#add_to_cart button').removeProp('disabled').removeClass('disabled');    
                $('#previews div').html('');
                $('.parameters_info').removeClass('show_parameters_info');
                /*-----------------------------------------------------------------------------------------------------*/
                
                    if (contentOnly) {
                        window.parent.ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
                        
                    } else {
                        ajaxCart.updateCartInformation(jsonData, addedFromProductPage);

                    }
                    if (jsonData.crossSelling)
                        $('.crossseling').html(jsonData.crossSelling);

                    if (idCombination)
                        $(jsonData.products).each(function(){
                            if (this.id != undefined && this.id == parseInt(idProduct) && this.idCombination == parseInt(idCombination))
                                if (contentOnly)
                                    window.parent.ajaxCart.updateLayer(this);    
                                else
                                    ajaxCart.updateLayer(this);
                        });
                    else
                        $(jsonData.products).each(function(){
                            if (this.id != undefined && this.id == parseInt(idProduct))
                                if (contentOnly)
                                    window.parent.ajaxCart.updateLayer(this);
                                else
                                    ajaxCart.updateLayer(this);                    
                        });
                    if (contentOnly)
                        parent.$.fancybox.close();

                        
                    
                } else {

                    if (contentOnly) {
                        window.parent.ajaxCart.updateCart(jsonData);
                    } else {
                        ajaxCart.updateCart(jsonData);    
                    }
                    if (addedFromProductPage) {
                        $('#add_to_cart button').val(addBtn_val).removeAttr('disabled').addClass('exclusive').removeClass('exclusive_disabled');    
                        //$('#add_to_cart button').removeProp('disabled').removeClass('disabled');                        
                    } else {
                        $(callerElement).removeProp('disabled');
                    }
                }

                /*----------------------------------------------------------------------------------------------------------------------*/
            // add the picture to the cart
            var $element = $(callerElement).parent().parent().find('a.product_image img,a.product_img_link img');
            if (!$element.length)
            $element = $('#bigpic');
            var $picture = $element.clone();
            var pictureOffsetOriginal = $element.offset();
            
            if ($picture.size())
            $picture.css({'position': 'absolute', 'top': pictureOffsetOriginal.top, 'left': pictureOffsetOriginal.left});
            
            var pictureOffset = $picture.offset();
            if ($('#cart_block')[0] && $('#cart_block').offset().top && $('#cart_block').offset().left)
            var cartBlockOffset = $('#cart_block').offset();
            else
            var cartBlockOffset = $('#shopping_cart').offset();
            
            // Check if the block cart is activated for the animation
            if (cartBlockOffset != undefined && $picture.size())
            {
            $picture.appendTo('body');
            $picture.css({ 'position': 'absolute', 'top': $picture.css('top'), 'left': $picture.css('left'), 'z-index': 4242 })
            .animate({ 'width': $element.attr('width')*0.66, 'height': $element.attr('height')*0.66, 'opacity': 0.2, 'top': cartBlockOffset.top + 30, 'left': cartBlockOffset.left + 705 }, 1000)
            .fadeOut(100, function() {
            ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
            });
            }
            else
            ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
            $('#add_to_cart button').val("Successfully Added!").css("background-color","#74bd00").delay(2000).queue(function(){
            $(this).val(addBtn_val).css("background-color","black");
            });
            },

                error: function(XMLHttpRequest, textStatus, errorThrown)
                {
                    alert("Impossible to add the product to the cart.\n\ntextStatus: '" + textStatus + "'\nerrorThrown: '" + errorThrown + "'\nresponseText:\n" + XMLHttpRequest.responseText);
                    
                    //reactive the button when adding has finished
                    if (addedFromProductPage)
                        $('#add_to_cart button').val(addBtn_val).removeAttr('disabled').addClass('exclusive').removeClass('exclusive_disabled');    
                        //$('#add_to_cart button').removeProp('disabled').removeClass('disabled');
                    else
                    $(callerElement).removeProp('disabled');
                }

            });
            },
            error: function(response)
            {
            alert("error: " + response.error);
            }
        });
        } else {
            alert("Please fill in the required fields");
        }
        } else {
            $(callerElement).attr('disabled', true);
        }
        if ($('#cart_block_list').hasClass('collapsed'))
        this.expand();
    },
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/


    //remove a product from the cart via ajax
    remove : function(idProduct, idCombination, customizationId, idAddressDelivery){
        //send the ajax request to the server
        $.ajax({
            type: 'POST',
            headers: { "cache-control": "no-cache" },
            url: baseUri + '?rand=' + new Date().getTime(),
            async: true,
            cache: false,
            dataType : "json",
            data: 'controller=cart&delete=1&id_product=' + idProduct + '&ipa=' + ((idCombination != null && parseInt(idCombination)) ? idCombination : '') + ((customizationId && customizationId != null) ? '&id_customization=' + customizationId : '') + '&id_address_delivery=' + idAddressDelivery + '&token=' + static_token + '&ajax=true',
            success: function(jsonData)    {
                ajaxCart.updateCart(jsonData);
                if ($('body').attr('id') == 'order' || $('body').attr('id') == 'order-opc')
                    deleteProductFromSummary(idProduct+'_'+idCombination+'_'+customizationId+'_'+idAddressDelivery);
            },
            error: function()
            {
                var error = 'ERROR: unable to delete the product';
                if (!!$.prototype.fancybox)
                {
                    $.fancybox.open([
                        {
                            type: 'inline',
                            autoScale: true,
                            minHeight: 30,
                            content: error
                        }
                    ], {
                        padding: 0
                    });
                }
                else
                    alert(error);
            }
        });
    },

    //hide the products displayed in the page but no more in the json data
    hideOldProducts : function(jsonData){
        //delete an eventually removed product of the displayed cart (only if cart is not empty!)
        if ($('.cart_block_list:first dl.products').length > 0)
        {
            var removedProductId = null;
            var removedProductData = null;
            var removedProductDomId = null;
            //look for a product to delete...
            $('.cart_block_list:first dl.products dt').each(function(){
                //retrieve idProduct and idCombination from the displayed product in the block cart
                var domIdProduct = $(this).data('id');
                var firstCut = domIdProduct.replace('cart_block_product_', '');
                var ids = firstCut.split('_');

                //try to know if the current product is still in the new list
                var stayInTheCart = false;
                for (aProduct in jsonData.products)
                {
                    //we've called the variable aProduct because IE6 bug if this variable is called product
                    //if product has attributes
                    if (jsonData.products[aProduct]['id'] == ids[0] && (!ids[1] || jsonData.products[aProduct]['idCombination'] == ids[1]))
                    {
                        stayInTheCart = true;
                        // update the product customization display (when the product is still in the cart)
                        ajaxCart.hideOldProductCustomizations(jsonData.products[aProduct], domIdProduct);
                    }
                }
                //remove product if it's no more in the cart
                if (!stayInTheCart)
                {
                    removedProductId = $(this).data('id');
                    if (removedProductId != null)
                    {
                        var firstCut =  removedProductId.replace('cart_block_product_', '');
                        var ids = firstCut.split('_');

                        $('dt[data-id=' + removedProductId + ']').addClass('strike').fadeTo('slow', 0, function(){
                            $(this).slideUp('slow', function(){
                                $(this).remove();
                                // If the cart is now empty, show the 'no product in the cart' message and close detail
                                if($('.cart_block:first dl.products dt').length == 0)
                                {
                                    $("#header .cart_block").stop(true, true).slideUp(200);
                                    $('.cart_block_no_products:hidden').slideDown(450);
                                    $('.cart_block dl.products').remove();
                                }
                            });
                        });
                        $('dd[data-id="cart_block_combination_of_' + ids[0] + (ids[1] ? '_'+ids[1] : '') + (ids[2] ? '_'+ids[2] : '') + '"]').fadeTo('fast', 0, function(){
                            $(this).slideUp('fast', function(){
                                $(this).remove();
                            });
                        });
                    }
                }
            });
        }
    },

    hideOldProductCustomizations : function (product, domIdProduct){
        var customizationList = $('ul[data-id=customization_' + product['id] + '_' + product['idCombination'] + '"]');
        if(customizationList.length > 0)
        {
            $(customizationList).find("li").each(function(){
                $(this).find("div").each(function(){
                    var customizationDiv = $(this).data('id');
                    var tmp = customizationDiv.replace('deleteCustomizableProduct_', '');
                    var ids = tmp.split('_');
                    if ((parseInt(product.idCombination) == parseInt(ids[2])) && !ajaxCart.doesCustomizationStillExist(product, ids[0]))
                        $('div[data-id=' + customizationDiv + ']').parent().addClass('strike').fadeTo('slow', 0, function(){
                            $(this).slideUp('slow');
                            $(this).remove();
                        });
                });
            });
        }

        var removeLinks = $('.deleteCustomizableProduct[data-id=' + domIdProduct + ']').find('.ajax_cart_block_remove_link');
        if (!product.hasCustomizedDatas && !removeLinks.length)
            $('div[data-id=' + domIdProduct + ']' + ' span.remove_link').html('<a class="ajax_cart_block_remove_link" rel="nofollow" href="' + baseUri + '?controller=cart&delete=1&id_product=' + product['id'] + '&ipa=' + product['idCombination'] + '&token=' + static_token + '"> </a>');
        if (product.is_gift)
            $('div[data-id=' + domIdProduct + ']' + ' span.remove_link').html('');
    },

    doesCustomizationStillExist : function (product, customizationId){
        var exists = false;

        $(product.customizedDatas).each(function(){
            if (this.customizationId == customizationId)
            {
                exists = true;
                // This return does not mean that we found nothing but simply break the loop
                return false;
            }
        });
        return (exists);
    },

    //refresh display of vouchers (needed for vouchers in % of the total)
    refreshVouchers : function (jsonData){
        if (typeof(jsonData.discounts) == 'undefined' || jsonData.discounts.length == 0)
            $('.vouchers').hide();
        else
        {
            $('.vouchers tbody').html('');

            for (i=0;i<jsonData.discounts.length;i++)
            {
                if (parseFloat(jsonData.discounts.price_float) > 0)
                {
                    var delete_link = '';
                    if (jsonData.discounts.code.length)
                        delete_link = '<a class="delete_voucher" href="'+jsonData.discounts.link+'" title="'+delete_txt+'"><i class="icon-remove-sign"></i></a>';
                    $('.vouchers tbody').append($(
                        '<tr class="bloc_cart_voucher" data-id="bloc_cart_voucher_'+jsonData.discounts.id+'">'
                        +'    <td class="quantity">1x</td>'
                        +'    <td class="name" title="'+jsonData.discounts.description+'">'+jsonData.discounts.name+'</td>'
                        +'    <td class="price">-'+jsonData.discounts.price+'</td>'
                        +'    <td class="delete">' + delete_link + '</td>'
                        +'</tr>'
                    ));
                }
            }
            $('.vouchers').show();
        }

    },

    // Update product quantity
    updateProductQuantity : function (product, quantity){
        $('dt[data-id=cart_block_product_' + product.id + '_' + (product.idCombination ? product.idCombination : '0')+ '_' + (product.idAddressDelivery ? product.idAddressDelivery : '0') + '] .quantity').fadeTo('fast', 0, function(){
            $(this).text(quantity);
            $(this).fadeTo('fast', 1, function(){
                $(this).fadeTo('fast', 0, function(){
                    $(this).fadeTo('fast', 1, function(){
                        $(this).fadeTo('fast', 0, function(){
                            $(this).fadeTo('fast', 1);
                        });
                    });
                });
            });
        });
    },

    //display the products witch are in json data but not already displayed
    displayNewProducts : function(jsonData){
        //add every new products or update displaying of every updated products
        $(jsonData.products).each(function(){
            //fix ie6 bug (one more item 'undefined' in IE6)
            if (this.id != undefined)
            {
                //create a container for listing the products and hide the 'no product in the cart' message (only if the cart was empty)

                if ($('.cart_block:first dl.products').length == 0)
                {
                    $('.cart_block_no_products').before('<dl class="products"></dl>');
                    $('.cart_block_no_products').hide();
                }
                //if product is not in the displayed cart, add a new product's line
                var domIdProduct = this.id + '_' + (this.idCombination ? this.idCombination : '0') + '_' + (this.idAddressDelivery ? this.idAddressDelivery : '0');
                var domIdProductAttribute = this.id + '_' + (this.idCombination ? this.idCombination : '0');

                if ($('dt[data-id=cart_block_product_' + domIdProduct + ']').length == 0)
                {
                    var productId = parseInt(this.id);
                    var productAttributeId = (this.hasAttributes ? parseInt(this.attributes) : 0);
                    var content =  '<dt class="unvisible" data-id="cart_block_product_' + domIdProduct + '">';
                    var name = $.trim($('<span />').html(this.name).text());
                    name = (name.length > 12 ? name.substring(0, 10) + '...' : name);
                    content += '<a class="cart-images" href="' + this.link + '" title="' + name + '"><img  src="' + this.image_cart + '" alt="' + this.name +'"></a>';
                    content += '<div class="cart-info"><div class="product-name">' + '<span class="quantity-formated"><span class="quantity">' + this.quantity + '</span> x </span><a href="' + this.link + '" title="' + this.name + '" class="cart_block_product_name">' + name + '</a></div>';
                    if (this.hasAttributes)
                          content += '<div class="product-atributes"><a href="' + this.link + '" title="' + this.name + '">' + this.attributes + '</a></div>';
                    if (typeof(freeProductTranslation) != 'undefined')
                        content += '<span class="price">' + (parseFloat(this.price_float) > 0 ? this.priceByLine : freeProductTranslation) + '</span></div>';

                    if (typeof(this.is_gift) == 'undefined' || this.is_gift == 0)
                        content += '<span class="remove_link"><a rel="nofollow" class="ajax_cart_block_remove_link" href="' + baseUri + '?controller=cart&delete=1&id_product=' + productId + '&token=' + static_token + (this.hasAttributes ? '&ipa=' + parseInt(this.idCombination) : '') + '"> </a></span>';
                    else
                        content += '<span class="remove_link"></span>';
                    content += '</dt>';
                    if (this.hasAttributes)
                        content += '<dd data-id="cart_block_combination_of_' + domIdProduct + '" class="unvisible">';
                    if (this.hasCustomizedDatas)
                        content += ajaxCart.displayNewCustomizedDatas(this);
                    if (this.hasAttributes) content += '</dd>';

                    $('.cart_block dl.products').append(content);
                }
                //else update the product's line
                else
                {
                    var jsonProduct = this;
                    if($.trim($('dt[data-id=cart_block_product_' + domIdProduct + '] .quantity').html()) != jsonProduct.quantity || $.trim($('dt[data-id=cart_block_product_' + domIdProduct + '] .price').html()) != jsonProduct.priceByLine)
                    {
                        // Usual product
                        if (!this.is_gift)
                            $('dt[data-id=cart_block_product_' + domIdProduct + '] .price').text(jsonProduct.priceByLine);
                        else
                            $('dt[data-id=cart_block_product_' + domIdProduct + '] .price').html(freeProductTranslation);
                        ajaxCart.updateProductQuantity(jsonProduct, jsonProduct.quantity);

                        // Customized product
                        if (jsonProduct.hasCustomizedDatas)
                        {
                            customizationFormatedDatas = ajaxCart.displayNewCustomizedDatas(jsonProduct);
                            if (!$('ul[data-id=customization_' + domIdProductAttribute + ']').length)
                            {
                                if (jsonProduct.hasAttributes)
                                    $('dd[data-id=cart_block_combination_of_' + domIdProduct + ']').append(customizationFormatedDatas);
                                else
                                    $('.cart_block dl.products').append(customizationFormatedDatas);
                            }
                            else
                            {
                                $('ul[data-id=customization_' + domIdProductAttribute + ']').html('');
                                $('ul[data-id=customization_' + domIdProductAttribute + ']').append(customizationFormatedDatas);
                            }
                        }
                    }
                }
                $('.cart_block dl.products .unvisible').slideDown(450).removeClass('unvisible');

            var removeLinks = $('dt[data-id=cart_block_product_' + domIdProduct + ']').find('a.ajax_cart_block_remove_link');
            if (this.hasCustomizedDatas && removeLinks.length)
                $(removeLinks).each(function(){
                    $(this).remove();
                });
            }
        });
    },

    displayNewCustomizedDatas : function(product){
        var content = '';
        var productId = parseInt(product.id);
        var productAttributeId = typeof(product.idCombination) == 'undefined' ? 0 : parseInt(product.idCombination);
        var hasAlreadyCustomizations = $('ul[data-id=customization_' + productId + '_' + productAttributeId + ']').length;

        if (!hasAlreadyCustomizations)
        {
            if (!product.hasAttributes)
                content += '<dd data-id="cart_block_combination_of_' + productId + '" class="unvisible">';
            if ($('ul[data-id=customization_' + productId + '_' + productAttributeId + ']').val() == undefined)
                content += '<ul class="cart_block_customizations" data-id="customization_' + productId + '_' + productAttributeId + '">';
        }

        $(product.customizedDatas).each(function(){
            var done = 0;
            customizationId = parseInt(this.customizationId);
            productAttributeId = typeof(product.idCombination) == 'undefined' ? 0 : parseInt(product.idCombination);
            content += '<li name="customization"><div class="deleteCustomizableProduct" data-id="deleteCustomizableProduct_' + customizationId + '_' + productId + '_' + (productAttributeId ?  productAttributeId : '0') + '"><a rel="nofollow" class="ajax_cart_block_remove_link" href="' + baseUri + '?controller=cart&delete=1&id_product=' + productId + '&ipa=' + productAttributeId + '&id_customization=' + customizationId + '&token=' + static_token + '"></a></div>';

            // Give to the customized product the first textfield value as name
            $(this.datas).each(function(){
                if (this['type'] == CUSTOMIZE_TEXTFIELD)
                {
                    $(this.datas).each(function(){
                        if (this['index'] == 0)
                        {
                            content += ' ' + this.truncatedValue.replace(/<br \/>/g, ' ');
                            done = 1;
                            return false;
                        }
                    })
                }
            });

            // If the customized product did not have any textfield, it will have the customizationId as name
            if (!done)
                content += customizationIdMessage + customizationId;
            if (!hasAlreadyCustomizations) content += '</li>';
            // Field cleaning
            if (customizationId)
            {
                $('#uploadable_files li div.customizationUploadBrowse img').remove();
                $('#text_fields input').attr('value', '');
            }
        });

        if (!hasAlreadyCustomizations)
        {
            content += '</ul>';
            if (!product.hasAttributes) content += '</dd>';
        }
        return (content);
    },

    updateLayer : function(product){
        $('#layer_cart_product_title').text(product.name);
        $('#layer_cart_product_attributes').text('');
        if (product.hasAttributes && product.hasAttributes == true)
            $('#layer_cart_product_attributes').html(product.attributes);
        $('#layer_cart_product_price').text(product.price);
        $('#layer_cart_product_quantity').text(product.quantity);
        $('.layer_cart_img').html('<img class="layer_cart_img img-responsive" src="' + product.image + '" alt="' + product.name + '" title="' + product.name + '" />');

        var n = parseInt($(window).scrollTop()) + 'px';

        $('.layer_cart_overlay').css('width','100%');
        $('.layer_cart_overlay').css('height','100%');
        $('.layer_cart_overlay').show();
        $('#layer_cart').css({'top': n}).fadeIn('fast');
        crossselling_serialScroll();
    },

    //genarally update the display of the cart
    updateCart : function(jsonData){
        //user errors display
        if (jsonData.hasError)
        {
            var errors = '';
            for (error in jsonData.errors)
                //IE6 bug fix
                if (error != 'indexOf')
                    errors += $('<div />').html(jsonData.errors[error]).text() + "\n";
            if (!!$.prototype.fancybox)
                $.fancybox.open([
                    {
                        type: 'inline',
                        autoScale: true,
                        minHeight: 30,
                        content: '<p class="fancybox-error">' + errors + '</p>'
                    }
                ], {
                    padding: 0
                });
            else
                alert(errors);
        }
        else
        {
            ajaxCart.updateCartEverywhere(jsonData);
            ajaxCart.hideOldProducts(jsonData);
            ajaxCart.displayNewProducts(jsonData);
            ajaxCart.refreshVouchers(jsonData);

            //update 'first' and 'last' item classes
            $('.cart_block .products dt').removeClass('first_item').removeClass('last_item').removeClass('item');
            $('.cart_block .products dt:first').addClass('first_item');
            $('.cart_block .products dt:not(:first,:last)').addClass('item');
            $('.cart_block .products dt:last').addClass('last_item');
        }
    },

    //update general cart informations everywhere in the page
    updateCartEverywhere : function(jsonData){
        $('.ajax_cart_total').text($.trim(jsonData.productTotal));

        if (parseFloat(jsonData.shippingCostFloat) > 0)
            $('.ajax_cart_shipping_cost').text(jsonData.shippingCost);
        else if (typeof(freeShippingTranslation) != 'undefined')
                $('.ajax_cart_shipping_cost').html(freeShippingTranslation);

        $('.ajax_cart_tax_cost').text(jsonData.taxCost);
        $('.cart_block_wrapping_cost').text(jsonData.wrappingCost);
        $('.ajax_block_cart_total').text(jsonData.total);
        $('.ajax_block_products_total').text(jsonData.productTotal);
        $('.ajax_total_price_wt').text(jsonData.total_price_wt);

        if (parseFloat(jsonData.freeShippingFloat) > 0)
        {
            $('.ajax_cart_free_shipping').html(jsonData.freeShipping);
            $('.freeshipping').fadeIn(0);
        }
        else if (parseFloat(jsonData.freeShippingFloat) == 0)
            $('.freeshipping').fadeOut(0);

        this.nb_total_products = jsonData.nbTotalProducts;

        if (parseInt(jsonData.nbTotalProducts) > 0)
        {
            $('.ajax_cart_no_product').hide();
            $('.ajax_cart_quantity').text(jsonData.nbTotalProducts);
            $('.ajax_cart_quantity').fadeIn('slow');
            $('.ajax_cart_total').fadeIn('slow');

            if (parseInt(jsonData.nbTotalProducts) > 1)
            {
                $('.ajax_cart_product_txt').each( function (){
                    $(this).hide();
                });

                $('.ajax_cart_product_txt_s').each( function (){
                    $(this).show();
                });
            }
            else
            {
                $('.ajax_cart_product_txt').each( function (){
                    $(this).show();
                });

                $('.ajax_cart_product_txt_s').each( function (){
                    $(this).hide();
                });
            }
        }
        else
        {
            $('.ajax_cart_quantity, .ajax_cart_product_txt_s, .ajax_cart_product_txt, .ajax_cart_total').each(function(){
                $(this).hide();
            });
            $('.ajax_cart_no_product').show('slow');
        }
    }
};

function HoverWatcher(selector)
{
    this.hovering = false;
    var self = this;

    this.isHoveringOver = function(){
        return self.hovering;
    }

    $(selector).hover(function(){
        self.hovering = true;
    }, function(){
        self.hovering = false;
    })
}

function crossselling_serialScroll()
{
    if (!!$.prototype.bxSlider)
        $('#blockcart_caroucel').bxSlider({
            minSlides: 2,
            maxSlides: 4,
            slideWidth: 178,
            slideMargin: 20,
            moveSlides: 1,
            infiniteLoop: false,
              hideControlOnEnd: true,
            pager: false
        });
}

  • Like 2
Link to comment
Share on other sites

  • 4 weeks later...
  • 1 month later...
  • 2 weeks later...

Hello i used your modified code for prestashop 1.6.0.14 but i have the same problem with @bomby the button keeps spinning. I have some console errors if this is enough to find the issue. (see attached screenshot)

 

 

 

 

 

post-725080-0-82785800-1429001045_thumb.png

Link to comment
Share on other sites

I advise all people here to buy zelarg's perfect one page checkout button. it is worth the €39 you spend. perfect support too, he'll solve your problems via email.

 

Hi cagrie thanks for info, but i would like to have a "free" solution if is possible. Mainly my issue is that i have made the customtext field required, but even when i put something in the textarea, after i press the save button got the error that i have to fill in all the required fields! I am 100% sure that i have no other required fields. Is this a known issue?

 

Best Regards

Edited by wiseprt (see edit history)
Link to comment
Share on other sites

URL of shop please :) I make test ok?

 

 

When I click on "Add to cart", the ajax loading button appears and it keeps spinning - while the page is not loading. nothing is saved/added to cart.

 
I have the same problem can you help me ?
 
thanks
Link to comment
Share on other sites

  • 2 months later...

 

When I click on "Add to cart", the ajax loading button appears and it keeps spinning - while the page is not loading. nothing is saved/added to cart.

 
I have the same problem can you help me ?
 
thanks

 

 

cut and copy before and after line

 

/*----------------------------------------------------------------------------------------------*/

 

to desired function in JS file

Link to comment
Share on other sites

  • 3 weeks later...

Hi All

 

I have carried out the steps in post #133, but the strange thing is works once then cannot be repeated the second time. I have to delete the files then ftp them again and it works!

 

Ideally I am looking for an Ajax-cart turned on solution but my prestashop version is 1.6.0.14.

 

Critically important this can work, as my products require personalised labels and the save button is an extra step the customer doesnt need.

 

Thanks in advance

Link to comment
Share on other sites

Hi

 

I also have the same problem as the previous poster.

 

The solution works, but I can only add one product to the cart. If I add a personalized product and then try to add another normal product to the cart, it will not let me.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...