DTL toolkit in Dojo

Source: Internet
Author: User

The DTL language focuses on providing sufficient programming functions for static texts, such as branch and loop to determine the presentation of relevant logic. It is mainly used to split the representation of a document and the string text of data. The template defines placeholders and the basic logic of how various definition documents should be displayed (the template tag "template tag "), templates can be used to generate HTML or various text-based formats. The DTL toolkit of dojo implements DTL Syntax Parsing, and provides a series of easy-to-use interfaces for receiving parameters, generating and parsing various DTL-based text or HTML pages. In this way, we can construct an HTML template based on the simple DTL syntax, and fully reuse the code based on the DTL interface of dojo. This article will focus on the DTL toolkit of dojo and their various usage methods and techniques.

DTL template language Introduction
The DTL template language is a set of rules built into the Django framework that contain tags and filters. It includes tags such as autoescape, block, comment, cycle, for, if, ifequal, and filters such as ADD, capfirst, center, first, last, length, lower, and safe. These tags and filters, like our programming language, can help us implement various logics. The DTL toolkit of dojo implements most of the preceding tag and filter Syntax Parsing functions based on this set of rules. Therefore, we can directly implement various logics in Dojo Based on the DTL template language.

DTL toolkit of dojo
The DTL toolkit of dojo provides many interfaces for parsing our "DTL program", which is not only applicable to text parsing, but also for HTML pages. For engineers who have previously used DTL development, porting existing code to dojo is quite convenient, basically seamless.
Next, let's take a look at some specific objects and interfaces of the DTL toolkit of dojo.
Context object
The context object is the object used to store content in the DTL toolkit of dojo. dojo "injects" this object into the template through some interfaces. In fact, context is a bit similar to real parameters. Let's look at a simple example:

Listing 1. Simple context example

 var context = new dojox.dtl.Context(   {foo: "foo", bar: "bar", get: function(key){ return key + "TEST"; }});  var tpl = new dojox.dtl.Template("{{ foo }}-{{ bar }}");  t.is("fooTEST-barTEST", tpl.render(context)); 

Here we initialize a context object and define its "get" method. Then we use this object to "fill" the template we created. Here, "{Foo}" and "{bar}" represent the "foo" and "bar" variables, so the final return value is "footest-bartest ". This is the collaborative working mode between context and template.
Let's look at an example of a content filter:

Listing 2. Context Filtering

 var context = new dojox.dtl.Context({ foo: "one", bar: "two", baz: "three" });  var filtered = context.filter("foo", "bar");  t.is(filtered.foo, "one");  t.is(filtered.bar, "two");  t.f(filtered.baz); 


 filtered = context.filter({ bar: true, baz: true });  t.f(filtered.foo);  t.is(filtered.bar, "two");  t.is(filtered.baz, "three"); 

 filtered = context.filter(new dojox.dtl.Context({ foo: true, baz: true }));  t.is(filtered.foo, "one");  t.f(filtered.bar);  t.is(filtered.baz, "three"); 

Here we provide three filtering examples:
1. "context. Filter (" foo "," bar ")": All attributes except "foo" and "bar" can be filtered out by attribute names.
2. "context. Filter ({bar: True, Baz: true})": You can also use True or false to filter.
3. "context. Filter (New dojox. DTL. Context ({FOO: True, Baz: true})": Filter a new context object.
In addition to filtering, our context object can also be extended:

Listing 3. Context Extension

 var context = new dojox.dtl.Context({ foo: "one" });  var extended = context.extend({ bar: "two", baz: "three" });  t.is(extended.foo, "one");  t.is(extended.bar, "two");  t.is(extended.baz, "three");  extended = context.extend({ barr: "two", bazz: "three" });  t.is(extended.foo, "one");  t.f(extended.bar);  t.f(extended.baz);  t.is(extended.barr, "two");  t.is(extended.bazz, "three");  t.f(context.bar)  t.f(context.baz);  t.f(context.barr);  t.f(context.bazz); 

Through the "extend" method, we can extend new attributes based on existing context objects. "Context. extend ({bar: "two", Baz: "three"}) "extends the" bar "and" Baz "attributes, whose values are" two "and" three ", respectively ". Note: The original context object (here it is the "context" variable) has not changed. The changed variable is the extended variable (here it is the "extended" variable ).
Text Template tag)
After the context object is introduced, let's talk about the template. Context content objects work together with template objects, and they are based on the DTL template language. Let's take a look at a simple text template example:
Listing 4. Simple Text Template

 var dd = dojox.dtl;  var template = new dd.Template(  '{% extends "../../dojox/dtl/tests/templates/pocket.html" %}   {% block pocket %}Simple{% endblock %}');  t.is("Simple Pocket", template.render()); 

