Skip to content

A Simple Javascript library to manage HTML Fragment templates

License

Notifications You must be signed in to change notification settings

diegolamonica/XTemplate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 

Repository files navigation

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](invoice example)

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

About

A Simple Javascript library to manage HTML Fragment templates

Resources

License

Stars

Watchers

Forks

Packages

No packages published