Product page tabs like 1.5 on Prestashop 1.6

Have you been missing the traditional product page tabs in the new Prestashop 1.6 template? If so, see how to easily take them back.

Let’s get some Prestashop 1.5 template code

To start off, get some 1.5 template code and drop it into our 1.6. I chose 1.5.6.2 as it’s the latest 1.5 so far. This is how it looks like, you can simply copy/paste it:

[php htmlscript=”true”]
{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">
{foreach from=$features item=feature}
{if isset($feature.value)}
<li><span>{$feature.name|escape:’htmlall’:’UTF-8′}</span> {$feature.value|escape:’htmlall’:’UTF-8′}</li>
{/if}
{/foreach}
</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}

[/php]

Copy the previous code. Then, open up product.tpl, which you can find in the theme’s folder, and locate this line:

[php htmlscript=”true”]
{if isset($features) && $features}
<!– Data sheet –>
<section class="page-product-box">
[/php]

Right before that, paste in the 1.5 template code. We will need to make minor adjustments to it, but before diving deep into coding, let’s comment out the 1.6 code.
Comment out everything from here:

[php htmlscript=”true”]
{if isset($features) && $features}
[/php]

To right before

[php htmlscript=”true”]
{if isset($HOOK_PRODUCT_FOOTER) && $HOOK_PRODUCT_FOOTER}{$HOOK_PRODUCT_FOOTER}{/if}
[/php]

The result should be as follows:

[php]
{*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 –>

// WHOLE CODE BLOCK HERE…

</div>
</div>
</section>
<!–end Accessories –>
{/if*}
{if isset($HOOK_PRODUCT_FOOTER) && $HOOK_PRODUCT_FOOTER}{$HOOK_PRODUCT_FOOTER}{/if}
[/php]

With the whole block commented out. Then, comment out what comes after the product footer hook as well

[php]
<!– 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}

// WHOLE CODE BLOCK HERE…

<p class="clear required"><sup>*</sup> {l s=’required fields’}</p>
</section>
<!–end Customization –>
{/if}
{/if*}
[/php]

Pay extra attention to this step, there are a bunch of IF statements at the end of the block, which might cause a bad error if not commented out in the right place.

Adapting the code

At this point, we need to adapt a couple of sections, to make sure they are compatible with 1.6. We will simply examine each section and replace the content with its newer counterpart when needed.

The first block is the product description, and there is really nothing to change here, as it’s the same across the two templates.

Features (data sheet) is another one that can be left as it is.

THe following one would be attachments, looking like this in the 1.5 snippet:

[php htmlscript=”true”]
{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}
[/php]

Let’s compare it to the 1.6 version:

[php htmlscript=”true”]
{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}
[/php]

Replacing it sounds like a good idea, so go ahead and do it. Simply paste over everything inside the foreach (make sure you also add the name=attachments part!).

Accessories is another one we need to replace, so delete everything within the condition:

[php htmlscript=”true”]
{if isset($accessories) AND $accessories}
<!– accessories –>
<div id="idTab4" class="bullet">

// Delete everything inside
</div>
{/if}

<!– Customizable products –>
[/php]

Still making sure to retain the #idTab4 div

The last block of the 1.5 template concerns customizable data, and it’s better to replace the whole content here as well. Therefore, once more:

[php htmlscript=”true”]
{if isset($product) && $product->customizable}
<div id="idTab10" class="bullet customization_block">
// Delete everything inside

</div>
{/if}

[/php]

Remove everything inside that div with idTab10 as ID.

We should be done…almost! There is a leftover of the 1.6 section, Pack Items, which used to be elsewhere in 1.5. If you don’t want it to be part of tabbed data, you can simply uncomment the section as it is. Otherwise, read on.

Dealing with the Pack Items block

We cannot simply copy and paste the pack items block, as that would result in a div having no parent link to call it among tabs. The first thing we therefore have to do is add a link pointing to it, in the tabs navigation bar:

[php htmlscript=”true”]
<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}
{if isset($packItems) && $packItems|@count > 0}<li><a href="#blockpack">{l s=’Pack Items’}</a></li>{/if}
{$HOOK_PRODUCT_TAB}
</ul>
[/php]

As you can see, I added a whole new line to handle the pack tab, which is referencing to a (still non existing) div with the id #blockpack. You can really choose any ID you want here, just making sure it matches in the following step.

Let’s not scroll back after the customization block:

[php]
{/if}

{if isset($HOOK_PRODUCT_TAB_CONTENT) && $HOOK_PRODUCT_TAB_CONTENT}{$HOOK_PRODUCT_TAB_CONTENT}{/if}
[/php]

Right before {if isset($HOOK_… } but after that closing {/if} (which was the customization condition), so in that only one empty line, add the following:

[php htmlscript=”true”]
{if isset($packItems) && $packItems|@count > 0}
<div id="blockpack">
{include file="$tpl_dir./product-list.tpl" products=$packItems}
</div>
{/if}
[/php]

Here is how it should look

[php htmlscript=”true”]
{/if}
{if isset($packItems) && $packItems|@count > 0}
<div id="blockpack">
{include file="$tpl_dir./product-list.tpl" products=$packItems}
</div>
{/if}
{if isset($HOOK_PRODUCT_TAB_CONTENT) && $HOOK_PRODUCT_TAB_CONTENT}{$HOOK_PRODUCT_TAB_CONTENT}{/if}
[/php]

Product Page tabs like 1.5 in Prestashop 1.6 - unstyled

You can now breathe. The worst part is done. Save and refresh, you should have a working tabs system, even if navigation links are stack one on top of the other. Let’s give it some style!

Styling Tabs in the Product page

There is not much to do at this point. Open up product.css, located in the theme folder, css/, and paste in the following

[css]

#more_info_tabs li {
float:left;

}

#more_info_tabs li a {
padding: 0 20px;
color:white;
line-height: 40px;
height: 40px;
display:block;
background: #555;
}

#more_info_tabs li a:active {text-decoration:none;}
#more_info_tabs li a.selected {
background:black;
text-decoration:none;
}

[/css]

I gave it some generic styling to have them look like tabs, so feel free to expand over the tutorial and make it prettier! We’re done!

Product Page tabs like 1.5 in Prestashop 1.6 - Final result

Need PrestaShop Modules? Have a look at my Prestashop Addons Store!

Looking for quality PrestaShop Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , | Posted under PrestaShop | RSS 2.0

Author Spotlight

Fabio Porta

Fabio has been involved in web development and design since 2005, when launched his first website at the age of 16. He’s now highly skilled in both client and server side development, along with design, and since August 2012 runs a successful website about PrestaShop tutorials and Prestashop Modules called Nemo’s Post Scriptum, at http://nemops.com

Leave a Reply

Your email address will not be published. Required fields are marked *