====== Advanced Template Customisations ====== **Working with FoxyCart Templates** * [[v:2.0:templates|Basic Customizations]]\\ Utilising the new configuration option for common changes * [[v:2.0:templates:intermediate-automagicache|Intermediate Customizations]]\\ Incorporating your own designs in the FoxyCart templates * [[v:2.0:templates:advanced|Advanced Customizations]]\\ Altering the raw templates * [[v:2.0:templates:primer|FoxyCart Templates and Caching Primer]] * [[v:2.0:templates:view_data|Template View Data]]\\ Cheatsheet for the variables accessible on the templates This section is for people with intermediate to advanced CSS, HTML, and JS abilities. We're happy to help you if you get stuck, but if it's your first rodeo, this stuff might be a bit head-spinning :) ===== Getting even more advanced with Twig ===== If you'd like to customize your templates beyond what you can do with HTML, CSS, and JavaScript, FoxyCart allows you to use the [[https://twig.symfony.com|Twig template language]] as well. Twig is flexible template language that's either near identical or relatively similar to a variety of other template languages. This functionality is very advanced, and most users should be able to achieve very seamless visual integrations without this. If you have super specific needs, however, you can dig into Twig. ===== Templates and Caching: How it all works ===== * We use [[https://twig.symfony.com|Twig]] as a template language, and we use [[https://github.com/justjohn/twig.js/wiki|Twig.js]] as well. Doing this allows us (and you) to use the same templates for clientside and serverside rendering. * We use the [[http://bem.info/method/definitions/|BEM methodology]] for CSS naming. * All template variables used exist in the ''FC.json'' object. You'll see references to variables in the template files. That's where they live, but there are helper methods to work with that data. * We have a system we call AutoMagiCache, which scrapes a template file on your site and will cache it (and all assets) securely on our systems, so you don't need SSL on your own server to reference assets (images, css, js). [[v:2.0:templates:intermediate-automagicache|Details on working with AutoMagiCache here]]. * We're currently using Twitter Bootstrap 3 as a base for our default theme, but we're using SASS ''@extend'' functionality so you won't see any Bootstrap classnames. * Doing advanced customizations can get involved, but there are "easier" and "more difficult" ways to accomplish things within our templating approach. When in doubt please, //please// just reach out. We're happy to help. Additionally, in previous versions of FoxyCart there was no clear separation of concerns between content (HTML), presentation (CSS), and dynamic behavior (Javascript). With v2.0 we're doing our best to help each aspect be a separate concern, so that you can override or customize the specific aspects your customers need without worrying about breaking things. ==== Recommended Reading ==== Before you proceed any further, we recommend looking over our [[v:2.0:templates:primer|Templates and Caching Primer]] page to get an understanding of the different pieces involved. Some parts may be already familiar to you - but having a grasp of the different pieces of the puzzle will make working deep within our templates all the more easier. We also strongly recommend taking a look at the Twig overview documentation over at their site at [[https://twig.symfony.com/doc/2.x/templates.html]]. Understanding the basics of Twig will help you to be able to read our templates. Below, you'll find our best attempt at explaining each aspect of our templates and how you can override, hook into, or remove the aspects that you're interested in. If you have questions, please don't hesitate to [[https://foxy.io/contact|contact our support]]. ===== FoxyCart Template Structure ===== There are two levels to the FoxyCart templates, both of which are rendered using the Twig templating language, which are the Page Templates and the Partial Includes. ==== Page Templates ==== The Page Templates are the templates that form the base of the actual page being output - this is where you'll find ''html'', ''head'' and ''body'' tags. These are also the templates that you'll find under the 'templates' menu in your store's FoxyCart administration. These templates are also the different steps to the checkout flow that a customer could experience. The Page Templates include: * Cart Include * Cart - Full page cart (''yourstore.foxycart.com/cart'') * Checkout * Receipt * Email (HTML and Text) One key thing to note is the "Cart Include" template. It is technically a partial include template - but is used for the Sidecart functionality on your own website, so is a page template in that regard. The template also performs duties as the cart partial as displayed within the cart, checkout, receipt and HTML email templates though as well. The "Cart Include" template therefore doesn't have the traditional HTML structure in terms of ''html'', ''head'' or ''body'' tags. ==== Partial Include Templates ==== Within the page templates, are one or more partial includes that output different sections of the respective templates. Partials can also be stacked - a given partial may include one or more other partials within itself if required. The different partials may seem confusing at first - but we've broken the templates up into modular reusable pieces. As a quick overview of the different partials includes we have, look over the following cascading lists of our partials as they're included. * ''cart.inc.twig'' * ''svg.inc.twig'' * ''errors.inc.twig'' * ''postal_code.inc.twig'' * ''regions.inc.twig'' * ''checkout.inc.twig'' * ''cart.inc.twig'' * ''errors.inc.twig'' * ''address.checkout.inc.twig'' * ''postal_code.inc.twig'' * ''regions.inc.twig'' * ''receipt.inc.twig'' * ''cart.inc.twig'' * ''address.receipt.inc.twig'' * ''postal_code.inc.twig'' * ''regions.inc.twig'' * ''address.email.inc.twig'' - included in ''responsive.email.twig'' * ''address.email.inc.txt.twig'' - included in ''email.txt.twig'' * ''cart.inc.txt.twig'' - included in ''email.txt.twig'' ==== Outputting Partial Includes ==== A page template on it's own is just a normal page. If you want to include FoxyCart functionality within it, you'll need to output one or more partial includes within the template. You can output a Twig include file in one of two ways, ''include'' and ''use''. Which you use will depend on what you're wanting to do. === Include - directly output the include into the page === If you use ''include'', that will take the whole contents of that file, and output it at that spot in the template. This is perfect if you're just wanting to output the default approach to that section, but you're wanting to include it somewhere specific. [[https://twig.symfony.com/doc/2.x/tags/include.html|View include in the Twig documentation]]. Example: {% include 'cart.inc.twig' %} === Embed - output the include on the page, but allowing for overriding blocks within it === Loading an include using ''embed'' behaves similar to ''include'' above in that it will output the whole contents of the file into the page. Within the ''embed'' tags though, you can also define ''block'' tags for blocks that exist within that included file, and overwrite them. Any code not contained with a pre-existing block, or any custom blocks, will be ignored. [[https://twig.symfony.com/doc/2.x/tags/embed.html|View embed in the Twig documentation]]. Example: {% embed 'checkout.inc.twig' %} {% endembed %} === Use - load the blocks contained within ready for placement and modifying === Referencing an include using ''use'', with just that tag in isolation will output nothing into the page. What it will do is gather all the blocks within that include and load them into memory for you to manually include as desired. Anything not contained inside blocks will be ignored. [[https://twig.symfony.com/doc/2.x/tags/use.html|View use in the Twig documentation]]. Example: {% use 'cart.inc.twig' %} {# Nothing output yet #} {{ block('logo') }} {# Logo block output into page #} ==== Blocks ==== Within the partial templates, we make use of [[https://twig.symfony.com/doc/2.x/tags/block.html|Twig's block functionality]] to wrap certain chunks of our code into a named block. For an example, let's say you have a partial include called ''widgets.inc.twig'' with blocks that look like this: {% block block_a %}

{{ widget_title }}

{% endblock block_a %} {% block block_b %}

{{ widget_subtitle }}

{% endblock block_b %}
As you can see, there are two blocks within that markup enclosing two headers. If you wanted to just include that whole partial in your page template, you would just use the ''include'' approach to do that. What if you wanted to include that partial, but make some changes to one of the blocks? That's where ''use'' comes into play - allowing you to reference whole blocks with a single tag. === Editing blocks with ''embed'' === As an example, let's say that we wanted to output our ''widgets.inc.twig'' partial within our page, but we wanted to change ''block_b'' to output the ''widget_subtitle'' in a paragraph tag instead of a heading. We don't want to change ''block_a'' at all. We could simply copy the whole ''widgets.inc.twig'' code into our partial and just ignore the blocks, which would work. A better way though is to make use of the ''embed'' tag, and overwrite blocks from the partial. By doing that - our code is cleaner within our page template, and if we make changes to our ''widgets.inc.twig'' partial file later on, we'll still get those changes (apart from anything we overwrite). So to follow on with our example, changing the ''h2'' element to a paragraph would look like this in our page template: {% embed 'widgets.inc.twig' %} {% block block_b %}

{{ widget_subtitle }}

{% endblock block_b %} {% endembed %}
In the code above - the ''widgets.inc.twig'' template will be output as it is in the original file, but ''block_b'' will be output as we redefined it within the ''embed''. This would result in HTML like this:

{{ widget_title }}

{{ widget_subtitle }}

Embedding also allows you to still output the block as it is - and just add something before or after it. For example, if we wanted to add some additional content after the ''h2'' title in ''block_b'', but leave the heading as it is, we can do that by outputting ''%%{{ parent() }}%%'' like this: {% embed 'widgets.inc.twig' %} {% block block_b %} {{ parent() }}

{{ widget_date }}

{% endblock block_b %} {% endembed %}
This set up would result in HTML like this:

{{ widget_title }}

{{ widget_subtitle }}

{{ widget_date }}

If you're wanting to make changes to how the cart template is displayed on the checkout or receipt - you should make changes directly to the "cart include" template. We don't currently support using an ''embed'' tag of the ''cart.inc.twig'' template within the checkout or receipt ''embed'' calls. ==== Allowed Twig Tags and Functionality ==== At present, the only allowed functionality for Twig is as follows: * Tags: [[https://twig.symfony.com/doc/2.x/tags/block.html|block]], [[https://twig.symfony.com/doc/2.x/tags/embed.html|embed]], [[https://twig.symfony.com/doc/2.x/tags/if.html|if]], [[https://twig.symfony.com/doc/2.x/tags/import.html|import]], [[https://twig.symfony.com/doc/2.x/tags/include.html|include]], [[https://twig.symfony.com/doc/2.x/tags/for.html|for]], [[https://twig.symfony.com/doc/2.x/tags/macro.html|macro]], [[https://twig.symfony.com/doc/2.x/tags/set.html|set]] * Filters: [[https://twig.symfony.com/doc/2.x/filters/abs.html|abs]], [[https://twig.symfony.com/doc/2.x/filters/capitalize.html|capitalize]], [[https://twig.symfony.com/doc/2.x/filters/date.html|date]], [[https://twig.symfony.com/doc/2.x/filters/date_modify.html|date_modify]], [[https://twig.symfony.com/doc/2.x/filters/default.html|default]], [[https://twig.symfony.com/doc/2.x/filters/escape.html|escape]], [[https://twig.symfony.com/doc/2.x/filters/first.html|first]], [[https://twig.symfony.com/doc/2.x/filters/join.html|join]], [[https://twig.symfony.com/doc/2.x/filters/json_encode.html|json_encode]], [[https://twig.symfony.com/doc/2.x/filters/keys.html|keys]], [[https://twig.symfony.com/doc/2.x/filters/last.html|last]], [[https://twig.symfony.com/doc/2.x/filters/length.html|length]], [[https://twig.symfony.com/doc/2.x/filters/lower.html|lower]], [[https://twig.symfony.com/doc/2.x/filters/merge.html|merge]], [[https://twig.symfony.com/doc/2.x/filters/nl2br.html|nl2br]], [[https://twig.symfony.com/doc/2.x/filters/number_format.html|number_format]], [[https://twig.symfony.com/doc/2.x/filters/round.html|round]], [[https://twig.symfony.com/doc/2.x/filters/slice.html|slice]], [[https://twig.symfony.com/doc/2.x/filters/split.html|split]], [[https://twig.symfony.com/doc/2.x/filters/raw.html|raw]], [[https://twig.symfony.com/doc/2.x/filters/replace.html|replace]], [[https://twig.symfony.com/doc/2.x/filters/reverse.html|reverse]], [[https://twig.symfony.com/doc/2.x/filters/title.html|title]], [[https://twig.symfony.com/doc/2.x/filters/trim.html|trim]], [[https://twig.symfony.com/doc/2.x/filters/upper.html|upper]], [[https://twig.symfony.com/doc/2.x/filters/url_encode.html|url_encode]] * Functions: [[https://twig.symfony.com/doc/2.x/functions/block.html|block]], [[https://twig.symfony.com/doc/2.x/functions/date.html|date]], [[https://twig.symfony.com/doc/2.x/functions/random.html|random]], [[https://twig.symfony.com/doc/2.x/functions/template_from_string.html|template_from_string]], [[https://twig.symfony.com/doc/2.x/functions/min.html|min]], [[https://twig.symfony.com/doc/2.x/functions/max.html|max]] Need a tag, filter or function not listed here? Simply [[http://www.foxycart.com/contact|get in touch]] and we can look at adding it. We also have some custom Twig filters and functions we've added to meet specific needs: **Tags** ; ''money_format'' : **Description:** Formats a given number into the formatting of the store : **Example:** ''%%{{ total_item_price|money_format }}%%'' ; ''pad'' : **Description:** Adds a specific character : **Parameters:** * Integer representing the length to pad (Default ''30'') * String of the value to pad the variable with (Default ''%%" "%%'') * String of the delimiter between the variable and the padding (Default ''%%":"%%'') * Direction of the padding from the variable ''%%"left"%%'' or ''%%"right"%%'' (Default ''%%"right"%%'') : **Example:** ''%%{{ key|pad(20) }}%%'' or ''%%{{ key|pad(30, "-", "", "left") }}%%'' ; ''fc_output_data'' : **Description:** Used to customise email subjects, from and bcc, [[v:2.0:emails#email_receipt_placeholders|as documented here]]. **Functions** ; ''selected'' : **Description:** Used to add the ''selected'' HTML attribute to select dropdowns : **Parameters:** Two strings for comparison : **Example:** ''%%