Xtemplate: Template engine that uses HTML page fragments

Recommend this page to a friend!
  Info   View files Documentation   Demos   View files View files (27)   DownloadInstall with Composer Download .zip   Reputation   Support forum   Blog    
Ratings Unique User Downloads Download Rankings
Not enough user ratingsTotal: 147 All time: 338 This week: 3Up
Version License JavaScript version Categories
xtemplate 1.5GNU Lesser Genera...1.0HTML, Utilities and Tools, Templates
Description Author

This object is a template engine that uses HTML page fragments.

It can process templates using HTML fragments present on the page inside script tags of type text/x-template. The object can:

- Replace placeholder marks with parameter values
- Include sub-templates
- Evaluate conditions
- Evaluate expressions
- Manage multilingual contents

Recommendations

invoice live edit
Parse dynamic table and calculate sum of rows and cols

Innovation Award
JavaScript Programming Innovation award nominee
May 2015
Number 2
Template engines often require that developers pass external template files or strings to define the template data to be processed.

This JavaScript object supports an alternative template data source type that consists in taking fragments of the current HTML page.

Manuel Lemos
Picture of Diego La Monica
  Performance   Level  
Name: Diego La Monica <contact>
Classes: 2 packages by
Country: Italy Italy
Age: 45
All time rank: 1063 in Italy Italy
Week rank: 6 Up1 in Italy Italy Up
Innovation award
Innovation award
Nominee: 2x

Details

XTemplate

A Simple Javascript library to manage HTML Fragments templates

To see XTemplate in action download the package and open files of examples directory in your browser or else see it on http://diegolamonica.info/demo/xtemplate/

2015-09-12: V 1.5

  • Enabled automatic translation action on setting new language
  • Now translation files are loaded in async mode (better than the deprecated sync mode)
  • New: now you can add your own placeholder activators simply
  • Added new methods `register` and `unregister` to manage custom placeholder activatos
  • Added new method `isTranslationReady`
  • Removed some debug messages
  • Added other debug messages
  • Updated documentation
  • Updated example file `translations.html`
  • Added example file `autotranslate.html`
  • Added example file `custom-placeholders.html`

For the changelog of previous versions go to the end of this page.

Dependencies

  • JQuery 1.9+

Basic Usage

Example: hello-world.html

Put this fragment in your HTML

<!-- 
Remember that type attribute must be set to "text/x-template" to be recognized as it is.
 Another fundamental thing is to define an id attribute for the script element.
 -->
<script type="text/x-template" id="my-template">
    <div>
        Hello World!
    </div>
</script>

<div id="my-section">This text will be replaced</div> 

Then put this code in your Javascript section:

var x = new Xtemplate(),
    /*
     * #my-template is the template selector
     */
    output = x.apply('#my-template', {});

$('#my-section').html(output);

Table of contents

XTemplate Function Reference

  • apply (templateId, rows[, callback[, intoId]]) Uses the template defined as `templateId` in conjunction with the data given in `rows` argument. If `intoId` is not defined the method will output the computed string. rows can be either an object or an array of objects. However it must contain at least an object else the given output will be an empty string. callback is an optional method that will manipulate each element defined in `rows`. It expect a single argument (the single row) and will returns the altered version of the row. Default value is `undefined` intoId is the section of the template where to append (or replace if the `replaceContents` option is set to `true`) the computed template.
  • applyString (templateString, items[, callback[, translations]]) Uses the template defined as string in conjunction with the data given in `rows` argument and returns the computed string. items can be either an object or an array of objects. However it must contain at least an object else the given output will be an empty string. callback is an optional method that will manipulate each element defined in `items`. It expect a single argument (the single row) and will returns the altered version of the row. Default value is `undefined` translations (default `undefined`) is a translation object as described in the section XTemplate translation file structure
  • setLang(langName) Set the lang to the new one. It will update the translation strings loading the files from the defined source (see Produce multilingual contents section).
  • register(activator, callback, priority) Defines new placeholder activator. The output of the method will be `true` if the activator is correctly registered. It will return false if the `activator` is already registered.

    activator can be either a string if it must recognize a simple placeholder (eg. `{&placeholder}`) or an indexed array if it must recognize a complex placeholder, like the condition statement. If it is an array then it must contain at least 2 values: the activator sequence (eg. `&`) in the index 0 and the closing block sequence in the index 1. If the third element of the array is defined then it must be a boolean value and determine if the inner block accepts multiple line. callback is the method that will be invoked to process the placeholder contents. To know how to build the callback method, see the next section Extending XTemplate Placeholders priority is the position where which to use the registered activator. It can be one of the values defined in #Activator Priorities# section.

  • unregister(activator) Will remove the activator from the parsing process. The method will return `true` it the activator is correctly removed else will return `false`. The reason the method will return `false` is because you are trying to remove a default activator.

