Pestañas en la ficha de producto como las de Prestashop 1.5

02 noviembre, 2014 |

Si te gusta, compártelo ;)

En Prestashop 1.6, en la página de "Detalles de producto" vemos pestañas con información sobre la ficha técnica del producto, para añadir información sobre el producto etc..., pues bien, estas pestañas no presentan el mismo aspecto ni la misma funcionalidad que en Prestashop 1.5, es por ello que vamos a recuperar las características de las pestañas de Prestashop 1.5, que en mi opinión son bastante mejores. Este aspecto presentan en Prestashop 1.6:

Pestañas en la ficha de producto de Prestashop 1.6

Y las queremos así:

Pestañas ficha de producto como en Prestashop 1.5

Tendremos que modificar dos archivos. El primero de ellos es el archivo prestashop/themes/nuestro-tema/product.tpl. El segundo es el archivo prestashop/themes/nuestro-tema/css/global.css

Modificando el archivo product.tpl

Vamos con el primero de ellos, product.tpl; debemos buscar este código y borrarlo:

{if isset($features) && $features}
<!-- Data sheet -->
<section class="page-product-box">
<h3 class="page-product-heading">{l s='Data sheet'}</h3>
<table class="table-data-sheet"> 
{foreach from=$features item=feature}
<tr class="{cycle values="odd,even"}">
{if isset($feature.value)} 
<td>{$feature.name|escape:'html':'UTF-8'}</td>
<td>{$feature.value|escape:'html':'UTF-8'}</td>
{/if}
</tr>
{/foreach}
</table>
</section>
<!--end Data sheet -->
{/if}
{if $product->description}
<!-- More info -->
<section class="page-product-box">
<h3 class="page-product-heading">{l s='More info'}</h3>{/if}
{if isset($product) && $product->description}
<!-- full description -->
<div  class="rte">{$product->description}</div>
</section>
<!--end  More info -->
{/if}
<!--HOOK_PRODUCT_TAB -->
<section class="page-product-box">
{$HOOK_PRODUCT_TAB}
{if isset($HOOK_PRODUCT_TAB_CONTENT) && $HOOK_PRODUCT_TAB_CONTENT}{$HOOK_PRODUCT_TAB_CONTENT}{/if}
</section>
<!--end HOOK_PRODUCT_TAB -->
{if isset($accessories) && $accessories}
<!--Accessories -->
<section class="page-product-box">
<h3 class="page-product-heading">{l s='Accessories'}</h3>
<div class="block products_block accessories-block clearfix">
<div class="block_content">
<ul id="bxslider" class="bxslider clearfix">
{foreach from=$accessories item=accessory name=accessories_list}
{if ($accessory.allow_oosp || $accessory.quantity_all_versions > 0 || $accessory.quantity > 0) && $accessory.available_for_order && !isset($restricted_country_mode)}
{assign var='accessoryLink' value=$link->getProductLink($accessory.id_product, $accessory.link_rewrite, $accessory.category)}
<li class="item product-box 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="product_desc">
<a href="{$accessoryLink|escape:'html':'UTF-8'}" title="{$accessory.legend|escape:'html':'UTF-8'}" class="product-image product_image">
<img class="lazyOwl" src="{$link->getImageLink($accessory.link_rewrite, $accessory.id_image, 'home_default')|escape:'html':'UTF-8'}" alt="{$accessory.legend|escape:'html':'UTF-8'}" width="{$homeSize.width}" height="{$homeSize.height}"/>
</a>
<div class="block_description">
<a href="{$accessoryLink|escape:'html':'UTF-8'}" title="{l s='More'}" class="product_description">
{$accessory.description_short|strip_tags|truncate:25:'...'}
</a>
</div>
</div>
<div class="s_title_block">
<h5 class="product-name">
<a href="{$accessoryLink|escape:'html':'UTF-8'}">
{$accessory.name|truncate:20:'...':true|escape:'html':'UTF-8'}
</a>
</h5>
{if $accessory.show_price && !isset($restricted_country_mode) && !$PS_CATALOG_MODE}
<span class="price">
{if $priceDisplay != 1}
{displayWtPrice p=$accessory.price}{else}{displayWtPrice p=$accessory.price_tax_exc}
{/if}
</span>
{/if}
</div>
<div class="clearfix" style="margin-top:5px">
{if !$PS_CATALOG_MODE && ($accessory.allow_oosp || $accessory.quantity > 0)}
<div class="no-print">
<a class="exclusive button ajax_add_to_cart_button" href="{$link->getPageLink('cart', true, NULL, "qty=1&amp;id_product={$accessory.id_product|intval}&amp;token={$static_token}&amp;add")|escape:'html':'UTF-8'}" data-id-product="{$accessory.id_product|intval}" title="{l s='Add to cart'}">
<span>{l s='Add to cart'}</span>
</a>
</div>
{/if}
</div>
</li>
{/if}
{/foreach}
</ul>
</div>
</div> 
</section>
<!--end Accessories -->
{/if}
{if isset($HOOK_PRODUCT_FOOTER) && $HOOK_PRODUCT_FOOTER}{$HOOK_PRODUCT_FOOTER}{/if}
<!-- description & features -->
{if (isset($product) && $product->description) || (isset($features) && $features) || (isset($accessories) && $accessories) || (isset($HOOK_PRODUCT_TAB) && $HOOK_PRODUCT_TAB) || (isset($attachments) && $attachments) || isset($product) && $product->customizable}
{if isset($attachments) && $attachments}
<!--Download -->
<section class="page-product-box">
<h3 class="page-product-heading">{l s='Download'}</h3>
{foreach from=$attachments item=attachment name=attachements}
{if $smarty.foreach.attachements.iteration %3 == 1}<div class="row">{/if}
<div class="col-lg-4">
<h4><a href="{$link->getPageLink('attachment', true, NULL, "id_attachment={$attachment.id_attachment}")|escape:'html':'UTF-8'}">{$attachment.name|escape:'html':'UTF-8'}</a></h4>
<p class="text-muted">{$attachment.description|escape:'html':'UTF-8'}</p>
<a class="btn btn-default btn-block" href="{$link->getPageLink('attachment', true, NULL, "id_attachment={$attachment.id_attachment}")|escape:'html':'UTF-8'}">
<i class="icon-download"></i>
{l s="Download"} ({Tools::formatBytes($attachment.file_size, 2)})
</a>
<hr>
</div>
{if $smarty.foreach.attachements.iteration %3 == 0 || $smarty.foreach.attachements.last}</div>{/if}
{/foreach}
</section>
<!--end Download -->
{/if}
{if isset($product) && $product->customizable}
<!--Customization -->
<section class="page-product-box">
<h3 class="page-product-heading">{l s='Product customization'}</h3>
<!-- Customizable products -->
<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>
{if $product->uploadable_files|intval}
<div class="customizableProductsFile">
<h5 class="product-heading-h5">{l s='Pictures'}</h5>
<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)|escape:'html':'UTF-8'}" 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 form-group">
<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="form-control 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">
<h5 class="product-heading-h5">{l s='Text'}</h5>
<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 name="textField{$field.id_customization_field}" class="form-control customization_block_input" id="textField{$customizationField}" rows="3" cols="20">{strip}
{if isset($textFields.$key)}
{$textFields.$key|stripslashes}
{/if}
{/strip}</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" />
<button class="button btn btn-default button button-small" name="saveCustomization">
<span>{l s='Save'}</span>
</button>
<span id="ajax-loader" class="unvisible">
<img src="{$img_ps_dir}loader.gif" alt="loader" />
</span>
</p>
</form>
<p class="clear required"><sup>*</sup> {l s='required fields'}</p> 
</section>
<!--end Customization -->
{/if}
{/if}
{if isset($packItems) && $packItems|@count > 0}
<section id="blockpack">
<h3 class="page-product-heading">{l s='Pack content'}</h3>
{include file="$tpl_dir./product-list.tpl" products=$packItems}
</section>
{/if}