Here we have created a template that contains "extends" and "Block", so it is obvious that here is a simple template inheritance syntax in DTL, using the subtemplate "pocket ": "{% block pocket %} simple {% endblock has been replaced to replace the parent Template into pocket.html" ("{% block pocket %} hot {% endblock %} pocket "). "Template. Render ()" is used to parse the syntax. The final result is "simple pocket", which fully complies with the parsing result of DTL syntax.
Let's take a look at several complex examples:

Listing 5. Advanced Simple Text Template

VaR dd = dojox. DTL; // pass 1 var context = new DD. context ({parent :".. /.. /dojox/DTL/tests/templates/pocket.html "}) template = new DD. template ('{% extends parent % }{% block pocket %} variabled {% endblock %}'); T. is ("variabled pocket", template. render (context); // The parameter is passed 2 context. parent = dojo. moduleurl ("dojox. DTL. tests. templates "," pocket.html "); template = new DD. template ('{% extends parent %} {% block pocket %} slightly more advanced {% endblock %}'); T. is ("slightly more advanced pocket", template. render (context); // The parameter is passed 3 context. parent = {URL: dojo. moduleurl ("dojox. DTL. tests. templates "," pocket.html ")} template = new DD. template ('{% extends parent % }{% block pocket %} super {% endblock %}'); T. is ("Super pocket", template. render (context ));

Three parameter passing methods are listed here. We don't need to write the path of the HTML file in the template as before. We can pass the context parameter to the template, either through moduleurl or an object with URL attributes.
In addition to passing the template HTML, context also supports passing real parameters in other ways:

Listing 6. Passing parameters in a Text Template

 var dd = dojox.dtl;  var context = new dd.Context({  parent: dojo.moduleUrl("dojox.dtl.tests.templates", "pocket2.html"),  items: ["apple", "banana", "lemon" ]  });  var template = new dd.Template(" {% extends parent %}{% block pocket %}My {{ item }}{% endblock %}");  t.is("(My apple) (My banana) (My lemon) Pocket", template.render(context)); 

There are two parameters: "parent" and "items". Let's take a look at the content of the parent template:

Listing 7. Parent template pocket2.html

  {% for item in items %}(  {% block pocket %}  Hot  {% endblock %}  ) {% endfor %}  Pocket 

According to the rules of DTL syntax, the block-"pocket" of the parent template replaces the block-"pocket" of the quilt template, and then parses the items parameter passed in by context, the final execution result should be: "(my apple) (my banana) (my lemon) pocket ".
In fact, we can also use "block. super "accesses the content of the parent template in the subtemplate:" {% extends parent % }{% block pocket %} My {item }}{ {block. super }}{% endblock % }".
Of course, DTL statements also support Annotations:
Listing 8. Text Template comment

  var template = new dd.Template(' Hot{% comment %}<strong>Make me disappear</strong>{% endcomment %} Pocket');  t.is("Hot Pocket", template.render()); 

Add comments using "{% comment %}" and "{% endcomment %}". The code in the comments will not be executed.
Let's take a look at the cycle Tag:

Listing 9. Text Template cycle label

 var context = new dd.Context({  items: ["apple", "banana", "lemon"],  unplugged: "Torrey" });  var template = new dd.Template(" {% for item in items %}{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' %}    Pocket. {% endfor %}");  t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context)); 

The cycle tag indicates the value of the loop in the list. Because "items" contains only three elements, the value here should be "Hot Pocket. diarrhea pocket. torrey pocket. ", the last" extra "won't be obtained.
Let's take a look at a slightly more complex example of cycle:

Listing 10. Advanced Text Template cycle label

 context = new dojox.dtl.Context({ unplugged: "Torrey" });  template = new dd.Template(" {% cycle 'Hot' 'Diarrhea' unplugged 'Extra' as steakum %}  Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket.");  t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket.", template.render(context)); 


Here, we use "as steakum" to define a reference for this cycle. In this way, we can reuse this cycle in future code, use "{% cycle steakum %}" to get the next value in its list.
Next we will introduce the "filter" tag:

