+34 687 770 998 hector.ayestaran@gmail.com





Blog


15
SEPT
2015

Prestashop: Cómo mover las propiedades de personalización de un producto al formulario del botón Añadir al Carrito

El objetivo de este artículo es conseguir que los campos personalizables de nuestros productos en Prestashop sean movidos al formulario principal, aquel donde se sitúa el botón para añadir el producto a la cesta de la compra, añadiendo así, de un solo clic, producto y datos introducidos por el usuario.

Prestashop: Moviendo atributos personalizables Prestashop: Moviendo atributos personalizables

Utilizaremos el tema default-bootstrap y la versión 1.6.0.14 de Prestashop como base. Marcaré con el signo "+" lo que haya que añadir, y con el "-" lo que haya que quitar.

Lo primero que haremos será modificar la validación de los campos personalizables de manera que nos detecte los cambios que vamos a introducir. Para ello iremos al documento /js/tools.js y modificaremos la función checkCustomizations:


	function checkCustomizations() 
	{
		var pattern = new RegExp(' ?filled ?');

		if (typeof customizationFields != 'undefined')
			for (var i = 0; i < customizationFields.length; i++)
			{
				/* If the field is required and empty then we abort */
				+ if (parseInt(customizationFields[i][1]) == 1 && $('#' + customizationFields[i][0] +'_addToCart').val() == '')
				- if (parseInt(customizationFields[i][1]) == 1 && ($('#' + customizationFields[i][0]).html() == '' ||  $('#' + customizationFields[i][0]).text() != $('#' + customizationFields[i][0]).val()) && !pattern.test($('#' + customizationFields[i][0]).attr('class')))
					return false;
			}
		return true;
	}

Acto seguido ocultaremos los campos personalizables que aparecen en la parte baja de la ficha del producto. Abriremos el documento /themes/default-bootstrap/product.tpl y en la línea 565 (más o menos) sustituiremos el siguiente código:


	{if isset($product) && $product->customizable}
	<!--Customization -->
	+ <section class="page-product-box" style="visibility:hidden">
	- <section class="page-product-box">

Lo siguiente será que Prestashop nos genere esos campos en la nueva ubicación, justo encima del botón Añadir al Carrito. Iremos a la línea 379 y añadiremos el siguiente bloque de código:


			{/foreach}

			++++++++++
			<fieldset class="attribute_fieldset">
				 {counter start=0 assign='customizationField'}
				 {foreach from=$customizationFields item='field' name='customizationFields'}
					  {if $field.type == 1}
							<label class="attribute_label {if $field.required}{/if}" 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 name="textField{$field.id_customization_field}" class="form-control customization_block_input" id="textField{$customizationField}_addToCart" rows="3" cols="20">{strip}
								 {if isset($textFields.$key)}
									  {$textFields.$key|stripslashes}
								 {/if}
							{/strip}</textarea>
							{counter}
					  {/if}
				 {/foreach}
			</fieldset>
			++++++++++

		</div> <!-- end attributes -->
	{/if}
</div> <!-- end product_attributes -->

Finalmente añadiremos un par de métodos a la lógica javascript que guarda los datos personalizables. Uno de ellos enviará por ajax dichos valores en el momento de pulsar el botón Añadir al Carrito.
Editaremos el documento /themes/default-bootstrap/js/modules/blockcart/ajax-cart.js y en la línea 123 añadiremos los métodos:

	
	++++++++++

	// muestra el aviso de campos personalizables obligatorios
	// invocado en "ajaxCart.add" y "addToCart"
	var fieldsRequired = function() {
		 if (!!$.prototype.fancybox)
			  $.fancybox.open([
					{
						 type: 'inline',
						 autoScale: true,
						 minHeight: 30,
						 content: '<p class="fancybox-error">' + fieldRequired + '</p>'
					}
			  ], {
					padding: 0
			  });
		 else
			  alert(fieldRequired);  
	};

	// invocado en "ajaxCart.overrideButtonsInThePage"
	var addToCart = function() {

		 var i = 0;
		 var fields = {};

		 // guarda el producto
		 var init = function() {
			  ajaxCart.add($('#product_page_product_id').val(), $('#idCombination').val(), true, null, $('#quantity_wanted').val(), null);
		 };

		 // si campos personalizables obligatorios y no completados, mostramos el aviso
		 // function checkCustomizations: modificado en /js/tools.js
		 if(!checkCustomizations()) {
			  fieldsRequired();
			  return;
		 }

		 // si no hay campos personalizables, guardamos al producto en la cesta
		 if(typeof customizationFields=='undefined' || !customizationFields.length) {
			  init();
			  return;
		 }

		 // campos para el post ajax de guardado de campos personalizables
		 fields.quantityBackup = $('#quantity_wanted').val();
		 fields.submitCustomizedDatas = 1;
		 fields.saveCustomization = 1;

		 // creamos los campos personalizables para el post
		 while($('#textField'+ i).length) { 
			  eval("fields."+ $('#textField'+ i).attr('name') +" = $('#textField"+ i +"_addToCart').val();");
			  i++;
		 }

		 // ponemos el botón de guardar en modo throbber
		 $('#add_to_cart button').addClass('disabled');
		 $('#add_to_cart button').prop('disabled', true);

		 // quitamos el aviso de error si lo hay
		 $('#pCustomizationError').fadeOut();

		 // guardamos los campos personalizables
		 $.post(
			  $('#customizationForm').attr('action'), 
			  fields,

			  function(data, status){ 
					// si error
					if(status != 'success') {
						 // restablecemos el botón de guardar
						 $('#add_to_cart button').removeClass('disabled');
						 $('#add_to_cart button').prop('disabled', false);
						 // mostramos el aviso de error
						 $('#pCustomizationError').fadeIn();
						 // y salimos
						 return;
					}

					console.log([data, status]);

					// si todo ok, guardamos el producto
					init();
			  }
		 );
	};

	+++++++++++

	//JS Object : update the cart by ajax actions
	var ajaxCart = {

En la línea 227 sustituiremos el siguiente código:

	//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).off('click', '.ajax_add_to_cart_button').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).off('click', '#add_to_cart button').on('click', '#add_to_cart button', function(e){
				e.preventDefault();
				+ addToCart();
				- ajaxCart.add($('#product_page_product_id').val(), $('#idCombination').val(), true, null, $('#quantity_wanted').val(), null);
			});

Como algo adicional, si queremos eliminar redundancias en el código, podemos sustituir varias líneas por una simple llamada. No es obligatorio, el botón funcionará igual.


	// add a product in the cart via ajax
	add : function(idProduct, idCombination, addedFromProductPage, callerElement, quantity, whishlist){
		if (addedFromProductPage && !checkCustomizations())
		{
			if (contentOnly)
			{
				var productUrl = window.document.location.href + '';
				var data = productUrl.replace('content_only=1', '');
				window.parent.document.location.href = data;
				return;
			}
			-----------
			if (!!$.prototype.fancybox)
			    $.fancybox.open([
			        {
			            type: 'inline',
			            autoScale: true,
			            minHeight: 30,
			            content: '<p class="fancybox-error">' + fieldRequired + '</p>'
			        }
			    ], {
			        padding: 0
			    });
			else
			    alert(fieldRequired);
			-----------
			+ fieldsRequired();
            return;
		}

Bueno, y eso es todo.

Volver