Y pegar este de abajo en su lugar:

<!-- description and features -->
{if (isset($product) && $product->description) || (isset($features) && $features) || (isset($accessories) && $accessories) || (isset($HOOK_PRODUCT_TAB) && $HOOK_PRODUCT_TAB) || (isset($attachments) && $attachments) || isset($product) && $product->customizable}
<div id="more_info_block" class="clear">
<ul id="more_info_tabs" class="idTabs idTabsShort clearfix">
{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}
{if isset($product) && $product->customizable}<li><a href="#idTab10">{l s='Product customization'}</a></li>{/if}
{$HOOK_PRODUCT_TAB}
</ul>
<div id="more_info_sheets" class="sheets align_justify">
{if isset($product) && $product->description}
<!-- full description -->
<div id="idTab1" class="rte">{$product->description}</div>
{/if}
{if isset($features) && $features}
<!-- product's features -->
<ul id="idTab2" class="bullet">
<table class="table-data-sheet"> 
{foreach from=$features item=feature}
<tr class="{cycle values="odd,even"}">
{if isset($feature.value)} 
<td>{$feature.name|escape:'html':'UTF-8'}</td>
<td>{$feature.value|escape:'html':'UTF-8'}</td>
{/if}
</tr>
{/foreach}
</table>
</ul>
{/if}
{if isset($attachments) && $attachments}
<ul id="idTab9" class="bullet">
{foreach from=$attachments item=attachment}
<li><a href="{$link->getPageLink('attachment', true, NULL, "id_attachment={$attachment.id_attachment}")|escape:'html'}">{$attachment.name|escape:'htmlall':'UTF-8'}</a><br />{$attachment.description|escape:'htmlall':'UTF-8'}</li>
{/foreach}
</ul>
{/if}
{if isset($accessories) AND $accessories}
<!-- accessories -->
<div id="idTab4" class="bullet">
<div class="block products_block accessories_block clearfix">
<div class="block_content">
<ul>
{foreach from=$accessories item=accessory name=accessories_list}
{if ($accessory.allow_oosp || $accessory.quantity_all_versions > 0 || $accessory.quantity > 0) AND $accessory.available_for_order AND !isset($restricted_country_mode)}
{assign var='accessoryLink' value=$link->getProductLink($accessory.id_product, $accessory.link_rewrite, $accessory.category)}
<li class="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">
<p class="s_title_block">
<a href="{$accessoryLink|escape:'htmlall':'UTF-8'}">{$accessory.name|escape:'htmlall':'UTF-8'}</a>
{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}
</p>
<div class="product_desc">
<a href="{$accessoryLink|escape:'htmlall':'UTF-8'}" title="{$accessory.legend|escape:'htmlall':'UTF-8'}" class="product_image"><img src="{$link->getImageLink($accessory.link_rewrite, $accessory.id_image, 'medium_default')|escape:'html'}" alt="{$accessory.legend|escape:'htmlall':'UTF-8'}" width="{$mediumSize.width}" height="{$mediumSize.height}" /></a>
<div class="block_description">
<a href="{$accessoryLink|escape:'htmlall':'UTF-8'}" title="{l s='More'}" class="product_description">{$accessory.description_short|strip_tags|truncate:400:'...'}</a>
</div>
<div class="clear_product_desc">&nbsp;</div>
</div>