Listing 11. Text Template filter tag

 var template = new dd.Template('  {% filter lower|center:"15" %}Hot Pocket{% endfilter %}');  t.is("  hot pocket   ", template.render()); 

The filter label is used to format text content. "{% filter lower | center:" 15 "%}" indicates converting the font to lowercase letters, center and retain 15 characters (space filling is not enough ).
Let's take a look at the "Firstof" tag:
Listing 12. Text Template Firstof tag

 var dd = dojox.dtl;  var context = new dd.Context({  found: "unicorn" });  var template = new dd.Template("{% firstof one two three four found %}");  t.is("unicorn", template.render(context));  context.four = null;  t.is("null", template.render(context));  context.three = false;  t.is("false", template.render(context)); 

"Firstof" here gets the first variable with a value, because only "found" is assigned a value, therefore, the "{% Firstof one two three four found %}" here should be "Unicorn". Of course, if you manually assign a value to the context variable, the running result of this statement will also change accordingly.
An example of the "include" label is as follows:

Listing 13. Text Template include tag

 var dd = dojox.dtl;  var context = new dd.Context({  hello: dojo.moduleUrl("dojox.dtl.tests.templates", "hello.html"),  person: "Bob",  people: ["Charles", "Ralph", "Julia"]  });  var template = new dd.Template("{% include hello %}");  t.is("Hello, <span>Bob</span>", template.render(context)); 

Like the "include" label in HTML, it is used to introduce external text content.

Listing 14. Text Template spaceless tag

var dd = dojox.dtl; var template = new dd.Template("{% spaceless %}<ul> \n <li>Hot</li> \n\n<li>Pocket </li>\n </ul>{% endspaceless %}"); t.is("<ul><li>Hot</li><li>Pocket </li></ul>", template.render()); 

Here the "spaceless" label is used to remove all spaces, leaving only non-space characters.
Then there are various labels supported by dojo, such as: For, if, ifchanged, ifequal, include, with, withratio, etc. Their syntax is the same as that supported by DTL, for more information about DTL syntax, see DTL syntax.
Text Template Filter)
Next we will introduce the filter. The filter in DTL is more of an auxiliary operation. Let's take a look at an example:

Listing 15. Add operations for text filtering

 var dd = dojox.dtl;  var context = new dd.Context({ four: 4 });  tpl = new dd.Template('{{ four|add:"6" }}');  t.is("10", tpl.render(context));  context.four = "4";  t.is("10", tpl.render(context));  tpl = new dd.Template('{{ four|add:"six" }}');  t.is("4", tpl.render(context));  tpl = new dd.Template('{{ four|add:"6.6" }}');  t.is("10", tpl.render(context)); 

Note the "add" Operation: "{four | add:" 6 "}". Because "context" specifies "four" as "4 ", therefore, the output here is "10 ".
In fact, the "add" operation has a wide range of compatibility, and it will forcibly convert the corresponding operation object. If not, it will implement the "add" operation in a default way, applicable to integer, decimal, or even array or list data.
Let's look at an example of "cut ".

Listing 16. text filtering cut operation

 var dd = dojox.dtl;  var context = new dd.Context({ uncut: "Apples and oranges" });  var tpl = new dd.Template('{{ uncut|cut }}');  t.is("Apples and oranges", tpl.render(context));  tpl = new dd.Template('{{ uncut|cut:"A" }}');  t.is("pples and oranges", tpl.render(context));  tpl = new dd.Template('{{ uncut|cut:" " }}');  t.is("Applesandoranges", tpl.render(context));  tpl = new dd.Template('{{ uncut|cut:"e" }}');  t.is("Appls and orangs", tpl.render(context)); 

"Cut" is mainly used to delete relevant characters. Here, "{uncut | cut:" A "}" is used to delete all "A" characters in the "uncut" variable value, note: It is case sensitive.

Listing 17. text filtering default

 var dd = dojox.dtl;  var context = new dd.Context();  tpl = new dd.Template('{{ empty|default }}');  t.is("", tpl.render(context));  tpl = new dd.Template('{{ empty|default:"full" }}');  t.is("full", tpl.render(context));  context.empty = "not empty";  t.is("not empty", tpl.render(context)); 

"Default": If a variable has a value, take the value of the variable; otherwise, take the value of "default.
The above are a few simple filtering operations. Let's look at a few more complex operations:

