Page tree
Skip to end of metadata
Go to start of metadata

In the root plugins Media Library folder Web Services has written a VCUutils.js file to use for programmable layouts. It includes the following common variables and functions so you don't have to declare this junk all the time in your content types and page layouts. Fair warning, there are tiny differences between using some of this stuff on content types and on page layouts (mostly the difference between 'content' and 'null'). If you need someone to add a variable or function so you don't have to define it every time contact

For page layouts you can use the following code:

If you're using this on a page layout it has to be in both the header and footer.

try {
  var utils = eval(String (com.terminalfour.publish.utils.BrokerUtils.processT4Tags (dbStatement, publishCache, section, null, language, isPreview, '<t4 type="media" id="147978" formatter="inline/*" />')));
} catch (e) {
    if (e instanceof SyntaxError) {

For content types this has to be ever so slightly altered:

try {
  var utils = eval(String (com.terminalfour.publish.utils.BrokerUtils.processT4Tags (dbStatement, publishCache, section, null, language, isPreview, '<t4 type="media" id="147978" formatter="inline/*" />')));
} catch (e) {
    if (e instanceof SyntaxError) {
Examples of use
// this is the equivalent of document.write('VCU is the best!'); which would print out as VCU is the best!
docwrite('VCU is the best!');
//In a content type, this would print out whatever the user has input in the content type's Heading field
//writes out the name of the section and wraps it in a h1 tag
docwrite('<h1>' + sectionName + '</h1>');
//only document.writes if this content is the first of it's type on the page (used primarily for plugins not loading CSS and JS multiple times on the page
if(pageFirst) {
	docwrite('Im the first piece of this type of content on this page');

In the above diagram, you can see that the pageFirst, pageLast, groupFirst and groupFirst selectors are entirely different. The pageFirst variable will only allow a document.write() if the content type is the first of its kind on the page. The groupFirst variable will allow a document.write() if the content type is the first of its kind in a set (broken by an instance of another content type preceding it). The pageFirst variable is the correct method to load in a plugin's CSS and JS on the page, because it will only allow this once per content type. The groupFirst variable is a good way of wrapping, say, a set of accordion panels in a wrapper (much like in Bootstrap).

The VCUutils.js file currently includes:

// Imports

// New classes
var oBU = new BrokerUtils();
var oCH = new ContentHierarchy();

// Variables
var oStmt = dbStatement;
var oMM = MediaManager.getManager();
var channel = publishCache.getChannel();
var breadcrumbs = TreeTraversalUtils.getPathSections(channel, section, true);
var sectionName = section.getName('en');
var sectionID = section.getID();
var sectionLevel = section.getLevel(channel);
var sectionLink = PathBuilder.getLink(dbStatement, section, publishCache, language, isPreview);
var sectionOrder = section.getSequenceNo();
var sectionChildren = section.getChildren(channel, language, true);
var parent = section.getParent();
var parentName = parent.getName('en');
var parentLevel = parent.getLevel(channel);
var parentLink = PathBuilder.getLink(dbStatement, parent, publishCache, language, isPreview);
var parentPath = parentLink.getLink();
var contentList = CSHelper.extractCachedContent (CSHelper.removeSpecialContent (section.getContent (publishCache.getChannel (), CachedContent.APPROVED)));
var contentID = content.getID();
var rootLevel = 0;
var rootSection = TreeTraversalUtils.getRoot(channel, section);
var rootName = rootSection.getName('en');
var rootID = rootSection.getID();
var rootLink = PathBuilder.getLink(dbStatement, rootSection, publishCache, language, isPreview);
var rootChildren = rootSection.getChildren(channel, language, true);
var rootContentList = CSHelper.extractCachedContent (CSHelper.removeSpecialContent (rootSection.getContent (publishCache.getChannel (), CachedContent.APPROVED)));
var siblings = TreeTraversalUtils.getSiblings(channel, section, language, true);

// Function to write document.write out quicker
function docwrite(input) {
// Function to get the link of a section
function link(section) {
    var link = PathBuilder.getLink(dbStatement, section, publishCache, language, isPreview);
    return link;
// Function to get content from a section
function element(input) {
// Function to process T4 tag in content
function processT4Tag(t4Tag) {
  var myContent = content || null;
  return com.terminalfour.publish.utils.BrokerUtils.processT4Tags(dbStatement, publishCache, section, myContent, language, isPreview, t4Tag);

// Parse Injectors ---------------------------------------------
function parseInj(r,a,e,n){var c=r,l=n.match(c);if(null!==l){var p=l[0].replace(a,"").replace(e,"");return p}}
function parseClassInj(s){return parseInj(/class:{([^}]+)\}/g,"class:{","}",s)}
function parseIdInj(n){return parseInj(/id:{([^}]+)\}/g,"id:{","}",n)}
function parseStyleInj(e){return parseInj(/style:{([^}]+)\}/g,"style:{","}",e)}
function parseLayoutInj(a){return parseInj(/layout:{([^}]+)\}/g,"layout:{","}",a)}
function parseBeforeInj(e){return parseInj(/before:{([^}]+)\}/g,"before:{","}",e)}
function parseAfterInj(r){return parseInj(/after:{([^}]+)\}/g,"after:{","}",r)}
// -------------------------------------------------------------

// Parse Templates ---------------------------------------------
function parseTemplate(e){var a=/#\[([^\]]+)\]/g,r=e.match(a),l=e,c=!1;if(null!==r){for(var p=0;p<r.length;p++){var v=r[p],t=/#\[([^\(]+)\(/g,n=v.match(t);if(null!==n){var f=n[0].replace("#[","").replace("(","");c=!0}else{var h=v.replace(" ","|");if(h!==v){var i=h.match(/#\[([^\|]+)\|/),m=h.match(/\|([^\]]+)\]/),u="<"+i[1]+">"+m[1]+"</"+i[1]+">";l=l.replace(v,u)}else{var i=h.replace("#[","").replace("]",""),u="<"+i+"></"+i+">";l=l.replace(v,u)}}var g=/\(([^\)]+)\)/g,s=v.match(g);if(null!==s)var o=" "+s[0].replace("(","").replace(")","").replace(/,/g,"");else var o="";var T=/\)([^\]]+)\]/g,b=v.match(T);if(null!==b)var d=b[0].replace(")","").replace("]","");else var d="";if(1==c){var j="<"+f+o+">"+d+"</"+f+">";l=l.replace(v,j)}}return l}return l}
// -------------------------------------------------------------

//function to decided if the content is the first or last of its type
var tid = content.getTemplateID();
var sid = section.getID();
var oCH = new ContentHierarchy();
var oCM = ContentManager.getManager();
var oStmt = dbStatement;
var oMM = MediaManager.getManager();
var oBU = new BrokerUtils();
var contentInSection = oCH.getContent(dbStatement,sid,'en');

var groupFirst = false;
var groupLast = false;
for (var i = 0; i < contentInSection.length; i++) {
	if(content.getID()==oCM.get(dbStatement,contentInSection[i],"en").getID()) {
		if(i==0) groupFirst=true;
		else if(tid!= oCM.get(dbStatement,contentInSection[i-1],"en").getTemplateID()) groupFirst=true;
		else groupFirst=false;
		if(i==contentInSection.length-1) groupLast=true;
		else if(tid!= oCM.get(dbStatement,contentInSection[i+1],"en").getTemplateID()) groupLast=true;
		else groupLast = false;

var pageFirst = false;
var pageLast = false;

// Create function to delete excess array objects if they have identical keys...
function unique(arr) {
  var comparer = function compareObject(a, b) {
    if (a.key == b.key) {
      return 0;
    } else {
      if (a.key < b.key) {
        return -1;
      } else {
        return 1;
  var end;
  for (var i = 0; i < arr.length - 1; ++i) {
    if (comparer(arr[i], arr[i+1]) === 0) {
      arr.splice(i, 1);
  return arr;

// Grab all pieces of content on the page
var cL = com.terminalfour.sitemanager.cache.utils.CSHelper.extractCachedContent (com.terminalfour.sitemanager.cache.utils.CSHelper.removeSpecialContent (section.getContent (publishCache.getChannel (), com.terminalfour.sitemanager.cache.CachedContent.APPROVED)));
// Run through each piece of content, find out all the content types, and create a key array...
var listContentTypeIDs = [];
for each (c in cL) {
  var ctID = c.getTemplateID();
    'key': ctID,
    'pieces': []

// Run through each piece of content, and put them in their corresponding key object
for each (c in cL) {
  var ctID = c.getTemplateID(),
      uID = c.getID();
  for each (k in listContentTypeIDs) {
    if (ctID == k.key) {
      var p = k.pieces;

// Get the current content type ID and unique ID
var this_ctID = content.getTemplateID(),
    this_uID = content.getID();

// Set the pageFirst and pageLast values
for each (k in listContentTypeIDs) {
  // Find the current content piece in the array of all alike content on the page...
  if (k.key == this_ctID) {
    var pieces = k.pieces,
        pFirst = pieces[0],
        pLength = pieces.length,
        pIndex = pLength - 1,
        pLast = pieces[pIndex];
    // If this piece of content is the first of its kind on the page...
    if (pFirst == this_uID) {
      pageFirst = true;
    } else {
      pageFirst = false;
    // If this piece of content is the last of its kind on the page...
    if (pLast == this_uID) {
      pageLast = true;
    } else {
      pageLast = false;
  • No labels