<p class="clearfix" style="margin-top:5px">
<a class="button" href="{$accessoryLink|escape:'htmlall':'UTF-8'}" title="{l s='View'}">{l s='View'}</a>
{if !$PS_CATALOG_MODE && ($accessory.allow_oosp || $accessory.quantity > 0)}
<a class="exclusive button ajax_add_to_cart_button" href="{$link->getPageLink('cart', true, NULL, "qty=1&amp;id_product={$accessory.id_product|intval}&amp;token={$static_token}&amp;add")|escape:'html'}" rel="ajax_id_product_{$accessory.id_product|intval}" title="{l s='Add to cart'}">{l s='Add to cart'}</a>
{/if}
</p>

</li>
{/if}
{/foreach}
</ul>
</div>
</div>
</div>
{/if}

<!-- Customizable products -->
{if isset($product) && $product->customizable}
<div id="idTab10" class="bullet customization_block">
<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>
{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)|escape:'html'}" 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 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" />
<input type="button" class="button" value="{l s='Save'}" onclick="javascript:saveCustomization()" />
<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}

{if isset($HOOK_PRODUCT_TAB_CONTENT) && $HOOK_PRODUCT_TAB_CONTENT}{$HOOK_PRODUCT_TAB_CONTENT}{/if}
</div>
</div>
{/if}
{if isset($packItems) && $packItems|@count > 0}
<div id="blockpack">
<h2>{l s='Pack content'}</h2>
{include file="$tpl_dir./product-list.tpl" products=$packItems}
</div>
{/if}

{if isset($HOOK_PRODUCT_FOOTER) && $HOOK_PRODUCT_FOOTER}{$HOOK_PRODUCT_FOOTER}{/if}

Con este archivo ya hemos terminado, guardamos cambios.

Modificando el CSS

Ahora vamos con prestashop/themes/nuestro-tema/css/global.css. Al final del archivo pegar este código CSS:

.idTabs {
list-style-type:none;
margin-top:20px;
}
 
ul.idTabs li {
float:left;
margin-right:-1px;
}
 
.idTabs a {
color:#555454;
text-transform:uppercase;
font-family:"Open Sans",sans-serif;
font-weight:600;
font-size:18px;
line-height:60px;
position:relative;
border:1px solid #d6d4d4;
background:#fbfbfb;
margin:0 0 20px;
padding:14px 20px 17px;
}
 
#more_info_sheets .product_desc .block_description {
float:left;
margin-left:10px;
width:420px;
}
 
#more_info_sheets .product_desc .clear_product_desc {
clear:both;
height:0;
line-height:0;
}
 
.idTabs .selected,#header .sf-menu > li.sfHover > a,#header .sf-menu > li > a:hover,#header .sf-menu > li.sfHoverForce > a {
color:#fff;
background: #553D3D;
border-bottom-color: #000000;
}