Listing 18. text filtering dictsort

 var dd = dojox.dtl;  var context = new dd.Context({  fruit: [  { name: "lemons", toString: function(){ return this.name; } },  { name: "apples", toString: function(){ return this.name; } },  { name: "grapes", toString: function(){ return this.name; } }  ]  });  tpl = new dd.Template('{{ fruit|dictsort|join:"|" }}');  t.is("lemons|apples|grapes", tpl.render(context));  tpl = new dd.Template('{{ fruit|dictsort:"name"|join:"|" }}');  t.is("apples|grapes|lemons", tpl.render(context)); 

"Dictsort" is mainly used for sorting. Here, "Fruit" is sorted and connected through "|" (join: "|"), so the result is "Lemons | apples | grapes ". If there are multiple attributes, you can specify the attribute sorting: | dictsort: "name", that is, sorting based on the "name" attribute.

Listing 19. text filtering truncatewords

 var dd = dojox.dtl;  var context = new dd.Context({ word: "potted meat writes a lot of tests" });  var tpl = new dd.Template("{{ word|truncatewords }}");  t.is(context.word, tpl.render(context));  tpl = new dd.Template('{{ word|truncatewords:"1" }}');  t.is("potted", tpl.render(context));  tpl = new dd.Template('{{ word|truncatewords:"2" }}');  t.is("potted meat", tpl.render(context));  tpl = new dd.Template('{{ word|truncatewords:20" }}');  t.is(context.word, tpl.render(context));  context.word = "potted \nmeat   \nwrites  a lot of tests";  tpl = new dd.Template('{{ word|truncatewords:"3" }}');  t.is("potted \nmeat   \nwrites", tpl.render(context)); 

As the name suggests, the "truncatewords" operation is mainly used to intercept text: "{word | truncatewords:" 2 "}" is equivalent to intercepting the first two texts, so the result is "Potted meat ", this operation is often used in our daily development, especially in page layout.
There are many other operations supported by dojo for filters, such as filesizeformat, fix_ampersands, iriencode, pluralize, removetags, slice, and urlencode. Their syntaxes are the same as those of DTL, if you are interested, you can refer to DTL's filter-related content. We will not describe it here.
Dom Template
Some of the labels and filters described earlier are text-based. Next we will introduce some of the dom-related labels and filter interfaces of the DTL toolkit of dojo, these interfaces will default that your template is in the standard HTML format. If not, it will detect and throw an exception. These interfaces are ideal for seamlessly integrating DTL-based HTML templates that we have previously written into dojo.

Listing 20. Dom template Error Detection

 var dd = dojox.dtl;  var template;  var found = false;  try {  template = new dd.DomTemplate('No div');  dd.tests.dom.util.render(template);  }catch(e){  t.is("Text should not exist outside of the root node in template", e.message);  found = true;  }  t.t(found);  t.is("potted meat", tpl.render(context));  template = new dd.DomTemplate('<div></div>extra content');  found = false;  try {  dd.tests.dom.util.render(template);  }catch(e){  t.is("Content should not exist outside of the root node in template", e.message);  found = true;  }  t.t(found); 

Here our content is "No Div", which obviously does not comply with HTML specifications. Therefore, the dojo interface throws an exception: "text cannot exist outside the root node ". The same is true for "<div> </div> extra content.
Let's take a look at two examples of errors:

Listing 21. Dom template error detection (advanced tutorial)

 template = new dd.DomTemplate('<div></div><div></div>');  found = false;  try {  dd.tests.dom.util.render(template);  }catch(e){  t.is("Content should not exist outside of the root node in template", e.message);  found = true;  }  t.t(found);  template = new dd.DomTemplate('{% if missing %}<div></div>{% endif %}');  found = false;  try {  dd.tests.dom.util.render(template);  }catch(e){  t.is("Rendered template does not have a root node", e.message);  found = true;  }  t.t(found); 

It can be seen that "<div> </div>", which does not have an independent root node, or contains a redundant root node, is not allowed. Similarly, "{% if missing %} <div> </div> {% endif %}" is not allowed if logical control exists outside the root node.
We can use the DTL language as much as possible to build "dynamic" HTML pages for us. Here is an example of element attributes:

Listing 22. Dom template element attributes

 var dd = dojox.dtl;  var template = new dd.DomTemplate(' <div>{% for item in items %}<a index="{{forloop.counter0}}"  id="id_{{item.param}}">{{item.param}}</a>{% endfor %}</div>');  var context = new dd.Context({  items: [  {  name: "apple",  param: "appleparam" },  {  name: "banana",  param: "bananaparam" },  {  name: "orange",  param: "orangeparam" }  ]  });  doh.is('<div><a index="0" id="id_appleparam">appleparam</a><a index="1"  id="id_bananaparam">bananaparam</a><a index="2"   id="id_orangeparam">orangeparam</a></div>',   dd.tests.dom.util.render(template, context)); 