Extending XTemplate Placeholders

XTemplate allows you to extend its syntax using the method register. The arguments that register expects are described in the above Function reference section.

Activator Priorities

The XTemplate flow on how it process templates the sequenze is: - Applying callback transformation to the items - Applying the translation strings - Execute expressions - Evaluate conditions - Replacing variables

So the allowed priorities values are: - XTEMPLATE_PRIORITY_BEFORE_CALLBACK - XTEMPLATE_PRIORITY_BEFORE_TRANSLATIONS - XTEMPLATE_PRIORITY_BEFORE_EXPRESSION - XTEMPLATE_PRIORITY_BEFORE_CONDITIONS - XTEMPLATE_PRIORITY_BEFORE_VAR - XTEMPLATE_PRIORITY_AFTER_VAR

Default Activators

The default activators are reserved and they are: - $ for variables identified by the constant XTEMPLATE_PLACEHOLDER_VAR - ? for conditional block start identified by the constant XTEMPLATE_PLACEHOLDER_IF_START - ! for conditional block end identified by the constant XTEMPLATE_PLACEHOLDER_IF_END - = for expression evaluation identified by the constant XTEMPLATE_PLACEHOLDER_EXPRESSION - # for subtemplate sections identified by the constant XTEMPLATE_PLACEHOLDER_SUBTEMPLATE - : for trasnlation contents identified by the constant XTEMPLATE_PLACEHOLDER_TRANSLATION - @ for reserved purposes identified by the constant XTEMPLATE_PLACEHOLDER_RESERVED

The callback method

The custom processing done by the custom placeholder activator is done by the callback method passed to the register method. It receives the following arguments:

  • `matches` is the array of matched pattern for each replacement. The order of contents is the following: 1. the whole matched string 2. the placeholder activator (eg. `$` ) 3. the placeholder (eg. for `{$lorem}` you will have `lorem`) 4. the inner content if the syntax expect a closing placeholder.
  • `items` is the object with key/value pairs given to the template.
  • `translations` is the key/value pairs with translation labels applied to the current template.

The method must return the computed text that will replace the current placeholder.

Example of custom activators

Example: custom-placeholders.html

Javascript:

x.register( '%', function(matches, items, translations){
     return '<a role="button" class="btn btn-primary">' + matches[2] + '</a>';
}, XTEMPLATE_PRIORITY_AFTER_VAR);

Template content:

{%Hello world!}

Output:

<a role="button" class="btn btn-primary">Hello world!</a>

XTemplate Configuration Object

When you initialize an XTemplate object, you can optionally pass a configuration object to it. Follow the properties that you can set for it:

| property | type | default value | description | |------------|:-------:|:-------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | debug | boolean | false | If true show some debug information in the console area | | lang | string | en_US | Defines which is the default language | | langPath | string | false | Set the path to the translations file (it can be relative, absoulte or external domain if CORS is allowed). The final file path is defined as: <langPath>/<lang>/<translation-file-name>. The <translation-file-name> must be defined in data-lang attribute of the template section. | | autotranslate | boolean | false | If true the call to setLang method will raise an automatic translation of contents. | | replaceContents | boolean | false | If true and is defined the intoId argument of the apply method, then it will replace the content in the intoId area. | | syncLoad | boolean | false | If true the translation strings loading process will be executed in synchronous mode. Note: before set it to true, please take a look to the XMLHttpRequest Standard |

An example initialization with Configuration object would be the following.

