On 8/19/2014 at 2:54 PM, defuzed said: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=1185115 ) work 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.
I had to try something like this because inline javascript in my previous post got cached along with the previous customers' text; it might work for file uploads but not text. People would buy the order from the customer before. Instead, this method changes a cartcontroller.php file including some code to check that this is a current cart. The new file sits in a slot for over-rides, that doesn't get updated like the rest of the code:
/override/controllers/front/CartController.php
I have not got it working with attributes like size and color. They stop working when I install this, so I need to use it only on products that have no normal attributes, using a separate template which is possible in Thirtybees.
I have not tested with quantity.
<?php /* * 2007-2012 PrestaShop 1.5.3.1 source * * NOTICE OF LICENSE * * This override removes the need to submit customization * as a separate step. It's from shamun's post (#124) on page 7 of this thread: * http://www.prestashop.com/forums/index.php?/topic/76874-how-to-remove-save-button-for-customized-fields/page__view__findpost__p__1054781 */ 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('Product is no longer available.', false); return; } /* Added to allow for customizations without saving. Almost the same as from ProductController. Image removed. */ if (Tools::isSubmit('submitCustomizedDatas')) { // If cart has not been saved, we need to do it so that customization fields can have an id_cart // We check that the cookie exists first to avoid ghost carts if (!$this->context->cart->id && isset($_COOKIE[$this->context->cookie->getName()])) { $this->context->cart->add(); $this->context->cookie->id_cart = (int)$this->context->cart->id; } $this->textRecord($product); } /* End customization without saving */ // 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 is not 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 is not enough product in stock.'); } else if (!$product->checkQty($this->qty)) $this->errors[] = Tools::displayError('There is not 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) { $this->context->cart->add(); if ($this->context->cart->id) $this->context->cookie->id_cart = (int)$this->context->cart->id; } // Check customizable fields if (!$product->hasAllRequiredCustomizableFields() && !$this->customization_id) $this->errors[] = Tools::displayError('Please fill in all required fields, then save the customization.'); 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(); if (count($removed) && (int)Tools::getValue('allow_refresh')) $this->ajax_refresh = true; } /* Allows addition of customized text inputs without saving. Modified parts: Method now requires an input. The input needs to be the $product ! Replaced $this->product-> with $product-> */ protected function textRecord($product) { if (!$field_ids = $product->getCustomizationFieldIds()) return false; $authorized_text_fields = array(); 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']; $indexes = array_flip($authorized_text_fields); foreach ($_POST as $field_name => $value) if (in_array($field_name, $authorized_text_fields) && !empty($value)) { if (!Validate::isMessage($value)) $this->errors[] = Tools::displayError('Invalid message'); else $this->context->cart->addTextFieldToProduct($product->id, $indexes[$field_name], Product::CUSTOMIZE_TEXTFIELD, $value); } else if (in_array($field_name, $authorized_text_fields) && empty($value)) $this->context->cart->deleteCustomizationToProduct((int)$product->id, $indexes[$field_name]); } }
There is still a default customization block at the bottom of the page. I suppose I should comment it out and maybe experiment using its code instead of the transplanted code, in case one is better than another.
So I had a look back through the thread and found the quote above, turned off ajax, logged-on to this message board so I could download the zipfile with a cartcontroller.php override and a product.tpl template, and it sort of worked. I have a test site on a server; found the "Themes" section and my theme, found product.tpl in there and just edited it to add the new text.
I am on the Thirtybees fork of PS1.6 that uses Niara theme; the template file is from PS 1.5.3.1, and formatting didn't work in my version. Photos. Layout. Luckily, Rhapsody has labelled the changes in his template. He has a block of code for a moved customization form, and he has put it somewhere inside the <form> </form> tag of the order form. So I reverted to my default product.tpl file (cut and pasted from github onto my server) and added the block of code. It worked. He put it just before the closing </form> but it will probably work higher-up the page. His code avoids the
The block of code looks like this.
{* Rhapsody Moved customization block below *} <!-- Customizable products --> {if isset($product) && $product->customizable} <ul id="more_info_tabs" class="idTabs idTabsShort clearfix"> <div id="idTab10" class="bullet customization_block"> {$HOOK_PRODUCT_TAB} </ul> {* Rhapsody comment out this section <form method="post" action="{$customizationFormTarget}" enctype="multipart/form-data" id="customizationForm" class="clearfix"> <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> Rhapsody Commented out *} {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 hard drive'}{/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='Type your text in the blanks below'}</h3> <ul id="text_fields"> <p class="clear required"><sup>*</sup> {l s='Mandatory entry fields have red labels'}</p> {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 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" /> {* 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> {/if} {* Rhapsody moved customization block above *}
I suppose I should now work out where to paste it as an over-ride, so that next time the site automatically updates, this page won't be changed. Or maybe use the free DH42 module that allows you to have custom code for a template controlled from the back office.