As you can see, the various attributes of the HTML element can be constructed through variables and logic: "<a Index =" {forloop. counter0 }}" id = "ID _ {item. param} ">" is an example of building the "Index" attribute and "ID" attribute.
Of course, you can also add custom attributes:

Listing 23. Dom template element Custom Attributes

 var dd = dojox.dtl;  var context = new dd.Context({frag: {start: 10, stop: 20}});  var template = new dd.DomTemplate(' <div startLine="{{ frag.start }}" stopLine="{{ frag.stop }}">abc</div>');  doh.is(' <div startline="10"  stopline="20">abc</div>',  dd.tests.dom.util.render(template, context)); 

Note that the nested context is defined here, so we should also use the "{frag. Start}" method when using it.
There are still many tags and filters related to Dom templates. Here we will not introduce them one by one. Interested readers can refer to the DTL Use Cases of dojo.

DTL-based Widgets
We have discussed how to use the basic interface of DTL. Next we will introduce an advanced usage of DTL: Build a custom widget based on DTL templates.
We know that every widget in Dojo usually has an HTML template to build the initial basic structure of the widget. However, sometimes our widgets are relatively large and complex, which leads to complicated HTML templates of our widgets. Because the HTML templates of widgets are relatively static, therefore, if the HTML template of the widget is complex, the amount of HTML code of the template will increase dramatically. If we can introduce DTL into the template, so that our template has certain logic control capabilities, that is, "dynamic" templates, this can greatly simplify the complexity of our template HTML code, this makes the code easier to maintain and reduces the bandwidth required by the Network request HTML template to improve network performance.

Listing 24. DTL-based Widgets

 dojo.declare("Fruit", [dijit._WidgetBase, dojox.dtl._DomTemplated], {  widgetsInTemplate: true,  items: ["apple", "banana", "orange"],  keyUp: function(e){  if((e.type == "click" || e.keyCode == dojo.keys.ENTER) &&  this.input.value){  console.debug(this.button);  var i = dojo.indexOf(this.items, this.input.value);  if(i != -1){  this.items.splice(i, 1);  }else{  this.items.push(this.input.value);  }  this.input.value = "";  this.render();  }  },  templateString: dojo.cache("dojox.dtl.demos.templates", "Fruit.html"),  }); 

Note the "items" parameters here: "items: [" apple "," banana "," orange "]" and "templatestring" parameters, the content of the "items" variable is injected into the template of the widget's javasfruit.html to construct the final HTML template of the widget. For details, refer to the following content:

List 25. DTL-based HTML Template

 <div>     <input dojoAttachEvent="onkeyup: keyUp" dojoAttachPoint="input">     <button dojoType="dijit.form.Button" dojoAttachPoint="button"     dojoAttachEvent="onClick: keyUp">         Add/Remove Item     </button>     <div id="pane" dojoType="dijit.layout.ContentPane parsed">         <ul>             {% for item in items %}             <li>                 <button dojoType="dijit.form.Button parsed" title="Fruit: {{ item }}"                 otherAttr2="x_{{item}}">                     {{ item }}                     <script type="dojo/connect" event="onClick" args="e">                     console.debug("                    You clicked", this.containerNode.innerHTML);</' + 'script>                 </button>             </li>             {% endfor %}         </ul>     </div>  </div> 

As you can see, "{% for item in items %}" will traverse the "items" member variable in our "Fruit" widget, build the final template of the "Fruit" widget.

Conclusion

This article introduces some features of the DTL toolkit in Dojo. First, we start with the DTL language, introduce the source, basic rules and features of the DTL language, and then introduce the DTL toolkit of dojo, in addition, we gradually introduced various objects and interfaces of the DTL toolkit of dojo, such as context object, template object, and render method. The features and usage of these interfaces are described in terms of text tags, text filters, and Dom templates. Finally, this article describes how to build DTL-based widgets Based on the DTL toolkit of dojo. These interfaces are very helpful for our daily development. We recommend that you pay more attention to them at ordinary times.

This article is first published in IBM developer works: http://www.ibm.com/developerworks/cn/web/1206_zhouxiang_dojodtl/

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.