ToolBox Files: Difference between revisions

From NSB App Studio
Jump to navigation Jump to search
 
(27 intermediate revisions by the same user not shown)
Line 1: Line 1:
The Toolbox files describe controls to the IDE. They are used to create entries in the Toolbox window and to describe the operation of the control to the IDE. The files reside in:
The Toolbox files describe controls to the IDE. They are used to create entries in the Toolbox window and to describe the operation of the control to the IDE. The files reside in:
* Windows: \program files\nsbasic\appstudio\toolbox
* Windows: \Program Files\NSB AppStudio\toolbox
* Mac: Applications/AppStudio.app/Contents/Resources/toolbox
* Mac: Applications/AppStudio.app/Contents/MacOS/toolbox
You are welcome to create your own ToolBox files - but keep a copy outside of the above directories. The file will be wiped out when you install a new version of AppStudio. If you have come up with a good one, send it to us: we'll test it and perhaps make it part of the AppStudio distribution.
You are welcome to create your own Toolbox files - but do not make changes in the above directories. Instead, save your new and modified Toolbox files to a directory named "AppStudio Toolbox" in your Documents folder. You can specify a different location in the Advanced tab of [[Preferences]].
 
Your Toolbox files will be loaded on starting AppStudio. If your files have the same name as existing ones, yours will take precedence. Restart AppStudio after modifying your Toolbox files for your changes to take effect.
 
Feel free to share your improvements and new controls with us - we will make them available to other users!


Here is an annotated tour through one of the ToolBox files: Button_jqm.js. We will look at the file for the [http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxbutton/index.htm jqWidgets Button] control:
Here is an annotated tour through one of the ToolBox files: Button_jqm.js. We will look at the file for the [http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxbutton/index.htm jqWidgets Button] control:


The file is formatted as a JSON structure. They are loaded into the IDE at startup. It's important to keep the syntax correct: the control will not load properly if there are any errors. If you make changes to the file, you need to restart the IDE to see the effect. You can edit the file in a standard text editor, or copy it into an [http://www.jsoneditoronline.org online JSON editor].
The file is formatted as a JSON structure. They are loaded into the IDE at startup. It's important to keep the syntax correct: the control will not load properly if there are any errors. If you make changes to the file, you need to restart the IDE to see the effect. You can edit the file in a standard text editor, or copy it into an [https://jsoneditoronline.org/ online JSON editor].


=== Elements of a ToolBox File ===
=== Elements of a ToolBox File ===
Line 15: Line 19:
"_type": "Button_jqw",  
"_type": "Button_jqw",  
</pre>
</pre>
The base class of the control. There is also a Widget.js file in the ToolBox: this control starts with what is in that file and builds on it. Widget is a simple definition that is good for building on:
The list of base classes of the control. There is also a Widget.js file in the ToolBox: this control starts with what is in that file and builds on it. Widget is a simple definition that is good for building on. We also add jqxAll, a file which contains properties which are in all jqx controls. It's in the properties subfolder. If you want to set up your own subfolder for bases classes, go ahead: it will be picked up automatically when AppStudio restarts.
<pre>
<pre>
"_base": "Widget",  
"_base": ["jqxAll","Widget"],  
</pre>
</pre>
Controls are categorized by palette number. For use defined controls, this is usually 4:
Controls are categorized by palette number. For user defined controls, this is usually 4:
<pre>
<pre>
"_palette": 4,  
"_palette": 4,  
Line 25: Line 29:
The name of the icon to use for the control. Should be a 16x16 .png file, with transparency for surrounding white space.
The name of the icon to use for the control. Should be a 16x16 .png file, with transparency for surrounding white space.
<pre>
<pre>
"_art": "images/extension.png",  
"_art": "images/jqxbutton.png",  
</pre>
</pre>
The shorthelp is displayed under the Properties Window when the control is selected. Can be any text.
The shorthelp is displayed under the Properties Window when the control is selected. Can be any text. It can be HTML formatted and include external links.
<pre>
<pre>
"_shorthelp": "Buttons.  jqWidgets",  
"_shorthelp": "Buttons.  jqWidgets",  
Line 42: Line 46:
<pre>
<pre>
"_requiredfiles": [
"_requiredfiles": [
     "nsb/jquery.js",
     "{_nsbdir}nsb/jquery.js",
     "http://jqwidgets.com/public/jqwidgets/styles/jqx.base.css",
     "http://jqwidgets.com/public/jqwidgets/styles/jqx.base.css",
     "http://jqwidgets.com/public/jqwidgets/styles/jqx.{theme}.css",
     "http://jqwidgets.com/public/jqwidgets/styles/jqx.{theme}.css",
Line 98: Line 102:
     },
     },


