webCOMAND

cTemplate Versions

cTemplate has evolved over time to provide more features and functionality.  The following documentation is designed to bring developers that have used past versions of cTemplate up to speed with new features.

cTemplate 1.0

Basic procedure language, formerly known as COMAND Script.

#INSERT(Template,Header)
<ul>
#LIST(Contacts)
	<li><a href="#LINK(Contact,ID=$ID)">$Name</a></li>
#ENDLIST
</ul>
#INSERT(Template,Footer)

cTemplate 1.1

The following new statements were added in version 1.1, released with webCOMAND 3.0.

#CQL

cQL query support is provided using a statement similar to #SQL, except it accepts a cQL query.

#CQL($Results,"SELECT Name FROM Contacts+")
#LIST($Results)
$Name
#ENDLIST

#CPATH

cPath support is provided using a statement similar to #SQL, except it accepts cPath.

#CPATH($Results,"/Users/John//[:Contacts+]")
#LIST($Results)
$Name
#ENDLIST

$this

cTemplate exposes a $this variable inside #CONTEXT and #LIST blocks, as well as from within a #INSERT and Publication Procedure to access the object, in addition to its field values.

#CQL($Results,"FROM Contacts+")
#LIST($Results)
	#INSERT(Contact,$this)
#ENDLIST

#EACH ("for each")

#EACH now provides "for each" style loops.

#CQL($Results,"FROM Contacts+")
#EACH($Results,$Result)
		$Name
#ENDEACH

#APPEND Separator

#APPEND now accepts an optional second parameter that will be used as a separator between existing text and the new appended text, only if there was existing text.

#CQL($Results,"FROM Contacts+")
#NEW($Names)#ENDNEW
#LIST($Results)
	#APPEND($Names,', ')$Name#ENDAPPEND
#ENDLIST

Simplified Quotes

cTemplate 1.0 required multiple sets of quotes to define a string inside #ASSIGN and #IF.  This has been simplified in cTemplate 1.1.

#ASSIGN($Variable,"String")
#ASSIGN($Variable,'String')

Editor Hints

With the introduction of the COMAND API, a new family of #EDIT* cTemplate statements were added, which add metadata that can be picked up by editor apps to provide more intelligent editing capabilities, typically within a web page. Sites is the first app to use this feature for editing web page content inline.

The two most commonly used #EDIT* statements are:

  • #EDITABLE($Variable,Options) - Identifies an object field to be editable. Inline editors will use the surrounding parent element in the mark-up as the editable area. Options is a space-separated list of flags and commands that can influence output in edit, staging and live output. For example, "hide" will make the specified object field editable in the area, but does not actually output the value.
  • #EDITAREA() ... #ENDEDITAREA - Introduces a surrounding element in the mark-up to serve as the container for #EDIT* statements within the #EDITAREA block. This is useful when the mark-up does not provide a suitable surrounding element.
<!DOCTYPE html>
<html>
	<head><title>$Title</title></head>
	<body>
		<h1>#EDITABLE($Title)</h1>
		#EDITAREA()
			#EDITABLE($Text)
		#ENDEDITAREA
	</body>
</html>

In edit mode, the cTemplate above will resolve to the following HTML.

<!DOCTYPE html>
<html>
	<head><title>Page Title</title></head>
	<body>
		<h1><x-editable id="edit-1"/>Page Title</h1>
		<x-editarea id="edit-2">
			<x-editable id="edit-3"/><p>Paragraph text.</p>
			<p>Each paragraph is surrounded by a p tag.</p>
		</x-editarea>
	</body>
</html>

Each #EDIT* statement will resolve to an <x-edit*> tag with a unique "edit-#" ids in the HTML.

A web application can select and style <x-edit*> tags and "edit-#" ids with JavaScript and CSS.

#EDITAREA blocks must be considered in CSS because they will add <x-editarea> tags (or custom tags if specified), which may cause issues with CSS selectors.

In the example above, if the value of $Text contains HTML <p> tags, the following CSS would not apply as expected in edit mode because <x-editarea>...</x-editarea> tags are added.

body > p { margin-left: 24px; }

The following edit-mode-only CSS could be used to comphensate.

#IF($IsEdit)body > x-editarea > p,#ENDIF
body > p { margin-left: 24px; }

Editor Options

More elaborate inline editing capabilities are also possible.

  • #EDITMENU() ... #ENDEDITMENU - Contains a group of options that should be presented in a popup that will display when the edit menu icon is clicked. The edit menu icon will typically appear in a corner of the parent edit area.
  • #EDITOPTION() - Specifies an edit option to make available in an editable area. Options will typically display as an icon in a corner of the editable area on hover and focus. If inside an #EDITMENU block, an icon and label will display in the popup when the menu is activated.