var x = new Xtemplate({
    debug: true,
    langPath: 'translations/',
    lang: 'en_US',
    autotranslate: true,
    replaceContents: false,
    syncLoad: true
});

Note To work properly, autotranslate when set to true, expect that the intoId argument of apply method must be defined.

Templates Syntax

The template syntax is really easy, to understand and remember: - {$variable} Reference to a variable - {?variable} ... {!variable} Show the block only if the variable exists - {#subtemplate} Reference to a subtemplate - {=expression} Executes a javascript expression a method call or a complex code in a safe context (XSS injection is not possible) - {:translation-label} Apply the translations according to the configuration (see Produce multilingual contents for further details)

Example of {$variable} usage

Example: hello-name.html

HTML:

<script type="text/x-template" id="hello-name-template">
    <div>
        Hello {$name}!
    </div>
</script>
<div id="my-section">This text will be replaced</div> 

Javascript:

var x = new Xtemplate(),
    row = {
      name: 'Diego'
    },
    output = x.apply('#hello-name-template', row);

$('#my-section').html(output);

Result will be:

<div id="my-section">
  <div>
      Hello Diego!
  </div>
</div> 

Example of {?condition} usage

Examples: hello-name-country-1.html (demo), hello-name-country-2.html (demo), conditions.html (demo)

The {?...} introduces an existence block condition ended by {!...}

The {?^...} introduces a non-existence block condition ended by {!^...}

HTML:

<script type="text/x-template" id="hello-name-template">
    <div>
        Hello {$name}{?country}, you are from {$country}{!country}!
    </div>
</script>
<div id="my-section">This text will be replaced</div> 

Javascript:

var x = new Xtemplate(),
    row = {
      name: 'Diego'
    },
    output = x.apply('#hello-name-template', row);

$('#my-section').html(output);

Output:

<div id="my-section">
  <div>
      Hello Diego!
  </div>
</div> 

But changing the row object as follows:

row = {
  name:     'Diego', 
  country:  'Italy'
}

will produce the following output:

<div id="my-section">
  <div>
      Hello Diego, you are from Italy!
  </div>
</div> 

Working with {#subtemplate}

  • Basic syntax {#subtemplate} `subtemplate` is the identifier of another template. The placeholder will be replaced with the subtemplate having the given `id`. The subtemplate will inherit the base data from the current template.
  • Advanced syntax {#subtemplate, subvariable=1, anotehrvariable="hello", anothervaraible=variablename} In the advanced syntax you can pass one or more runtime defined variables that will be merged in the base object and have limited scope to the subtemplate element. An argument value will be threat as: - `string` if it starts with `"` or `'` and will end with the same character. - `number` if it is a sequence of numbers optionally followed by a dot and by one or more numbers (in example `100` or `100.01`) - `variable` if it is not a string and not a number, then it would be a key of the current template
  • Extended Advanced syntax is {#subtemplate, +objectData1, +objectData2, anothervaraible="variable value"} The same as the Advanced syntax, but when an argument is prefixed by `+` the parser will try to do several operations: - if `objectData1` is an array and is the only argument passed to the subtemplate, then the informations avaliable on subtemplate will be only the ones into `objectData1` and it will loop the array using `subtemplate` as given template. - if `objectData1` is an array, but it is not the lonely argument passed to the subtemplate, then the data is ignored. - if `objectData1` is an object, it will be merged with the base object data. - if multiple objects were defined int the subtemplate call (like in the example above), all them will be merged together. Duplicate keys will be overwritten by the last in order of declaration.

Basic Syntax example

Example: subtemplate-basic.html (demo)

HTML:

<script type="text/x-template" id="country-template">
        and I am from {$country}
    </script>
    <script type="text/x-template" id="name-template">
        Hello, my name is {$name}
        {#country-template}
    </script>
    <div id="my-section"></div>

Javascript:

var x = new Xtemplate(),
    row = {
        name: 'Diego',
        country: 'Italy'
    },
    output = x.apply('#name-template', row);

$('#my-section').html(output);

Output:

<div id="my-section">
    Hello, my name is Diego
    
    and I am from Italy

</div>

Extended Syntax

Example: subtemplate-advanced.html (demo)

HTML:

<script type="text/x-template" id="name-template">
  Hello, my name is {$name}
  {#country-template live=country,age="38"}
</script>

<script type="text/x-template" id="country-template">
  actually I live in {$live} and I'm {$age} years old
</script>

<div id="my-section">This text will be replaced</div>

Javascript:

var x = new Xtemplate(),
    row = {
        name:       'Diego',
        country:    'Italy'
    },
    output = x.apply('#name-template', row);

$('#my-section').html(output);

Output:

<div id="my-section">
  Hello, my name is Diego
  
  actually I live in Italy and I'm 38 years old
</div>

Extended Advanced Syntax

Example: invoice.html (demo)

Due the complexity of the explanation, it's better to see it in action in the http://diegolamonica.info/demo/xtemplate/invoice.html

Callback argument usage example

Examples: callback-example.html (demo)

HTML:

<script type="text/x-template" id="country-template">
    and I am from {$country}
</script>
<script type="text/x-template" id="name-template">
    Hello, my name is {$name}
    {#country-template}<br />
</script>
<div id="my-section"></div>

Javascript:

  function myDataCallback(row) {

      var names = {
          John: 'London',
          Aaron: 'New York City',
          Anita: 'Spain'
      }

      if (names[row.name] !== undefined) {
          row.country = names[row.name];
      }
      return row;
  }

  var x = new Xtemplate(),
      rows = [
          { name: 'Diego', country: 'Italy' },
          { name: 'John'},
          { name: 'Aaron'},
          { name: 'Anita'}
      ],
      output = x.apply('#name-template', rows, myDataCallback);

  $('#my-section').html(output);

Output:

  Hello, my name is Diego
  and I am from Italy
  <br />
    
  Hello, my name is John
  and I am from London
  <br />
    
  Hello, my name is Aaron
  and I am from New York City
  <br />
    
  Hello, my name is Anita
  and I am from Spain
  <br />

Using {=expression}

Examples: functions.html (demo)

The Expression placeholder is able to evaluate any Javascript content with some known limitations: - The following methods/objects are disabled due security concerns: - setTimeout - setInterval - XMLHttpRequest - addEventListner - You cannot use curly brackets in the expression ( it's wrong to do: {='hello{'+name+'}'}, raising an unpredictable result, use instead the unicde value \u007b (or &#123;) for the opened bracket and \u007d (or &#125) for the closed bracket.

HTML:

<script type="text/x-template" id="functions-template">
    <pre>
        Math: 3 + 4 = {=3+4}
        Check XMLHttpRequest : {=typeof(document.XMLHttpRequest)}
        Check XMLHttpRequest : {=typeof(XMLHttpRequest)}

        var1+var2 : {=var1+var2}

        {=window.location.href} 
    </pre>
</script>

<div id="my-section"></div>

Javascript:

var x = new Xtemplate(true),

    output = x.apply('#functions-template', {
        var1: 1,
        var2: 3
    });

$('#my-section').html(output);

Output:

<pre>
Math: 3 + 4 = 7
Check XMLHttpRequest : undefined
Check XMLHttpRequest : object

var1+var2 : 4

http://localhost:63342/XTemplate/examples/functions.html 
</pre>

Produce multilingual contents

XTempalte allows you to manage multiple languages for your contents.

Note: because since the v 1.5 the translation strings loading is performed in an async process, the method apply should be invoked using the intoId parameter too. However you can force the loading process to run in sync mode setting the option syncLoad to true in the configuration object. Before go by this way, please take a look to the XMLHttpRequest Standard

XTemplate translation labels binding

Using the data-lang attribute in your x-template fragment, you can set the name of the file that keeps the translation labels:

<script type="text/x-template" id="my-template" data-lang="translations.json">
   <div>
     {:hello} {$name}!
     {:theCountry}
  </div>
</script> 

XTemplate translation file structure

The translation file is a simple JSON file with one or more key/value pairs:

{
    "hello": "Ciao! Io sono",
    "theCountry": " Vivo in {$country}!"
}

Due the translation lables were applied before every proessing, you can put into each value some placeholder like you can see in theCountry translation key.

ChangeLog

2015-09-12: V 1.5

  • Enabled automatic translation action on setting new language
  • Now translation files are loaded in async mode (better than the deprecated sync mode)
  • New: now you can add your own placeholder activators simply
  • Added new methods `register` and `unregister` to manage custom placeholder activatos
  • Added new method `isTranslationReady`
  • Removed some debug messages
  • Added other debug messages
  • Updated documentation
  • Updated example file `translations.html`
  • Added example file `autotranslate.html`
  • Added example file `custom-placeholders.html`

2015-05-26: V 1.4.1

  • Corrected some typos in documentation
  • Bugfix: in the `{=evaluation}` parsing, if the evaluated key is null then it was considered wrongly as undefined.

2015-05-25: V 1.4

  • Minor improvements in the `{=expression}` evaluation placeholder
  • Now subpattern arguments accepts the use of `+` (see documentation)
  • jQuery defined from anonymous function initialization
  • added `invoice.html` as real world example
  • updated all the examples to improve comprehensiveness
  • Updated the documentation

2015-05-21: V 1.3

  • Improved the `{=expression}` evaluation making it more safer, updated docummentation
  • Updated the `functions.html` example
  • Bugfix on translation strings where they are not available for specific language
  • Added License header in the class
  • Added a minimal format to the examples (using bootstrap over CDN)
  • Added fork-me link in all the examples files
  • Added an index to example directory (itself built with XTemplate)

2015-05-19: V 1.2

  • Introduced the `{:translation-label}` placeholder
  • Added the configuration object
  • Added `setLang` method
  • Added the `translations.html` example file
  • Improved the documentation

2015-05-15: V 1.1

  • Introduced the `{=expression}` placeholder
  • Added debug functionality

2015-05-13: V 1.0

  • Some Bugfixes (thanks to michacom contribution )
  • Introduced the negative condition

2015-05-11: First commit

  Example of usageExternal page  

Open in a separate window

  Files folder image Files  
File Role Description
Files folder imageexamples (14 files, 1 directory)
Accessible without login Plain text file LICENSE Lic. License text
Accessible without login Plain text file readme.md Doc. Documentation
Plain text file xtemplate.js Class Class source

  Files folder image Files  /  examples  
File Role Description
Files folder imagetranslations (2 directories)
  Accessible without login HTML file autotranslate.html Output V 1.5
  Accessible without login Plain text file callback-example.html Example Example
  Accessible without login Plain text file conditions.html Example Example
  Accessible without login HTML file custom-placeholders.html Output V 1.5
  Accessible without login Plain text file functions.html Example Example
  Accessible without login Plain text file hello-name-country-1.html Example Example
  Accessible without login Plain text file hello-name-country-2.html Example Example
  Accessible without login Plain text file hello-name.html Example Example
  Accessible without login Plain text file hello-world.html Example Example
  Accessible without login HTML file index.html Example Version 1.3- Added an index file to example directory (itself built with XTemplate)
  Accessible without login HTML file invoice.html Example Documentation
  Accessible without login Plain text file subtemplate-advanced.html Example Example
  Accessible without login Plain text file subtemplate-basic.html Example Example
  Accessible without login HTML file translations.html Example Documentation

  Files folder image Files  /  examples  /  translations  
File Role Description
Files folder imageen_US (5 files)
Files folder imageit_IT (5 files)

  Files folder image Files  /  examples  /  translations  /  en_US  
File Role Description
  Accessible without login Plain text file company-info.js Conf. Configuration script
  Accessible without login Plain text file hello-name.js Example Example script
  Accessible without login Plain text file invoice-footer.js Conf. Configuration script
  Accessible without login Plain text file invoice-header.js Conf. Configuration script
  Accessible without login Plain text file invoice.js Conf. Configuration script

  Files folder image Files  /  examples  /  translations  /  it_IT  
File Role Description
  Accessible without login Plain text file company-info.js Conf. Configuration script
  Accessible without login Plain text file hello-name.js Example Example script
  Accessible without login Plain text file invoice-footer.js Conf. Configuration script
  Accessible without login Plain text file invoice-header.js Conf. Configuration script
  Accessible without login Plain text file invoice.js Conf. Configuration script

 Version Control Unique User Downloads Download Rankings  
 100%
Total:147
This week:0
All time:338
This week:3Up