<pre> 
"name": "",  
"name": "",  
"_name": {  
"_name": {  
Line 208: Line 211:
     "#{id} {{position:absolute; left:{left}px; top:{top}px; height:{height}px; width:{width}px}}",  
     "#{id} {{position:absolute; left:{left}px; top:{top}px; height:{height}px; width:{width}px}}",  
</pre>
</pre>
The htmltemplate lays out the html for the control. It's placed at the top of the app, so it is executed when the app is first loaded. It uses the same substitution tricks as csstemplate. If you want to execute a script to generate the HTML, you can include it in &lt;script> tags.
The htmltemplate lays out the html for the control. It's placed at the top of the app, so it is executed when the app is first loaded. It uses the same substitution tricks as csstemplate. If you want to execute a script to generate the HTML, you can call a function which returns the HTML.
<pre>
<pre>
"_htmltemplate":  
"_htmltemplate":  
     "<input type='button' id='{id}' {hidden}{disabled} style='{style}' name='{name}' value='{value}' data-role='none'>",
     "\"<input type='button' id='{id}' {hidden}{disabled} style='{style}' name='{name}' value='{value}' data-role='none'>\",",
</pre>
</pre>
<pre>
"_htmltemplate": "  NSB.bs.dropdown.make('{id}', '{value}', '{dropdown}', '{blockLevel} {class}', '{disabled}', '{_fontcss!i}{_bordercss!i}{_margincss!i}{_paddingcss!i}{_colorscss!i}{hidden}{style!j}', '{_fontcss!i}{_bordercss!i}{_margincss!i}{_paddingcss!i}{_colorscss!i}{hidden}{style!j}', '{appearance}', '{outline}', '{size}', '{icon}', '', '{align}', '{items!j}', '{grouping}', '{groupStyle}', '{_bsBadge!i}', '{_bsPopover2!i}', '{filter}', '{filterPlaceholder}'),",
</pre>
jstemplate is some optional JavaScript code that is executed once all the controls are created. It uses the same substitution tricks. Any valid JavaScript can be used here.
jstemplate is some optional JavaScript code that is executed once all the controls are created. It uses the same substitution tricks. Any valid JavaScript can be used here.
<pre>
<pre>
Line 220: Line 227:
</pre>
</pre>
And that brings us to the end of the file. One more thing: You can use multiple lines in any of the templates by using an array of strings, one string per line. (The requiredfiles element above is an example of this.)
And that brings us to the end of the file. One more thing: You can use multiple lines in any of the templates by using an array of strings, one string per line. (The requiredfiles element above is an example of this.)
=== Hiding controls from jQuery Mobile ===
jQuery Mobile's CSS will enhance all the controls in your project - not just jQuery Mobile controls. To stop this from happening, add this to the outmost element of the control:
<pre>
data-role='none' data-enhance='false'
</pre>


== Advanced Templating ==
== Advanced Templating ==


There are several advanced templating techniques available to help make writing templates easier and more concise.
There are several advanced templating techniques available to help make writing templates easier and more concise.
=== Preventing Translation ===
To prevent a field from being picked up for translation (internationalization), add the following property to an item:
<pre>
"i18n": false,
</pre>
=== Grouping Properties ===
If you add a "group" element to a property, the property will be grouped with other properties of the same group. A heading will display for the group.
<pre>
"group": "Borders",
</pre>
[[File:Propertygroup.png]]
=== Common Properties ===
Some properties are shared by multiple controls. Common Property files let you define these properties in a file which is shared by the controls. To do this, put the properties you want to share into a JSON file in the ToolBox/properties folder. Here's the borders.js file which contains the properties for borders:
<pre>
{
"_type": "borders",
"_base": "NSBObject",
"borderStyle": "solid",
"_borderStyle": {
    "group": "Borders",
    "acignore": true,
    "desc": "Border Style",
    "type": "enum",
    "keys": ["","dotted","dashed","solid","double","groove","ridge","inset","outset"],
    "values": ["","dotted","dashed","solid","double","groove","ridge","inset","outset"]
    },
   
"borderWidth": "",
"_borderWidth": {
    "group": "Borders",
    "acignore": true,
    "desc": "Border width",
    "type": "str"
    },
   
"borderColor": "gray",
"_borderColor": {
    "group": "Borders",
    "acignore": true,
    "desc": "Color of border. Can be name, #RRGGBB or rgb(R,G,B).",
    "type": "str"
  }
}
</pre>
To add these properties to a control, add "borders" to the controls's "_base" property:
<pre>
"_base": ["borders","NSBForm"],
</pre>
=== Hiding Properties ===
<pre>
"_onclick": {"type": "hidden"}
</pre>


=== Conditionals ===
=== Conditionals ===
Line 233: Line 309:


<pre>
<pre>
  " {if ready <> ''}ready:function(){{ {ready} }},{/if}",
  "{if ready <> ''} ready:function(){{ {ready} }},{/if}",
  " {if alignVertical == 'center'}{id}.style.lineHeight={height}+'px'; {/if}",
  "{if alignVertical == 'center'} {id}.style.lineHeight={height}+'px'; {/if}",
"  right:{right}{if isinstance(right, int) or right.isdigit()}px{/if}"
"  right:{right}{if isinstance(right, int) or right.isdigit()}px{/if}"
"{if scrolling == 'true'}  {id}_ref = new iScroll('{id}_scroller',{{ {scroll_options} }});{/if}"
</pre>


Conditionals test the exp for Trueness. Use == for equality <> for not equal.
Python functions can be used in the expressions.
<pre>
class='btn{eval appearance[0:5] + outline + appearance[5:]}{size}{blockLevel} {class}'
</pre>
</pre>
Conditionals test the exp for Trueness. Use == for equality.


=== Iteration ===
=== Iteration ===
Line 262: Line 343:
* <code>!j</code> - JavaScript string encoding.  Single quotes, double quotes, backslashes, and unicode characters are escaped.
* <code>!j</code> - JavaScript string encoding.  Single quotes, double quotes, backslashes, and unicode characters are escaped.
* <code>!h</code> - HTML encoding.  Ampersands, single quotes, double quotes, greater than signs, and less than signs, are escaped.
* <code>!h</code> - HTML encoding.  Ampersands, single quotes, double quotes, greater than signs, and less than signs, are escaped.
* <code>!b</code> - Both: JavaScript + HTML encoding
* <code>!p</code> - For positions. Add 'px' to a position when needed.
* <code>!i</code> - Do an immediate substitution and return the result. Lets you put expressions in properties. See how Form.js uses border.js.
=== Parent ===
You can test a value in the parent of the control. For a control, that would mean the container or form it is in. For a form, that would be the project.
<pre>
  {if _parent.firstform} == id}  console.log("first form!");{/if}
</pre>


=== More Information ===
=== More Information ===


The formatting language is extension of the standard Python format operator.  For more information on even more advanced techniques, including output formatting, please see: http://docs.python.org/2.7/library/string.html#format-string-syntax
The formatting language is extension of the standard Python format operator.  For more information on even more advanced techniques, including output formatting, please see: http://docs.python.org/2.7/library/string.html#format-string-syntax

Latest revision as of 16:13, 12 September 2022

The Toolbox files describe controls to the IDE. They are used to create entries in the Toolbox window and to describe the operation of the control to the IDE. The files reside in:

  • Windows: \Program Files\NSB AppStudio\toolbox
  • Mac: Applications/AppStudio.app/Contents/MacOS/toolbox

You are welcome to create your own Toolbox files - but do not make changes in the above directories. Instead, save your new and modified Toolbox files to a directory named "AppStudio Toolbox" in your Documents folder. You can specify a different location in the Advanced tab of Preferences.

Your Toolbox files will be loaded on starting AppStudio. If your files have the same name as existing ones, yours will take precedence. Restart AppStudio after modifying your Toolbox files for your changes to take effect.

Feel free to share your improvements and new controls with us - we will make them available to other users!

Here is an annotated tour through one of the ToolBox files: Button_jqm.js. We will look at the file for the jqWidgets Button control:

The file is formatted as a JSON structure. They are loaded into the IDE at startup. It's important to keep the syntax correct: the control will not load properly if there are any errors. If you make changes to the file, you need to restart the IDE to see the effect. You can edit the file in a standard text editor, or copy it into an online JSON editor.

Elements of a ToolBox File

The name of the control. This isn't shown anywhere. It must be unique. Elements that begin with "_" do not appear in the Properties Windows. These are usually put at the beginning of the file:

{
"_type": "Button_jqw", 

The list of base classes of the control. There is also a Widget.js file in the ToolBox: this control starts with what is in that file and builds on it. Widget is a simple definition that is good for building on. We also add jqxAll, a file which contains properties which are in all jqx controls. It's in the properties subfolder. If you want to set up your own subfolder for bases classes, go ahead: it will be picked up automatically when AppStudio restarts.

"_base": ["jqxAll","Widget"], 

Controls are categorized by palette number. For user defined controls, this is usually 4:

"_palette": 4, 

The name of the icon to use for the control. Should be a 16x16 .png file, with transparency for surrounding white space.

"_art": "images/jqxbutton.png", 

The shorthelp is displayed under the Properties Window when the control is selected. Can be any text. It can be HTML formatted and include external links.

"_shorthelp": "Buttons.  jqWidgets", 

Controls in the ToolBox are grouped by Category. This defines which categories the control belongs too. If more than one, use a comma separated list. The categories must be defined in Toolbox.js.

"_category": ["jqWidgets"],

Is the control resizable in the Design Screen?

"_resizable": true,

List of files that the control requires. In this example, jQuery is in the project folder, in nsb, while the other files come from the jqWidgets server. AppStudio will take care of bundling the files into the app.

"_requiredfiles": [
    "{_nsbdir}nsb/jquery.js",
    "http://jqwidgets.com/public/jqwidgets/styles/jqx.base.css",
    "http://jqwidgets.com/public/jqwidgets/styles/jqx.{theme}.css",
    "http://jqwidgets.com/public/jqwidgets/jqxcore.js",
    "http://jqwidgets.com/public/jqwidgets/jqxbuttons.js",
    "http://jqwidgets.com/public/jqwidgets/styles/images/bg_blueenergy.png",
    "http://jqwidgets.com/public/jqwidgets/styles/images/bg_darkblue.png",
    "http://jqwidgets.com/public/jqwidgets/styles/images/bg_black.png"
    ],

This is the name used to construct the id of the new control. It appears in the Project Explorer.

"_displayname": "Button",

This field isn't used yet.

"_longhelp": "longhelp",

This next section is optional (and not from Button.js - it's borrowed from Grid.js). It provides the items which pop up in the code window after you type a control name and a period.

"_acprops": {
    "addCols(n)": {"desc": "Add n cols to the right of the table. Default is 1."},
    "addRows()": {"desc": "Add n rows to the end of the table. Default is 1."},
    "cell(row,col)": {"desc": "Return a reference to cell."},
    "setValue(row,col,val)": {"desc": "Set value of cell."}
},

Some optional settings. These are actually defined in widgets.js, but they can be overridden for a particular control. If _singular is true, there can only be one instance on a form: an example would be a Headerbar. _designTemplate can be used for controls whose bounds do not get drawn properly by default.

"__size": 10, 
"__fontweight": "bold", 
"__fontsize": 12, 
"__textalign": "center" 
"_resizable": true,
"_draggable": true,
"_singular": false,
"_design_jstemplate": {
  "left": 0,
  "top": 0,
  "width": 0,
  "height": 0}

Now, we start the elements which will appear in Project Properties. "class" is for the names of any styling classifications. It is actually defined in Widgets.js.

"class": "",

The id of a control defaults to _displayname + n, where n is the number of occurrences of the control. Each of the project properties will be defined by a structure like this one. As we see more of these, we will discuss the options. This is the simplest one: the type is "str", which means the field accepts a simple string input. The desc field will appear in the description area under the Properties Window. The id property is followed by a number of other str type properties which are straightforward. The default value of the element, if any, is in the first line of the element definition.

"id": "", 
"_id": { 
    "desc": "Unique button identifier", 
    "type": "str" 
    },

"name": "", 
"_name": { 
    "desc": "Key in submitted form", 
    "type": "str" 
    }, 
    
"value": "Button", 
"_value": { 
    "desc": "The caption of the button", 
    "type": "str" 
    }, 
 

Here we see a couple of additional options. Type 'css' will bring up a textarea to edit the string. Use this for multiline or large string elements. We also see the "actype" option. It stands for autocomplete: this is used by the Code Window to display autocomplete options.

   
"style": "", 
"_style": { 
    "actype": "Style",
    "desc": "Styling rules for element", 
    "type": "css" 
    }, 

This introduces the 'int' type. It's as simple a 'str', but will only accept integers. The acignore option indicates there is no autocomplete for this.

"top": 0, 
"_top": { 
    "acignore": true,
    "desc": "Location of top of element", 
    "type": "int" 
    }, 

"left": 0, 
"_left": { 
    "acignore": true,
    "desc": "Location of left side of element", 
    "type": "int" 
    }, 

"height": 32, 
"_height": { 
    "acignore": true,
    "desc": "Vertical size of element", 
    "type": "int" 
    }, 

"width": 100, 
"_width": { 
    "acignore": true,
    "desc": "Horizontal size of element", 
    "type": "int" 
    }, 

The 'enum' type is used when there is a list of possible values for the control. "keys" are the choices which are shown in the Properties Window. "Values" are the corresponding values to be used in the actual app. The first line has the initial value, which must be one of the elements in "values". In this case, the initial value is "", the second element in "values".

"hidden": "", 
"_hidden": { 
    "desc": "Hide control", 
    "type": "enum", 
    "keys": ["True", ""], 
    "values": ["hidden='true';",""]
}, 

"theme": "classic",
"_theme": { 
    "desc": "Color theme for control.", 
    "type": "enum", 
    "keys": ["classic","darkblue","energyblue","shinyblack","summer","black","fresh","highcontrast","ui-darkness","ui-lightness","ui-le-frog","ui-overcast","ui-redmond","ui-smoothness","ui-start","ui-sunny"], 
    "values": ["classic","darkblue","energyblue","shinyblack","summer","black","fresh","highcontrast","ui-darkness","ui-lightness","ui-le-frog","ui-overcast","ui-redmond","ui-smoothness","ui-start","ui-sunny"]
    }, 

"roundedCorners": "jqx-rc-all",
"_roundedCorners": { 
    "desc": "Which corners should be rounded?", 
    "type": "enum", 
    "keys": ["All","Top","Bottom","Left","Right","Top-Right","Top-Left","Bottom-Right",
    "Bottom-Left"], 
    "values": ["jqx-rc-all","jqx-rc-t","jqx-rc-b","jqx-rc-r","jqx-rc-l","jqx-rc-tr","jqx-rc-tl","jqx-rc-br","jqx-rc-bl"]
    }, 

"buttonType": "Button",
"_buttonType": { 
    "desc": "Type of jqWidgets button", 
    "type": "enum", 
    "keys": ["Button","RepeatButton","LinkButton","ToggleButton"], 
    "values": ["Button","RepeatButton","LinkButton","ToggleButton"]
    }, 

"delay": 50,
"_delay": { 
    "acignore": true,
    "desc": "Time between two click events.", 
    "type": "int" 
   }, 

"disabled": "false", 
"_disabled": { 
    "desc": "Control disabled?", 
    "type": "enum", 
    "keys": ["False", "True"], 
    "values": ["false","true"]
    }, 

The csstemplate lays out a css definition for the control. In most cases, the following is sufficient. Notice things like {id} and {left}? At runtime, they get replaced by the values of the controls id and left properties. What if you need using a { or } bracket, other than for a substitution? In that case, double them up. {{ will become {, and }} will become }. This definition is placed the <head> section of the output.

At runtime the following statement would then be #Button1 {position:absolute; left:109px; top:273px; height:32px; width:100px}.

"_csstemplate": 
    "#{id} {{position:absolute; left:{left}px; top:{top}px; height:{height}px; width:{width}px}}", 

The htmltemplate lays out the html for the control. It's placed at the top of the app, so it is executed when the app is first loaded. It uses the same substitution tricks as csstemplate. If you want to execute a script to generate the HTML, you can call a function which returns the HTML.

"_htmltemplate": 
    "\"<input type='button' id='{id}' {hidden}{disabled} style='{style}' name='{name}' value='{value}' data-role='none'>\",",
"_htmltemplate": "  NSB.bs.dropdown.make('{id}', '{value}', '{dropdown}', '{blockLevel} {class}', '{disabled}', '{_fontcss!i}{_bordercss!i}{_margincss!i}{_paddingcss!i}{_colorscss!i}{hidden}{style!j}', '{_fontcss!i}{_bordercss!i}{_margincss!i}{_paddingcss!i}{_colorscss!i}{hidden}{style!j}', '{appearance}', '{outline}', '{size}', '{icon}', '', '{align}', '{items!j}', '{grouping}', '{groupStyle}', '{_bsBadge!i}', '{_bsPopover2!i}', '{filter}', '{filterPlaceholder}'),",

jstemplate is some optional JavaScript code that is executed once all the controls are created. It uses the same substitution tricks. Any valid JavaScript can be used here.

"_jstemplate": 
    "$('#{id}').jqx{buttonType}({{theme:'{theme}', width:{width}, height:{height}, roundedCorners:'{roundedCorners}', delay:{delay}, disabled:{disabled} }});"
}

And that brings us to the end of the file. One more thing: You can use multiple lines in any of the templates by using an array of strings, one string per line. (The requiredfiles element above is an example of this.)

Hiding controls from jQuery Mobile

jQuery Mobile's CSS will enhance all the controls in your project - not just jQuery Mobile controls. To stop this from happening, add this to the outmost element of the control:

data-role='none' data-enhance='false'

Advanced Templating

There are several advanced templating techniques available to help make writing templates easier and more concise.

Preventing Translation

To prevent a field from being picked up for translation (internationalization), add the following property to an item:

"i18n": false,

Grouping Properties

If you add a "group" element to a property, the property will be grouped with other properties of the same group. A heading will display for the group.

"group": "Borders",

Common Properties

Some properties are shared by multiple controls. Common Property files let you define these properties in a file which is shared by the controls. To do this, put the properties you want to share into a JSON file in the ToolBox/properties folder. Here's the borders.js file which contains the properties for borders:

{
"_type": "borders",
"_base": "NSBObject",

"borderStyle": "solid", 
"_borderStyle": { 
    "group": "Borders",
    "acignore": true,
    "desc": "Border Style", 
    "type": "enum", 
    "keys": ["","dotted","dashed","solid","double","groove","ridge","inset","outset"],
    "values": ["","dotted","dashed","solid","double","groove","ridge","inset","outset"] 
    }, 
    
"borderWidth": "", 
"_borderWidth": { 
    "group": "Borders",
    "acignore": true,
    "desc": "Border width", 
    "type": "str"
    }, 
    
"borderColor": "gray",
"_borderColor": { 
    "group": "Borders",
    "acignore": true,
    "desc": "Color of border. Can be name, #RRGGBB or rgb(R,G,B).", 
    "type": "str" 
   }
}

To add these properties to a control, add "borders" to the controls's "_base" property:

"_base": ["borders","NSBForm"],

Hiding Properties

 "_onclick": {"type": "hidden"}

Conditionals

    {if exp}
      conditional text
    {/if}
 "{if ready <> ''}  ready:function(){{ {ready} }},{/if}",
 "{if alignVertical == 'center'}  {id}.style.lineHeight={height}+'px'; {/if}",
 "  right:{right}{if isinstance(right, int) or right.isdigit()}px{/if}"
 "{if scrolling == 'true'}  {id}_ref = new iScroll('{id}_scroller',{{ {scroll_options} }});{/if}"

Conditionals test the exp for Trueness. Use == for equality <> for not equal.

Python functions can be used in the expressions.

class='btn{eval appearance[0:5] + outline + appearance[5:]}{size}{blockLevel} {class}'

Iteration

    {list exp}
      item {$} is {exp[$]}
    {/list}

Nesting is possible, but in the case of nested lists, $ is bound to the list that immediately preceeds it.

Lists expect exp to be indexable - a list or a object.

Conversions

You can include an exclamation point (!) after the replacement field name to trigger a conversion. For example:

    <script>exampleFunc('{css!j}');</script>

The following modes are available:

  • !j - JavaScript string encoding. Single quotes, double quotes, backslashes, and unicode characters are escaped.
  • !h - HTML encoding. Ampersands, single quotes, double quotes, greater than signs, and less than signs, are escaped.
  • !b - Both: JavaScript + HTML encoding
  • !p - For positions. Add 'px' to a position when needed.
  • !i - Do an immediate substitution and return the result. Lets you put expressions in properties. See how Form.js uses border.js.

Parent

You can test a value in the parent of the control. For a control, that would mean the container or form it is in. For a form, that would be the project.

  {if _parent.firstform} == id}  console.log("first form!");{/if}

More Information

The formatting language is extension of the standard Python format operator. For more information on even more advanced techniques, including output formatting, please see: http://docs.python.org/2.7/library/string.html#format-string-syntax