#EDITMENU($TitleMenu)
	#EDITOPTION($TitleAlignment)
#ENDEDITMENU
<html>
	<head><title>$Title</title></head>
	<body>
		<h1>#EDITABLE($Title)$TitleMenu</h1>
		#LIST($Blocks)
			<div#IF($IsEdit) class="edit-box"#ENDIF>
			#EDITMENU($BlockMenu,'ul','top right inside')
				#EDITOPTION($TextAlignment,'li','no-icon')
				#CONTEXT($Image)
					#EDITOPTION($Image,'li')
					#EDITOPTION($ImageCaption,'li')
					#EDITOPTION($ImageAlignment,'li','no-icon')
				#ENDCONTEXT
			#ENDEDITMENU
			#EDITAREA()
			$BlockMenu
			#EDITABLE($Text)
			#ENDEDITAREA
			</div>
		#ENDLIST
	</body>
</html>

In the example above, #EDITMENU creates HTML code that is used to display a menu. By default, it will create a <x-editmenu> structure with an <x-editoption> for each #EDITOPTION. Optional parameters to #EDITMENU and #EDITOPTION can customize the tag and added class(es).

#EDITAREA creates a <div class="edit-area"> block by default. This is used as a container area for editable content controls, such as #EDITABLE (border and menu on hover, inline Field UI and menu on click/tap), #EDITDROP (makes area a drag-and-drop target, if multiple a popup asks which to use) and #EDITMENU (dropdown options on hover/tap).

#EDIT* statements only produce output when published to a staging/preview version of the site. It is a best-practice to use the Publication.  IsEdit checkbox field value to provide conditional editable staging/preview-only markup. $IsEdit will be FALSE when publishing to a production destination, and when publishing to a read-only staging/preview destination. $IsStaging will be FALSE when publishing to a production destination.

Security with #PROHIBIT and #PERMIT

New security features were introduced to restrict untrusted code from accessing potentially dangerous or unwanted cTemplate features and functionality.

#PROHIBIT(OUTPUT,FILE,IMAGE,ADD,EDIT,$Variable) ... #ENDPROHIBIT

#PERMIT($SpecificVariable) ... #ENDPERMIT

Permit ONLY allows specified features, statements and variables.  All others will be prohibited.

In addition to specific statements and variables, the following keywords are allowed.

  • read-only - shortcut for: script-access, file-access, content-write
  • script-access - shortcut for: PHP, PERL, EVAL
  • file-write - shortcut for: OUTPUT, FILE
  • file-read - shortcut for: FILE
  • file-access - shortcut for: OUTPUT, FILE
  • content-write - shortcut for: ADD, EDIT, REMOVE
  • all-variables - access to all variables
  • local-variables - access to all local variables

cTemplate 1.2

The following features will be added in the next cTemplate update.

cQuery

cTemplate 1.2 will support inline cQuery, which is a super-set of cPath (so inline cPath is supported as well).  cQuery syntax extends the existing explicit variable reference syntax, like ${Variable}. ${Variable} syntax was primarily used to delineate a variable from trailing text that would otherwise be interpreted as part of the variable name. For example $Variableable would become ${Variable}able. cQuery extends that same syntax to enable object and repository traversal, as well as object method calls.

Consider the following examples.

${Variable} or ${Field} same result as cTemplate 1.0.
${Object.Field} new object traversal capability
${Object.SubObject.Field} any depth is supported
${Object} implicitly calls Summary method when used in "string context"
${Object.Summary()} explicitly calls Summary method
${/cPath/from/root[0]} explicitly calls Summary method
${Object.Field[0]} cPath object selection from list field
${Object.Field/Identifier} cPath object selection from list field
${Object.Field[:Field+ AND Title LIKE 'Edit%']}

Finally, consider the following example.

#LIST(${Object.Fields})
$Identifier
#ENDLIST

Fields referenced in a #LIST block could potentially be lazy-loaded, so the variables must exist in the namespace/scope, but only get loaded when referenced.

cTemplate 2.0

The second version of the language becomes a full-featured scripting language.

  • Collections - Standard array-style access for working with Collections.
  • Object Oriented - Content Types are treated as classes with the ability to reference fields and call methods with JavaScript-like notation.
  • Extensible - Function and class definitions
  • cScript Blocks - In addition to the previous version's inline scripting, cScript blocks are also supported for more elegant large scripts. Curly-brackets are used instead of open and close tags. Output is explicitly written like a traditional scripting language.
#CSCRIPT
	insert( 'Template', 'Header' );
	write( '<ul>\n' );
	list( 'Contacts' ) {
		write( '<li><a href="' + link( 'Contact', 'ID=$ID' ) + '">' + $Name + '</a></li>\n' );
	}
	write( '</ul>\n' );
	insert( 'Template', 'Footer' );
#ENDCSCRIPT