El fragmento de código CSS anterior dará estilo a las pestañas de la página "Detalles de producto".

Compatibilidad con otros módulos

La modificación que estamos realizando cambia la manera en que se muestran las fichas en la plantilla por defecto de Prestashop 1.6. Si utilizamos algunos módulos que añaden pestañas a esta sección, tendremos que cambiar la forma en que se muestran estas pestañas. Es fácil.

Vamos a ver cómo hacerlo para el módulo de comentarios de productos. Abrir el archivo prestashop/themes/nuestro-tema/modules/productcomments/tab.tpl, veremos este código:

<h3 id="#idTab5" class="idTabHrefShort page-product-heading">{l s='Reviews' mod='productcomments'}</h3>

Sustituirlo por este:

<li><a href="#idTab5" class="idTabHrefShort page-product-heading">{l s='Reviews' mod='productcomments'}</a></li>

Con esto ya hemos terminado! Podemos utilizar fácilmente el mismo modo de modificación para otros módulos.

11 comentarios:

  1. Muy buen tutorial, buscando lo encontré y es una currada, lo unico que a mi por ejemplo las imagenes de accesorios no se cargan. ¿sabrias decir por que pasa?

    ResponderEliminar
    Respuestas
    1. Hola Jose,
      Si el resto del contenido sí se muestra es posible que sea porque esa combinación no tenga asignada ninguna imagen. Desde la pestaña "Combinaciones" (cuando editas un producto) puedes ver éstas, modifica la combinación y asigna una imagen a esa combinación.

      Quizás sea por eso, si no, pudiera ser porque debas compilar, vaciar la caché, o compruébalo en otro navegador.

      Un saludo.

      Eliminar
  2. Gracias francisco, la última parte del tutoras ea aplicable a otros módulos?
    El problema que tengo es que se me añaden las pestañas, hasta ahí bien, pero el módulo en cuestión o los módulos se me ven en todas las pestañas. Supongo que por estar hechos para presta 1.6.

    ResponderEliminar
    Respuestas
    1. Hola Jose Manuel,

      Creo que el problema va a ser por lo siguiente:

      Las etiquetas [a] que están dentro de las etiquetas [li] tienen el atributo href="#idTab2".

      Luego tienes una línea como está: [ul id="idTab2" class="bullet"]

      Si te fijas el valor "idTab2" coincide, debes fijarte en que a ti te coincida también, tiene que haber correspondencia para que el contenido del módulo que has instalado sea llamado al hacer clic.

      P.D. He sustituido < y > por [ y ] respectivamente porque no se pueden insertar aquí etiquetas HTML.

      Eliminar
  3. cuando hago los cambios me muestra este error "Error del servidor

    500" que debo hacer?

    ResponderEliminar
    Respuestas
    1. Borra la caché de prestashop, recompila la plantila prueba en otro navegador.
      Si te sigue sin funcionar deshaz los cambios.

      Eliminar
    2. Borra la caché de prestashop, recompila la plantila prueba en otro navegador.
      Si te sigue sin funcionar deshaz los cambios.

      Eliminar
  4. Buenas tardes, acabo de hacer todo lo que dice en el tutorial, sale el "Mas" y "Ficha técnica" juntos uno debajo del otro pero sin formato, pudiendo haciendo clic en uno y otro y cambia de un texto a otro pero lo que es el formato esta literalmente como lo ves aquí escrito

    Más
    Ficha técnica

    (supongo que es problema del CSS)

    Como puedo modificar para que se vean bien las pestañas.

    Gracias.

    ResponderEliminar
    Respuestas
    1. Hola, no sé si habrás leído todo el tutorial, pero en la parte final se dice que hay que sustituir los encabezados h3 por etiquetas li. Y si no fuera por eso, puede deberse a que las etiquetas li no están flotadas. Utiliza float:left sobre las etiquetas li.

      Eliminar
    2. Buenas, perfecto gracias!!! Ya me funcionó.

      Para terminar, veo que dices para hacer en otros modulos como el ejemplo del comments pues yo tengo uno que se llama Ask a question (gratuito)
      http://store.nemops.com/free-modules/32-ask-a-question.html#.WC8iwfnhCUk

      El problema que al ver el .tpl de este modulo sale ya con el < li >.... y no se pone en una pestaña sino sale debajo.

      Los demás perfecto, la pestaña MAS y Reseñas pero este del Ask a question, se pone debajo.

      Gracias por la ayuda!

      Eliminar
    3. Asegúrate de que tenga la propiedad float:left activa. A veces otras reglas CSS interfieren y por eso no se aplica el float. ¿Conoces la herramienta Inspeccionar Elemento de los navegadores?
      Con esa herramienta podrás comprobarlo bien.

      Eliminar