Mura 10: Mura Rendering

The Mura contentRenderer.cfc

The majority of Mura's rendering behavior occurs in a special file labeled the "contentRenderer.cfc". Mura's primary, or "Core" contentRenderer is located under:

 {context}/core/mura/content/contentRenderer.cfc

As covered in the Theme Developer's Guide, the "Core" contentRenderer also contains a plethora of helper methods, as well as settings used by Mura's display objects, all of which are frequently used by Mura developers.

Since the "Core" contentRenderer is a "core" file, it shouldn't be modified directly. Instead, if you wish you to override any of the default settings or methods found in the "core" contentRenderer, Mura will first check the theme, and then the site for a contentRenderer.cfc. If the matching setting or method is found, it will use the custom setting or method in lieu of Mura's default "core" setting or method. You only need to define the setting(s) or method(s) you wish to override in your "Site" or "Theme" contentRenderer.

Custom Rendering Methods

In addition to overriding any of the default settings and methods found in the "Core" contentRenderer, any custom rendering methods defined in the "Site" or "Theme" contentRenderer are available via the Mura Scope. For example, if you have the following method defined in your "Site" or "Theme" contentRenderer:

public string function dspHello() {
  return "<p>Hello from dspHello!</p>";
}

You may invoke the method by simply using the following syntax:

<cfoutput>
  #m.dspHello()#
</cfoutput>

The above code would output:

<p>Hello from dspHello!</p>

Lookup Hierarchy

Mura uses the following lookup hierarchy for settings or methods found in a contentRenderer.cfc. If the setting or method is defined in the first file, Mura will use it and ignore any other identically named methods found in the remaining files.

  1. "Theme" contentRenderer
    • ../themes/{ThemeName}/contentRenderer.cfc
  2. "Site" contentRenderer
    • {context}/sites/{SiteID}/includes/contentRenderer.cfc
  3. "Core" contentRenderer
    • {context}/core/mura/content/contentRenderer.cfc

contentRenderer Settings

The vast majority of the contentRenderer settings allow developers to apply custom classes to Mura's modules. This allows developers to use CSS to control the style and display of Mura's modules, without having to override the rendering methods or modules themselves to achieve the desired result.

Mura allows you to override its default contentRenderer settings on a site-by-site basis. To override a setting, simply place a reference to the setting and your desired value in your "Site" or "Theme" contentRenderer.cfc.

Example

this.validateCSRFTokens = true;
this.navOffset = 0;
this.navDepthLimit = 1000;
this.navWrapperClass = 'sidebar-nav well';

Reference

A reference for Mura's "Core" contentRenderer.cfc settings is outlined below. Keep in mind the vast majority of the contentRenderer settings are specific to Mura's modules, and as such, most of these settings are merely the CSS classes that will be applied to them.

Note: The settings listed below are the "default" settings, and many of them may be overwritten in Mura's default theme. Please refer to the theme's contentRenderer.cfc file to review the theme's settings.

Setting Type Default Description
validateCSRFTokens boolean false If true, Mura will check for cross-site request forgery (CSRF) tokens to help prevent CSRF attacks.
navOffset int 0 This allows you to start standard navigation behavior at lower navigation levels. For example, this would be useful if you have a section of your site that should have its own primary navigation, such as a Member's only area with a custom layout template.
navDepthLimit int 1000 This sets the maximum depth that standard navigation will follow.
navParentIdx int 2  
navGrandParentIdx int 3  
navDepthAdjust int 0  
navSelfIdx int 1  
deferMuraJS boolean false If true, Mura will add a "defer" attribute to the script reference for mura.min.js so that the script will be executed when the page has finished parsing.
jsLib string jquery

This determines what JavaScript library Mura should use with its built-in display objects. Valid options are:

  • jquery
  • prototype
jsLibLoaded boolean false This allows developers to not rely on Mura to load the default JavaScript framework and simply add it to their theme's HTML head area.
suppressWhitespace boolean true If true, Mura will remove excess whitespace characters from CFML generated content.
longDateFormat string long This is the default long date format for the site.
shortDateFormat string short This is the default short date format for the site.
showMetaList list jpg,jpeg,png,gif,svg This is a list of file extensions that will not directly download, but instead, will render in a Mura CMS page with the "Summary" being displayed in the body area.
imageInList list jpg,jpeg,png,gif,svg This is a list of what image extensions should be shown in built in content listing display objects.
directImages boolean true This tells Mura whether to serve images indirectly through fileManager.renderImage() or create direct links.
personalization string user This allow developers to choose whether site personalizations such as ratings and favorites are attached to simple cookies or an actual Mura user. Users do not need to login in order to save cookie-based personalizations. Valid options:
  • user
  • cookie
hasEditableObjects boolean false If true, enables editable objects.
asyncObjects boolean true If true, Mura will load display objects asynchronously.
asyncRender boolean false  
defaultInheritedRegions string list, empty by default An indexed list of the display regions to be inherited by default. Regions are identified in Site Settings, i.e. Left Column^Body^Footer, and if the desired default regions to be inherited was Body and Footer, then the value for this setting would be "2,3".
queueObjects boolean true  
layoutManager boolean false If true, enables the front-end Mura Layout Manager. 
legacyObjects boolean true If true, allows for management of legacy display objects used in pror Mura versions
siteIDInURLs boolean   If a boolean value exists, it will override the settings.ini.cfm value
indexFileInURLs boolean   If a boolean value exists, it will override the settings.ini.cfm value
hashURLs boolean   If a boolean value exists, it will override the settings.ini.cfm value
enableMuraTag boolean   If a boolean value exists, it will override the settings.ini.cfm value
showAdminToolbar boolean   If true, the front end toolbar will be rendered for administrative users.
showMemberToolbar boolean   If true, the front end toolbar will be rendered for site members
showEditableObjects boolean   If true, editable display objects like components and content collections will be rendered. 
showInlineEditor boolean   If true, will display the Inline Edit button on the front end toolbar for administrative users. 
renderHTMLQueues boolean true If true, Mura will render the request's HTMLHeadQueue and HTMLFootQueue.
preloaderMarkup string empty string Allows developers to include a custom preloader.
bodyMetaImageSizeArgs struct {size="medium"}  
bodyMetaImageClass string thumbnail A CSS class applied to the primary associated image.
navsize int 50 An integer value to control the maximum number of navigational items to output for Mura generated navigation.
imageClass string img-thumbnail A CSS class applied to the primary associated image when displayed in a list such as a collection.
categoriesNestCheckboxClass string checkbox A CSS class applied to category checkboxes.
generalWrapperClass string well A CSS class applied to general wrapper HTML elements.

Heading Markup Settings

When Mura outputs headings, the following settings may be used. The following settings are also used to control the heading tags used for the HTML Editor's "Format" select menu options. The defaults listed below are based on the concept that <h1> tags are reserved for the "Site Name" or logo area of the layout templates, and page titles begin with <h2> tags.

Setting Type Default
headline string h2
subHead1 string h3
subHead2 string h4
subHead3 string h5
subHead4 string h6
subHead5 string h6

Alert Markup Settings

When Mura outputs an alert, the following settings may be used.

Setting Type Default
alertSuccessClass string alert alert-success
alertInfoClass string alert alert-info
alertWarningClass string alert
alertDangerClass string alert alert-error

Table Markup Settings

When Mura outputs a table, the following settings may be used.

Setting Type Default
tableClass string table table-bordered table-striped
tableHeadClass string empty string
tableHeaderClass string empty string
tableBodyClass string empty string
tableRowClass string empty string
tableCellClass string empty string
tableFooterClass string empty string

Module (Display Object) Settings

The vast majority of contentRenderer settings are used to control the CSS classes for HTML markup of Mura's baked-in modules. Mura's modules and their associated settings are described below.

Navigation

The markup for the various types of navigational modules can be found in the files located under:

{context}/core/modules/v1/nav/
Setting Type Default
navWrapperClass string sidebar-nav well
navLIClass string empty string
liHasKidsClass string empty string
liHasKidsAttributes string empty string
liCurrentClass string current
liCurrentAttributes string empty string
liHasKidsNestedClass string empty string
aHasKidsClass string empty string
aHasKidsAttributes string empty string
aCurrentClass string current
aCurrentAttributes string empty string
ulNestedClass string empty string
ulNestedAttributes string empty string
ulTopClass string navSecondary
ulPaginationClass string navSequential
ulPaginationWrapperClass string pagination
aNotCurrentClass string empty string
navCalendarWrapperClass string svCalendar
navCalendarTableClass string table table-bordered
navSequentialWrapperClass string pagination
navSequentialULClass string empty string
tagCloudWrapperClass string svTagCloud
navArchiveWrapperClass string empty string
navArchiveListClass string empty string
navBreadcrumbULClass string breadcrumb

Form

The Form module markup can be found in the files located under:

{context}/core/modules/v1/form/
Setting Type Default
formWrapperClass string well
formFieldWrapperClass string control-group
formFieldLabelClass string control-label
formInputWrapperClass string input-addon
formInputClass string form-control
formCheckboxClass string empty string
formButtonWrapperClass string btn-group
formButtonInnerClass string empty string
formButtonClass string btn btn-default
formRequiredWrapperClass string empty string

Form Builder

The Form Builder module markup can be found in the files located under:

{context}/core/modules/v1/formbuilder/
Setting Type Default
formBuilderFieldWrapperClass string empty string
formBuilderButtonWrapperClass string form-actions
formBuilderSubmitClass string btn btn-default
formBuilderFormFieldsClass string control-group
formBuilderTabHeaderClass string dropdown
formBuilderDisabledInputClass string disabled
formBuilderCheckboxClass string checkbox

Calendar

The Calendar module markup can be found in the files located under:

{context}/core/modules/v1/calendar/
Setting Type Default
calendarWrapperClass string svCalendar
calendarTableClass string table table-bordered
calendarTableHeaderClass string empty string
calendarTitleInDesc boolean true
calendarListWrapperClass string svCalendar
calendarcolors array of structs [
{background='##3a87ad', text='white'},
{background='blue', text='white'}
]

Comments

The Comments module markup can be found in the files located under:

{context}/core/modules/v1/comments/
Setting Type Default
commentsWrapperClass string empty string
commentSortContainerClass string empty string
commentSortWrapperClass string empty string
commentSortSelectClass string empty string
commentFormWrapperClass string empty string
commentFormClass string well
commentNewClass string btn
commentFieldWrapperClass string empty string
commentFieldLabelClass string empty string
commentInputWrapperClass string empty string
commentInputClass string empty string
commentCheckboxClass string checkbox
commentPrefsInputWrapperClass string empty string
commentSubmitButtonWrapperClass string empty string
commentSubmitButtonClass string btn
commentMoreCommentsUpClass string btn btn-default icon-arrow-up
commentMoreCommentsDownClass string btn btn-default icon-arrow-down
commentRequiredWrapperClass string empty string
commentAdminButtonWrapperClass string empty string
commentUserEmailClass string btn
commentDeleteButtonClass string btn
commentEditButtonClass string btn
commentApproveButtonClass string btn
commentThumbClass string img-polaroid
commentSpamClass string btn
commentSpamLinkClass string btn
commentClass string empty string
commentDateTimeClass string empty string
commentReplyClass string empty string
commentAwaitingApproval string empty string
commentAdminButtonWrapperClass string btn-group pull-right
commentUserEmailClass string btn btn-default btn-sm
commentDeleteButtonClass string btn btn-default btn-sm
commentEditButtonClass string btn btn-default btn-sm
commentApproveButtonClass string btn btn-default btn-sm
commentMoreCommentsContainer string well
emailLinkClass string btn
commentsLinkClass string btn
approveCommentLinkClass string btn
deleteCommentLinkClass string btn

Collections, Folders, and List/Grid Output

Collections & List/Grid module markup can be found in the files located under:

{context}/core/modules/v1/collection/
Setting Type Default
contentListImageStyles boolean true
contentListImagePadding int 20
contentListPropertyMap struct {
containerEl={tag="div"},
itemEl={tag="dl",class="clearfix"},
labelEl={tag="span"},
title={tag="dt"},
date={tag="dt"},
credits={tag="dd",showLabel=true,rbkey="list.by"},
tags={tag="dd",showLabel=true,labelDelim=":",rbkey="tagcloud.tags"},
rating={tag="dd",showLabel=true,labelDelim=":",rbkey="list.rating"},
default={tag="dd"}
}
contentGridStyleMap struct {
'1 Column'='mura-grid-one',
'2 Column'='mura-grid-two',
'3 Column'='mura-grid-three',
'4 Column'='mura-grid-four',
'5 Column'='mura-grid-five',
'6 Column'='mura-grid-six',
'7 Column'='mura-grid-seven',
'8 Column'='mura-grid-eight',
'9 Column'='mura-grid-nine'
}
contentGridPropertyMap struct {
itemEl={tag="div",class="mura-item-meta"},
labelEl={tag="span"},
title={tag="div"},
date={tag="div"},
credits={tag="div",showLabel=true,labelDelim=":",rbkey="list.by"},
tags={tag="div",showLabel=true,labelDelim=":",rbkey="tagcloud.tags"},
rating={tag="div",showLabel=true,labelDelim=":",rbkey="list.rating"},
'default'={tag="div"}
}
contentListWrapperDivClass string empty string
contentListItemImageLinkClass string thumbnail
folderWrapperClass string svIndex
nextNWrapperClass string empty string

Edit Profile

The Edit Profile module markup can be found in the files located under:

{context}/core/modules/v1/editprofile/
Setting Type Default
editProfileWrapperClass string empty string
editProfileFormClass string form-horizontal
editProfileFormGroupWrapperClass string control-group
editProfileFieldLabelClass string control-label
editProfileFormFieldsWrapperClass string empty string
editProfileFormFieldsClass string empty string
editProfileHelpBlockClass string help-block
editProfileExtAttributeFileWrapperClass string empty string
editProfileExtAttributeFileCheckboxClass string checkbox
editProfileExtAttributeDownloadClass string empty string
editProfileExtAttributeDownloadButtonClass string btn btn-default
editProfileSubmitButtonWrapperClass string empty string
editProfileSubmitButtonClass string btn btn-primary
editProfileSuccessMessageClass string alert alert-success

Event Reminder Form

The Event Reminder Form module markup can be found in the files located under:

{context}/core/modules/v1/event_reminder_form/
Setting Type Default
eventReminderFormWrapperClass string empty string
eventReminderFormClass string well
eventReminderFieldWrapperClass string control-group
eventReminderFormLabelsClass string control-label
eventReminderSubmitClass string btn btn-default

Feed

The Feed module markup can be found in the files located under:

{context}/core/modules/v1/feed/

You should also review the Collections, Folders, and List/Grid Output settings above for markup information specific to the feed output itself. These settings are merely "wrapper" classes.

Setting Type Default
localIndexWrapperClass string svSyndLocal svFeed svIndex clearfix
remoteFeedWrapperClass string svSyndRemote svIndex svFeed clearfix

Login Form

The Login Form module markup can be found in the files located under:

{context}/core/modules/v1/login/
Setting Type Default
loginWrapperClass string container
loginWrapperInnerClass string row
loginFormClass string form-horizontal
forgotPasswordFormClass string form-horizontal
loginFormGroupWrapperClass string empty string
loginFormFieldLabelClass string control-label
loginFormFieldWrapperClass string empty string
loginFormFieldClass string empty string
loginFormPrefsClass string empty string
loginFormCheckboxClass string checkbox
loginFormSubmitWrapperClass string empty string
loginFormSubmitClass string btn btn-default
notRegisteredLinkClass string btn btn-primary

Search Form & Search Results

The Search Form module markup can be found in the files located under:

{context}/core/modules/v1/search/
Setting Type Default
searchFormClass string empty string
searchFormInputWrapperClass string empty string
searchFormInputClass string empty string
searchFormSubmitWrapperClass string empty string
searchFormSubmitClass string btn btn-default
searchShowNumbers int 1
searchResultWrapperClass string container
searchResultInnerClass string row
searchResultsRowClass string row
searchResultsMoreResultsRowClass string row
searchResultsListClass string svIndex
searchResultsPagerClass string pager
searchAgainRowClass string row
searchAgainInnerClass string empty string
searchAgainFormClass string empty string
searchAgainInputWrapperClass string empty string
searchAgainFormInputClass string empty string
searchAgainButtonWrapperClass string empty string
searchAgainSubmitClass string btn btn-default

User Tools

The User Tools module markup can be found in the files located under:

{context}/core/modules/v1/user_tools/
Setting Type Default
userToolsLoginWrapperClass string well clearfix
userToolsLoginFormClass string form-horizontal
userToolsFormGroupWrapperClass string empty string
userToolsLoginFormLabelClass string control-label
userToolsLoginFormInputWrapperClass string empty string
userToolsLoginFormInputClass string empty string
userToolsLoginFormFieldInnerClass string empty string
userToolsLoginFormCheckboxClass string checkbox
userToolsLoginFormSubmitClass string btn btn-default
userToolsNotRegisteredLinkClass string btn btn-primary
userToolsWrapperClass string clearfix
userToolsEditProfileLinkClass string btn btn-default
userToolsLogoutLinkClass string btn btn-default

Content Rater

The Content Rater module markup can be found in the files located under:

{context}/core/modules/v1/rater/
Setting Type Default
raterObjectWrapperClass string row clearfix
raterWrapperClass string empty string
avgRatingWrapperClass string empty string

 

The Mura [m] Tag

As covered in the Theme Developer's course, you may use "Mura Tags" when you want to output dynamic code within the HTML Editor.

Developers need to use Mura Tags because hash tags (#) are ignored when entered as text in the HTML Editor. Hence, you can only render a CFML variable, or function call.

Globally Enable/Disable the Mura Tag

To globally enable or disable the Mura Tag, open the file located under {context}/config/settings.ini.cfm. Locate the enablemuratag key, and set the value to true to enable the Mura Tag, or false to disable the Mura Tag.

If enablemuratag is set to false, the Mura tag button will not appear on any HTML Editors. In addition, the Mura Tags will not be parsed as CFML, and will only display as a string of text, as it was entered into the HTML Editor.

Enable/Disable the Mura Tag on a Site-by-Site Basis

If you wish to enable or disable the Mura Tag on a site-by-site basis, you may edit the Site or Theme contentRenderer.cfc file located under:

  • Site contentRenderer.cfc
    • {context}/sites/{SiteID}/contentRenderer.cfc
  • Theme contentRenderer.cfc
    • ../themes/{ThemeName}/contentRenderer.cfc

Then, add this.enablemuratag=true to enable, or this.enablemuratag=false to disable. This setting overrides the global setting described above.

Rendering Mura Tags

When you expect Mura Tags in the output, you'll want to use the m.SetDynamicContent(string) function. This function is covered under the setDynamicContent section of the Theme Developer's Guide.

Class Extensions

Mura's Class Extensions allow you to customize some of its common bean objects such as content beans, user beans, group beans, and site beans. The term "class extension" itself is borrowed from the world of object-oriented programming (OOP). These "objects" are designed in hierarchies, commonly referred to as a "class" hierarchy. Hence, "class extensions" is a term Mura uses to define custom subclasses.

Class extensions allow you to create Extended Attribute Sets (think fieldsets, or groups of related form elements) to provide additional "attributes" (think form fields) to collect and store data. In addition, you can create Related Content Sets to allow content managers the ability to associate content to something other than the default catch-all "Related Content" field, allowing you to create fields such as Related Videos, Related Files, Related Authors, and so on.

Also, class extensions provide an excellent way to allow developers the ability to target a certain Type and/or Subtype of a content item's body area, so they can do things such as automatically alter the layout of the body area, and/or include additional data, etc. Using this method means you wouldn't necessarily have to create any Extended Attribute Sets or Related Content Sets either, unless that's something you desire.

Types & Subtypes

Each of the bean objects Mura exposes for customization (see table below) include two very important attributes: Type, and Subtype. While you can change the Subtype attribute of a bean object, you cannot alter the Type attribute itself.

When working with class extensions, you first target the specific Type for customization. Then, you target the "default" Subtype, or create a new Subtype altogether. These are often represented as {Type}/{Subtype} when creating new objects. For example, "Folder/Locations", "Page/Location", "User/Employee", etc.

While the options for customization are essentially limitless, here are a few examples to help illustrate how you might use class extensions.

  • User
    • You could create a new "User" subtype, such as "Employee". Then, you might want to collect additional data about the employee such as "Emergency Contact Name", "Emergency Contact Mobile", etc.
  • Folder
    • You could create a new "Folder" subtype, such as "Locations". Then, you could target any content items using "Folder/Locations" as the Type and Subtype in order to loop over any child content items and display them on a map. You wouldn't necessarily have to add any Extended Attribute Sets or Related Content Sets either. As you'll see in the Define with the Admin UI section, you can also restrict the {Type}/{Subtype} of content that can be added as children.
  • Page
    • Along the same lines of the previous Folder example, you could create a new "Page" subtype, such as "Location". Then, you could collect data about the location such as the Street, City, State, Phone Number, etc. and display the information entered into these fields on the page when it's being rendered. In addition, you could use this data to geocode the location for use on map.

The "default" Subtype

By targeting "default" as the Subtype, any Extended Attribute Sets or Related Content Sets associated with the class extension will apply to all objects sharing the same Type attribute.

For example, if you create a new class extension and the Type equals "Page" and Subtype equals "Default", then anything you create will apply to all "Page/Default" content items, as well as any other "Page/{Anything}" content items.

Extendable Bean Objects

The table below itemizes each of the "Base Types" of bean objects available for customization.

Type Bean Description
Page content This is the standard Page content type.
Folder content This is the standard Folder content type.
File content This is the standard File content type.
Calendar content This is the standard Calendar content type.
Link content This is the standard Link content type.
Component content This is a standard Component, which is essentially a special type of content itself. Using Class Extensions with Components opens several possibilities such as creating a Component with tabbed content, slideshows, and more.
Form content This is a standard Form, also a special type of content.
Base content Extending the Base/Default object allows you to create additional Extended Attribute Sets and Related Content Sets to appear on all standard content types (Page, Folder, File, Calendar, and Link), excluding Components and Forms. If you specify a different Subtype, then any Extended Attribute Sets or Related Content Sets will only appear on content types that share the specified Subtype.
User (2) user Since the group bean is essentially the user bean, the type attribute for users is technically stored as a "2" to indicate the record reflects a "user".
Group (1) group Since the group bean is essentially the user bean, the type attribute for groups is technically stored as a "1" to indicate the record reflects a "group".
Address address Address bean objects are related to user beans. A user may have one or more addresses. By extending this class, you can create additional attributes to store new types of data that Mura doesn't already collect.
Site site Extending the Site object allows you to create additional Extended Attribute Sets via the Site Settings area of the back-end administration area of Mura.

 

Define with Admin UI

Follow the steps below to create a custom class extension. For example purposes, we'll create a Page/Location, as mentioned in the introduction to Class Extensions.

  1. From Mura's back-end administration area, select Site Settings, click Class Extensions, and select Add Class Extension.
  2. You should be taken to the Add Class Extension screen.
    • Base Type
      • Please refer to the Extendable Bean Objects section of the Class Extensions page for details on each option.
    • Description
      • You may enter your desired description of the class extension here. This is merely information for anyone else who may edit or manage the class extension in the future, and is not displayed anywhere else by default.
    • Status
      • Active
        • If selected, the defined Class Extension will appear as an option for content managers when creating new content items.
      • Inactive
        • If selected, the defined Class Extension will not appear as an option for content managers when creating new content items.
  3. From the Add Class Extension screen, click the Base Type menu, and choose your desired option, (e.g., Page).
  4. Once you've made a selection, additional form fields may appear. If you select one of the content types, (e.g., Page, Folder, etc.), additional form fields will appear.
    • Sub Type
      • You may choose to leave the initial setting of "Default" so that any Extended Attribute Sets and/or Related Content Sets will apply to all content items sharing the same Type. Or, you may enter your own, unique Subtype.
    • Icon
      • The icon you select here, will appear in the Select Content Type dialog window, when content managers create new content items.
    • Show "Summary" field when editing?
      • Select whether you wish to display the "Summary" field.
    • Show "Body" field when editing?
      • Select whether you wish to display the "Body" field.
    • Show "Associated Image" field when editing?
      • Select whether you wish to display the "Associated Image" field.
    • Allow user to add only specific Subtypes?
      • If Yes, you may select one, or more options from the available list. This will restrict what appears in the Select Content Type dialog window, when content managers add new content items as children on this specific type of content.
  5. When finished, click the Add button, so save your new Class Extension.
  6. You should now be taken to the Class Extension screen, where you may view/create Extended Attribute Sets, and Related Content Sets.

Extended Attribute Sets

Extended Attribute Sets are essentially <fieldset> elements. In other words, they're a set of form controls, grouped under a common name. To create an Extended Attribute Set, follow the steps outlined below.

  1. From the back-end administration area of Mura, select Site Settings, click Class Extensions, and select Class Extensions.
  2. You should be directed to the Class Extensions screen.
  3. Select the Class Extension you wish to add an Extended Attribute Set to, from the listing of available Class Extensions.
  4. You should be directed to the Class Extension screen. Here, you can view any available Extended Attribute Sets or Related Content Sets.
  5. To add an Extended Attribute Set, click the Add button, then select Add Attribute Set.
  6. You should now see the Add Attribute Set screen.
    • Attribute Set Name
      • The text entered here will be used as the <legend> for the generated <fieldset>.
    • Container (Tab)
      • You may select the tab you wish to include your Extended Attribute Set on, from the listing of available tabs. The listing will differ, depending on the Base Type you selected when creating the Class Extension itself.
      • If you select the Custom UI option, you're essentially telling Mura that you'll take care of collecting any attributes you're going to define. If you wish to add a new tab, and include a custom form for collecting the data, you may find this Gist useful: https://gist.github.com/stevewithington/f3dd405d5a188fb594a1
  7. Once you've entered an Attribute Set Name, and selected your desired Container (Tab), click the Add button to create your new attribute set.
  8. You should be directed to the Manage Extended Attribute Set screen. This is where you'll add, and manage your new attributes, or form fields.
  9. To create a new attribute, click the Add New Attribute button.
  10. The screen should now reveal a form to add a new attribute.
    • Name (No spaces)
      • Text entered here will be used as the name attribute of the form field. In addition, the text entered here is how you will reference any data entered for this attribute, as you'll see in the Displaying Extended Attributes section. It is important to use a proper naming convention, as if you were manually creating the input using HTML. Keep in mind that this form field will be included on a much larger form, and as such, you'll want to avoid using any of the bean object's attribute names so you don't run into any naming collisions. For example, you don't want to use the Name "title", since Content Beans already have an attribute labeled "title".
      • The recommended best practice is to prefix the Name with the Subtype of your class extension. For example, if your Subtype equals "Location", instead of using "title" for the Name, you might use "locationtitle" for the Name.
    • Label
      • Text entered here will be used as the <label> element.
    • Input Type
      • Select your desired input type from the option list.
    • Default Value
      • Optionally, enter a default value here. To include a dynamic value, you may use Mura [m] tags.
    • Tooltip
      • Optionally, enter text to be used as a tooltip.
    • Required
      • Whether the field is required. If True, Mura will use the option selected in the Validate field when the user submits the form.
    • Validate
      • If you desire the input to be validated before the form is submitted, select one of the following options.
        • None
          • Do not validate input.
        • Date
          • Validates data entered is a valid date. Mura will display a calendar UI widget for content managers to use when completing this form field.
        • DateTime
          • Validates data entered is a valid date and time. Mura will display a calendar and time UI widget for content managers to use when completing this form field.
        • Numeric
          • Validates data entered is an integer.
        • Email
          • Validates data entered matches standard email address formats.
        • Regex
          • Validates data entered against the JavaScript regular expression entered in the Regex field.
        • Color
          • If the Input Type is set to TextBox, and this option is selected, Mura will display a "color picker" UI widget for content managers to use when completing this form field.
        • URL
          • Validates data entered matches standard URL formats.
    • Regex
      • If Validate is set to Regex, Mura will use the JavaScript regular expression entered here to validate data entered in this form field.
    • Validation Message
      • If Required is set to True, text entered here will be displayed to content managers if the data entered in this form field does not pass validation rules.
    • Option List ("^" Delimiter)
      • This carat ("^") delimited list of "option values" will be used if Input Type is set to SelectBox, MultiSelectBox, or RadioGroup. For example, "option1^option2^option3". To include a dynamic value, you may use Mura [m] tags.
    • Option Label List (Optional, "^" Delimiter)
      • This carat ("^") delimited list of "option labels" will be used if Input Type is set to SelectBox, MultiSelectBox, or RadioGroup. For example, "Option 1^Option 2^Option 3". To include a dynamic value, you may use Mura [m] tags.
    • For Administrative Use Only?
      • If Yes, the field will not display for content editing purposes, and will be a hidden form field.
  11. After you've completed the form, click the Add button to create your new attribute.
  12. Repeat these steps to create additional attributes for the Extended Attribute Set.
  13. The attributes sort order is the order in which they will be displayed to content managers. If you wish to reorder any of them, click the Reorder button.
  14. Then, hover over the attribute you wish to move, and then click, drag, and drop to your desired location.
  15. When finished reordering, click the Save Order button.

Define with XML

In the Define with Admin UI section, we covered creating Class Extensions, Extended Attribute Sets, and Related Content Sets using Mura's back-end administrator user interface. In addition to using the administrator's UI, Mura can parse a special XML file to create Class Extensions, as well as create custom image sizes, and more.

config.xml.cfm

Whenever Mura experiences an application reload, it scans for the config.xml.cfm file, and if found, will attempt to parse the file to create any pre-defined Class Extensions and custom image sizes. As you'll see in the Mura Modules section and Plugins section, if the file is located under a modules or plugin directory, Mura uses the file to obtain various settings and information about the module or plugin too.

Convention-Based Lookup

The config.xml.cfm file will be discovered in any theme directory, module directory, content type directory, or plugin directory.

For example:

  • {context}/themes/{ThemeName}/
  • {context}/themes/{ThemeName}/content_types/{Type}/
  • {context}/themes/{ThemeName}/content_types/{Type}_{Subtype}/
  • {context}/themes/{ThemeName}/modules/{Module}/
  • {context}/sites/{SiteID}/themes/{ThemeName}/
  • {context}/sites/{SiteID}/themes/{ThemeName}/content_types/{Type}/
  • {context}/sites/{SiteID}/themes/{ThemeName}/content_types/{Type}_{Subtype}/
  • {context}/sites/{SiteID}/themes/{ThemeName}/modules/{Module}/
  • {context}/plugins/{PluginName}/plugin/
  • {context}/plugins/{PluginName}/modules/{Module}/
  • {context}/plugins/{PluginName}/content_types/{Type}_{Subtype}/

As covered in the Mura Rendering section, you can nest additional module directories and content type directories within each other, and Mura will automatically search for the config.xml.cfm file in those too.

Please refer to the Elements of the "config.xml.cfm" File section for details about the file itself.

Elements Of The "config.xml.cfm" File

At the top level, a config.xml.cfm document should contain the mandatory <mura> element. There are no attributes available for this element, unless being used with a module/display object.

The following table describes available attributes, only if used with a module/display object.

Attribute Req/Opt Default Description
name Required This is the actual name or title of the module/display object.
contenttypes Optional empty string If blank, it will never display as a draggable option. You may use the asterisk (*) to indicate the display object may be used on all content types. Or, you may pass in a comma-delimited list of content types the display object may be used on. For example, contenttypes="{Type | Type/Subtype},Folder/Blog,Folder/News".
omitcontenttypes Optional empty string You may use the asterisk (*) to indicate the display object should not be used on any content types. Or, you may pass in a comma-delimited list of content types the display object should not be used on. For example, contenttypes="{Type | Type/Subtype},Folder/Blog,Folder/News".
condition Optional true You may pass in a condition to be evaluated at runtime as to whether the display object should be available. For example, condition="(m.content('title') == 'News')".
iconclass Optional mi-cog You may use a Fontawesome icon class, prefixed with "mi-" instead of "fa-" to avoid potential conflicts. For example, iconclass="mi-book". The icon specified here will be used to identify the display object.
cacheoutput Optional true If false, output will not be cached, when Site Caching is enabled.

Example <mura>

This attributes will only be used with a display object.

<mura name="My Display Object" contenttypes="*" iconclass="mi-book">
  ...
</mura>

Subordinate to the <mura> element is an <imagesizes> element, which may contain one or more custom image sizes, and an <extensions> element, which may contain one or more custom class extension definitions.

<mura>
    <imagesizes>
    </imagsizes>
    <extensions>
    </extensions>
</mura>

Note: Plugins have additional elements, and will be covered in the Plugin Development section.

<imagesize> is a sub-element of <imagesizes>

The following table describes the available attributes.

Attribute Req/Opt Description
name Required Treat the value of this attribute as a variable name. In other words, do not include any spaces or special characters.
width Required Specify the numeric width in pixels.
height Required Specify the numeric height in pixels.

Example <imagesize>

<imagesize name="yourimagesizename" width="600" height="100"/>

<extension> is a sub-element of <extensions>

The following table describes the available attributes.

Attribute Req/Opt Description
type Required

The Base Type to apply the class extension to. Valid options are:

  • 1 (to indicate User Group)
  • 2 (to indicate User)
  • Address
  • Page
  • Folder
  • File
  • Calendar
  • Link
  • Component
  • Site
  • Base
subtype Required Use "default" to apply the class extension to all, or enter a custom subtype. Does not apply to the Site type.
availablesubtypes Optional Answers the question; "Allow users to add only specific subtypes?". Leave blank to allow all content types. Or, you may pass in a comma-delimited list of content types. For example, availablesubtypes="{Type | Type/Subtype},Folder/Blog,Folder/News".
description Optional May enter a description for the class extension.
hasassocfile Optional Answers the question; "Show 'Associated Image' field when editing?". Valid options are: 1 (yes/true), 0 (no/false). Default is "1".
hasbody Optional Answers the question; "Show 'Body' field when editing?". Valid options are: 1 (yes/true), 0 (no/false). Default is "1". Applies to Page, Folder, and Calendar.
hasconfigurator Optional Answers the question; "Show 'List Display Options' field when editing?". Valid options are: 1 (yes/true), 0 (no/false). Default is "1". Applies to Folder only.
hassummary Optional Answers the question; "Show 'Summary' field when editing?". Valid options are: 1 (yes/true), 0 (no/false). Default is "1". Applies to Page, Folder, File, Calendar, and Link.
iconclass Optional You may use a Fontawesome icon class, prefixed with "mi-" instead of "fa-" to avoid potential conflicts. For example, iconclass="mi-book". The icon specified here will be used to identify the display object.
isactive Optional Answers the question; "Status". Valid options are: 1 (yes/true), 0 (no/false). Default is "1".

Example <extension>

<extension type="Page" subType="Product" hasSummary="1" hasBody="1" isActive="1">
	...
</extension>

<attributeset> is a sub-element of <extension>

An attribute set is similar to creating a <fieldset> element in HTML.

The following table describes the available attributes.

Attribute Req/Opt Description
name Required This will display on the content edit screen as the title or label above the grouping of associated attributes, similar to a fieldset's legend.
container Required This is the "tab" container which the grouping of associated attributes will be displayed on. Valid options depend on the content Type. See the Available Container Options table.
orderno Optional Specify the numeric

Available Container/Tab Options

Option Description
Basic Displays the attribute set on the Basic tab.
Default Displays the attribute set on the Extended Attributes tab. This is the default setting.
Custom Will not display the attribute set by default. This allows for a developer to create a custom user interface to collect the data.
List Display Options DIsplays the attribute set on the List Display Options tab.
Layout & Objects Displays the attribute set on the Layout & Objects tab.
Categorization Displays the attribute set on the Categorization tab.
Tags Displays the attribute set on the Tags tab.
Related Content Displays the attribute set on the Related Content tab.
Advanced Displays the attribute set on the Advanced tab.
Publishing Displays the attribute set on the Publishing tab.
Usage Report Displays the attribute set on the Usage Report tab.

Valid Container/Tab Options

The following table describes available options to use as the value for each Base Type.

Base Type Container/Tab Options
1 (User Groups), 2 (Users), & Site
  • Default
  • Custom
Pages, Folders, Links, Files, and Calendars
  • Basic
  • Default
  • List Display Options
  • Layout & Objects
  • Categorization
  • Tags
  • Related Content
  • Advanced
  • Publishing
  • Usage Report
  • Custom
Address, Custom, and Base
  • Basic
  • Default
  • Custom
Component
  • Basic
  • Default
  • Categorization
  • Usage Report
  • Custom

Example <attributeset>

<attributeset name="Mobile Options" container="Basic" orderno="1">
    ...
</attributeset>

<attribute> is a sub-element of <attributeset>

An attribute describes a data container (form field) and its validation rules.

The following table describes required and optional attributes of the <attribute> element:

Attribute Description
name The variable name. This will also become the form fields "name" attribute.
label The label that will be displayed on the form
hint A tooltip hint for the form field
type Valid options: TextBox (default), TextArea, HTMLEditor, SelectBox, MultiSelectBox, RadioGroup, File, Hidden
required Valid options: true, false (default)
validation Leave blank if not using validation. Otherwise, valid options are: Date, DateTime, Numeric, Email, Regex, Color, and URL.
regex If validation is set to Regex, then you can enter a JavaScript regular expression to execute when the form is submitted.
message The error message that displays when validation fails.
defaultvalue Optional. The default value for the form field.
optionlist A carat "^" delimited list of option values. Used when type is set to SelectBox, MultiSelectBox or RadioGroup.
optionlabellist A carat "^" delimited list of option labels. Used when type is set to SelectBox, MultiSelectBox or RadioGroup.
adminonly Valid options: 0 for false (default), 1 for true. Whether the attribute is for administrator use only, and will not be displayed.

Note: To enable a color picker for a form field, set type="TextBox" and validation="Color"

Example config.xml.cfm

<?xml version="1.0" encoding="UTF-8"?>
    <mura>
        <!-- Image Sizes -->
        <imagesizes>
          <imagesize
            name="locationimage"
            width="600"
            height="400"/>
        </imagesizes>

        <!-- Class Extensions -->
        <extensions>
            <extension 
                adminonly="0" 
                availablesubtypes="Page/Location" 
                description="" 
                hasassocfile="0" 
                hasbody="0" 
                hasconfigurator="0" 
                hassummary="0" 
                iconclass="mi-map-o" 
                subtype="Locations" 
                type="Folder"/>

            <extension 
                availablesubtypes="" 
                description="" 
                hasassocfile="1" 
                hasbody="0" 
                hasconfigurator="0" 
                hassummary="1" 
                iconclass="mi-map-pin" 
                subtype="Location" 
                type="Page">

                <attributeset 
                    container="Basic" 
                    name="Location Options" 
                    orderno="1">

                    <attribute 
                        adminonly="0" 
                        defaultvalue="" 
                        hint="" 
                        label="Location Street" 
                        message="Please enter a Location Street" 
                        name="locationstreet" 
                        optionlabellist="" 
                        optionlist="" 
                        orderno="1" 
                        regex="" 
                        required="true" 
                        type="TextBox" 
                        validation=""/>

                    <attribute 
                        adminonly="0" 
                        defaultvalue="" 
                        hint="" 
                        label="Location City" 
                        message="Please enter a Location City" 
                        name="locationcity" 
                        optionlabellist="" 
                        optionlist="" 
                        orderno="2" 
                        regex="" 
                        required="true" 
                        type="TextBox" 
                        validation=""/>

                    <attribute 
                        adminonly="0" 
                        defaultvalue="" 
                        hint="" 
                        label="Location State" 
                        message="Please enter a Location State" 
                        name="locationstate" 
                        optionlabellist="" 
                        optionlist="" 
                        orderno="3" 
                        regex="" 
                        required="true" 
                        type="TextBox" 
                        validation=""/>

                    <attribute 
                        adminonly="0" 
                        defaultvalue="" 
                        hint="" 
                        label="Location Postal Code" 
                        message="" 
                        name="locationpostalcode" 
                        optionlabellist="" 
                        optionlist="" 
                        orderno="4" 
                        regex="" 
                        required="false" 
                        type="TextBox" 
                        validation=""/>

                </attributeset>
            </extension>
        </extensions>
    </mura>

Export Definitions via Admin UI

Mura is able to export Class Extensions as an XML file via the back-end administration UI. This is the recommended method for creating XML Class Extension definitions, as opposed to writing the XML by hand. By using this method, you're able to reduce the likelihood of typos or introducing errors when Mura attempts to parse your XML file(s).

There are two methods for exporting Class Extensions. You can export them individually, or select multiple extensions to export as a single XML file.

Export Single Class Extension

To export a single Class Extension, follow the steps outlined below.

  1. From the back-end administration area of Mura, select Site Settings, click Class Extensions, and select Class Extensions.
  2. You should be directed to the Class Extensions screen.
  3. Select the Class Extension you wish to export, from the listing of available Class Extensions.
  4. You should be directed to the Class Extension screen.
  5. Click the Export Class Extension button.
  6. You should directed to the Export Class Extensions screen.
  7. You can hover over the code, and press <CTRL>+C on a PC, or <CMD>+C on a Mac to copy it to your clipboard, then paste the code into your own XML file.
  8. Or, you can simply click the Download button at the bottom of the screen, to download the code as a XML file.
  9. You now have a file that can be used to import the Class Extension into another instance of Mura, or package it with a display object's config.xml.cfm file or a plugin's config.xml.cfm file for future distribution.

Export Multiple Class Extensions

To export multiple Class Extensions at the same time, so they can be packaged together in a single XML file, follow the steps outlined below.

  1. From the back-end administration area of Mura, select Site Settings, then click Class Extensions, and select Export Extensions.
  2. Or, from the Class Extension screen, select the Actions button, then click Export.
  3. You should be directed to the Export Class Extensions screen.
  4. Select the Class Extensions you wish to export, or simply click Select All to check all available Class Extensions if you desire to do so.
  5. Click the Export button.
  6. You should now be directed to the Export Class Extensions screen.
  7. You can hover over the code, and press <CTRL>+C on a PC, or <CMD>+C on a Mac to copy it to your clipboard, then paste the code into your own XML file.
  8. Or, you can simply click the Download button at the bottom of the screen, to download the code as a XML file.
  9. You now have a file that can be used to import the Class Extension into another instance of Mura, or package it with a display object's config.xml.cfm file or a plugin's config.xml.cfm file for future distribution.

Import Definitions via Admin UI

To import Class Extensions, you will first need a properly formatted XML file, preferably exported via Mura's admin UI. Once you have a properly formatted XML file, follow the steps below to import the Class Extensions.

  1. From the back-end administration area of Mura, select Site Settings, click Class Extensions, then select Import Extensions.
  2. Or, from the Class Extensions screen, select the Actions button, and click Import.
  3. You should be directed to the Import Class Extensions screen.
  4. Click the Browse or Choose File button, then select navigate to the exported XML file.
  5. When ready, click the Import button.
  6. Mura will then upload, and attempt to parse the submitted XML file. When the import has completed, your new Class Extensions should appear in the list on the Class Extensions screen.

Displaying Extended Attributes

There are a few ways to display the attributes of Class Extensions, and it really depends on where you're attempting to display them. That said, the most important thing to keep in mind is that you'll need to know your attribute's name property, in order to display it.

In short, a Class Extension's attribute is treated as a property of the bean it's associated with. So, for example, if a Class Extension's Base Type is Content, then you could use the same getter and setter methods when working with any other attribute of a Content Bean.

Basic Syntax

The basic syntax is shown in the example below.

someBean.get('attributeName')
someBean.get{AttributeName}()
someBean.getValue('attributeName')

Examples

The examples listed below demonstrate the most common method for accessing attributes of a Class Extension. In addition, the recommended best practice is to use esapiEncode when outputting attributes.

Via Layout Template

This example assumes the Base Type is "Content", and you merely want to display the attribute on a layout template.

<cfoutput>
  <h2>
    #esapiEncode('html', m.content('attributeName'))#
  </h2>
</cfoutput>

Via HTML Editor

This example assumes you wish to output an attribute in the body of a HTML Editor.

[m]esapiEncode('html', m.content('attributeName'))[/m]

Via Content Bean

This example assumes you load a Content Bean, and then want to retrieve the data for whatever reason.

contentBean = m.getBean('content').loadBy(title='Home');
// assumes we have a custom attribute labeled `locationstreet`
street = contentBean.get('locationstreet');

Via Iterator

You can easily pull out attributes of Class Extensions while looping inside of a Mura Iterator.

<!--- get an iterator of the content item's children --->
<cfset it = m.content().getKidsIterator()>
<ul>
<cfloop condition="it.hasNext()">
  <cfset item = it.next()>
  <li>
    #esapiEncode('html', item.get('attributeName'))#
  </li>
</cfloop>
</ul>

Making Attributes Editable

When displaying an extended attribute in a layout template, you may want to make the attribute editable by content managers when they're using front-end editing features. This is accomplished by using m.renderEditableAttribute.

Note: This feature only works on extended attributes with its Input Type set to TextBox or HTMLEditor.

Function Syntax

m.renderEditableAttribute(
  attribute
  , type
  , required
  , validation
  , message
  , label
  , value
  , enableMuraTag
)

Parameters

Parameter Type Req/Opt Default Description
attribute string required   The attribute's name
type string opt text

Valid options are:

  • text
    • Treats the attribute as text being entered into a TextBox
  • HTMLEditor
    • When editing content via inline edit mode, and a content manager double clicks into the text, a HTML Editor toolbar will appear.
required boolean opt false If true, Mura will require a value to be entered before saving successfully.
validation regex opt blank Leave blank, or enter a JavaScript regular expression to use for validation purposes. Will trigger if a value is entered and a save is attempted.
message string opt empty string The message to display when the submitted value does not pass validation.
label string opt attribute name Text to display above the field when edited.
value string opt the attribute's stored value Optionally pass in a string to preset the value.
enableMuraTag boolean opt false If true, the value will be parsed by Mura's setDynamicContent to render any Mura [m] tags.

Example

The following example demonstrates how to use m.renderEditableAttribute for an attribute with its Input Type set to HTMLEditor.

<cfoutput>
  <div>
    #m.renderEditableAttribute(
      attribute='attributeName'
      type='HTMLEditor'
      label='Attribute Label'
    )#
  </div>
</cfoutput>

Mura Modules & Display Objects

Mura's baked-in modules are managed via the front-end user interface. Modules are sometimes referred to as "display objects" because often times, that's how the module itself is used. However, a Mura module does not have to contain a "display" of any kind. Modules can be complete applications, or simply contain some custom logic that is triggered based on a desired event.

Note: If you aren't familiar with Mura's default Modules, you should review the Layout Manager Modules section of the Using Mura Guide before continuing in this section.

Mura includes a variety of baked-in modules (display objects) by default while offering content managers the ability to quickly and easily add modules such as Collections, Components, Containers, Forms, Navigation, and many more.

Each of Mura's modules contain some server-side logic, basic markup, styling, and sometimes include JavaScript. In this section, you'll learn how to safely modify this logic, markup, styling, and/or JavaScript, and do so without worrying about your changes getting overwritten whenever Mura's files are updated. In addition, you'll learn how to create your own, custom modules too.

Modifying Mura's Modules

Mura's base modules (display objects) are located under the following directory:

{context}/core/modules/v1/

As illustrated in the image below, there are more modules than the ones listed.

You shouldn't modify any of the files in these directories directly. If you choose to do so, you run the risk of your changes being overwritten whenever Mura is updated to the latest version.

Instead, copy the desired directory and all of its files, then paste it under one of the locations listed in the "Lookup Hierarchy" section below. Then, you can safely make your modifications without fear of losing any of your changes the next time Mura is updated.

Registering a Custom "modules" Directory

While Mura automatically scans for modules in the directories specified in the "Lookup Hierarchy" section below, you may register a custom "modules" directory using the code example below.

m.siteConfig().registerModuleDir(
  dir='/path/to/your/modules/'
);

The directory path should be a logical path to a CFML directory, and is usually registered in the onApplicationLoad() event.

Lookup Hierarchy

As mentioned under "The 'Modules' Directory" section, Mura uses the following lookup hierarchy when searching for modules, and aborts the lookup process once the target module has been located:

  • Registered Module Directory
    • {RegisteredModuleDirectory}/
    • A pre-registered module directory path. See "Registering a Custom 'Modules' Directory" section above.
  • Module
    • ../{module}/modules/
    • A nested "modules" directory nested within a known module.
  • Theme
    • ../themes/{ThemeName}/modules/
    • Theme modules are only used when the specified theme is actively assigned to a site. Keep in mind themes may be located under either the global themes directory ({context}/themes/{ThemeName}), or under a site ({context}/sites/{SiteName}/themes/{ThemeName}).
  • Site
    • {context}/sites/{SiteName}/modules/
    • Site modules are shared across all themes within the specific site.
  • Global
    • {context}/modules/
    • Global modules are shared across all sites under a single Mura instance.
  • Core
    • {context}/core/modules/v1/core_assets/modules/
    • These are the "core" modules or display objects which may be copied and placed into any of the directories above to be safely modified.

Note: You should not edit the "core" modules directly. If you do, you run the risk of losing your edits or changes whenever you update Mura to the latest version.

Anatomy of a Module

Mura's default modules follow a specific directory structure and file naming convention. These conventions also apply to the development of custom modules (including those known as Mura "display objects" in prior versions).

Directory Structure

First, create a subdirectory using the name of the module, under any standard or registered "modules" directory within the Mura file structure. For example, ../sites/mysite/modules/mymodule/ or  ../themes/mytheme/modules/{module}/. 

Inside of the{module} directory, you may use the following files and directories as applicable:

File or Directory Req/Opt Description
index.cfm Optional If your module will be used as as part of the Layout Manager, this file will manage and/or contain the view that is rendered to the browser. See example "index.cfm" file section below.
config.xml.cfm Optional This is the configuration file for the module itself. This file also allows you to include custom image sizes, class extensions, and more. See example "config.xml.cfm" file section below. Also see Elements Of The "config.xml.cfm" File for more about available elements and attributes.
configurator.cfm Optional This file allows developers to include a form with configuration options which appear on the module configuration panel when using the Inline Edit feature. See example "configurator.cfm" file section below.
/model/ Optional In order to leverage Mura ORM, the module can contain its own "model" directory, which in turn may also include  "beans" and/or "handlers" directories. See Mura ORM Configuration for more about the "model" directory.
/content_types/ Optional You may also include custom content types. This is useful for keeping content types directly related to specific module(s) together, in a unified directory structure. See Content Type for more information.
/modules/ Optional You may also nest custom modules. This is useful for keeping related modules together, under one, unified module itself. One caveat is that if you choose to display the nested object on the parent object, content managers will not be able to access the nested object's configurator, if it has one. Because of this, you may wish to either omit the "contenttypes" attribute from your config.xml.cfm's <mura ...> node, or explicitly add contenttypes="" so that the nested object will not appear in the module panel's UI. If you need configurable options for the nested object, you should include the options on the parent object's configurator. To include the nested object in the view of the parent object, use the following syntax: #m.dspObject(object='{objectName}', objectparams=objectparams)#.

Example "index.cfm" File

The example below shows the contents of a basic "index.cfm" file for a module.
For custom modules, you may include your own code or markup as needed.

<cfparam name="objectparams.mytext" default="" />

<cfoutput>
  <h2>My Object</h2>

  <cfif Len(objectparams.mytext)>
    <p>
      This object has a configurator, and the value of "objectparams.mytext" is:<br>
      <strong>#esapiEncode('html', objectparams.mytext)#</strong>
    </p>
  <cfelse>
    <!--- No value entered for "objectparams.mytext" --->
  </cfif>
</cfoutput>

Use MuraJS to add any CSS or JavaScript to your module. The example below leverages the loader() method to load both CSS and JavaScript. Simply add this code to your "index.cfm" file, changing file paths to match your specific directory structure and filenames as needed.

<!--- Add the following to your "index.cfm" file --->
<script>
  Mura(function(m) {
    m.loader()
      .loadcss(m.themepath + '/modules/myobject/my.css')
      .loadjs(
        m.themepath + '/modules/myobject/my.js',
        m.themepath + '/modules/myobject/other.js',
        function() {
          // Do something with the loaded JS, if desired
        }
      );
  });
</script>

Visit the MuraJS section to learn more about Mura.loader() capabilities.

Rendering Via JavaScript

If your module will be rendered using only JavaScript, your index.cfm file should only contain the following code:

<cfset objectparams.render="client">

Choosing this option means you'll have to load your JavaScript by using a custom event handler method, as shown below.

// ../yourmodule/model/handlers/yourhandler.cfc

component extends='mura.cfobject' {

  function onRenderStart(m) {
    // if script should be included in the <head>
    arguments.m.addToHTMLHeadQueue('<script src="/path/to/script.js"></script>');

    // OR

    // if script should be included before closing </body> tag
    arguments.m.addToHTMLFootQueue('<script src="/path/to/script.js"></script>');
  }

}

Please also see the Modules and Display Objects and Mura JS sections for more information on rendering modules via JavaScript.

Example "config.xml.cfm" File

This is one example of a standard "config.xml.cfm" file. Visit the Elements Of The "config.xml.cfm" File section for more details on available elements and attributes.

<?xml version="1.0" encoding="UTF-8"?>
  <mura name="My Module" contenttypes="*" iconclass="mi-rebel">
    <!-- May also include other elements here -->
  </mura>

Example "configurator.cfm" File

This is very basic example of a module's "configurator.cfm" file.

<cfparam name="objectparams.mytext" default="" />

<cfoutput>
    <div class="mura-control-group">
        <label class="mura-control-label">My Text</label>
        <input  type="text"
                name="mytext"
                class="objectParam"
                value="#esapiEncode('html_attr', objectparams.mytext)#" />
    </div>
</cfoutput>

See the Module Configurators for more on proper markup conventions.

Content Types

In addition to using some of Mura's content-related event hooks, developers can control the rendering of the body area by targeting a content's Type and Subtype. This feature also applies to any custom Class Extensions. For example, "Folder/Contacts", "Page/Contact", etc.

Mura automatically scans the following directories for custom content types:

  • {context}/themes/{ThemeName}/content_types/
  • {context}/sites/{SiteID}/themes/{ThemeName}/content_types/
  • {context}/sites/{SiteID}/content_types/
  • ../content_types/{type}/content_types/
  • ../content_types/{type}_{subtype}/content_types/

Or, you can register any directory you want by using the following syntax:

m.siteConfig().registerContentTypeDir(
  '/path/to/your/content_types/'
);

// Path is a logical path to a CFML directory
// Usually registered in onApplicationLoad();

Note: This feature only works if the layout template is using m.dspBody() to render the body area.

Control Body By Type/Subtype

You target the body's Type/Subtype by a conventional directory structure.

For example, you could target content by only its Type:

../content_types/{type}/

// If you wish to target 'Page'
../content_types/page/index.cfm

Or, you can target by both the Type, and its Subtype:

../content_types/{type}_{subtype}/

// If you wish to target 'Page/Contact'
../content_types/page_contact/index.cfm

Anatomy of a {type}_{subtype} Directory

As previously mentioned, you create a directory under a known or registered "content_types" directory by using {type}_{subtype} (e.g., ../content_types/page_contact/ or ../.content_types/component_default/, etc.). Within the {type}_{subtype} directory, you may have the following files and/or directories:

File or Directory Req/Opt Description
index.cfm Required This is the body or view used by Mura for display file itself. At a minimum, this file should contain <cfoutput>#m.renderEditableAttribute(attribute="body",type="htmlEditor")#</cfoutput>, if you wish to see any text entered into the "Content" area. See example "index.cfm" file below.
config.xml.cfm Optional This is the configuration file. This allows you to include custom image sizes, class extensions, and more. See Elements Of the "config.xml.cfm" File section for more information.
/model/ Optional If you wish to leverage Mura ORM, the content type could have its own "model" directory, which in turn could also include a "beans" and/or "handlers" directory too. See Mura ORM Configuration section for more information about the "model" directory.
/modules/ Optional You may also include custom modules. This is useful for keeping modules and/or display objects directly related to specific content types together, in a unified directory structure. See Modules section for more information. See below for information on how to output modules in your layout template.
/content_types/ Optional You may include a nested "content_types" directory. This is a great way to keep related code items together.

Example "index.cfm" File

The example below illustrates what an "index.cfm" file could contain. However, you may include your own custom markup, code, and more.

<cfoutput>
  <article class="article">
    <!--- Page Title --->
    <h2 class="article__title">#m.renderEditableAttribute(attribute='title')#</h2>

    <!--- Primary Image --->
    <cfif m.content().hasImage(usePlaceholder=false)>
      <figure class="article__image">
        <img src="#m.getURLForImage(fileid=m.content('fileid'), size='medium')#" 
             alt="#esapiEncode('html_attr', m.content('title'))#" />
      </figure>
    </cfif>

    <!--- Content --->
    <div class="article__body">
      #m.renderEditableAttribute(attribute='body', type='htmlEditor')#
    </div>
  </article>
</cfoutput>

How To Output Modules

To output a module (display object) in your custom body layout, use the following syntax:

<cfoutput>
  #m.dspObject(object='{objectName}')#
</cfoutput>

When hardcoding a module in your layout, the "Delete" button will not appear for content managers when using the "Inline Edit" mode.

Including Configurable Modules

The first thing to understand about including configurable modules in your custom body layout is there can only be one (1) module that is configurable. Whichever module you wish to be configurable should include a "objectparams" parameter, and include the "objectparams" as the value, as shown below:

<cfoutput>
  #m.dspObject(object='{objectName}', objectparams=objectparams)#
</cfoutput>

If you attempt to include multiple configurable modules using the code example above, the first module will be configurable, and all others will not. This means, when you select "Inline Edit" mode, only the first configurable module will include the pencil icon and actually be configurable.

To include additional modules, you may pass in any "objectparams" parameters as an object, as show in the example below:

<cfoutput>
  #m.dspObject(
    object='object1', 
    objectparams={param1=objectparams.param1, param2=objectparams.param2}
  )#

  #m.dspObject(object='object2', objectparams=objectparams)#
</cfoutput>

In the example above, "object2" will be the only configurable module.

Internationalization & Localization

Mura utilizes resource bundles to internationalize various areas of the user interface, making the code locale-independent.

Resource bundles are .properties files, located under specified directories in Mura. These .properties files, or resource bundles, are named to indicate the language code, and country code. For example, the language code for English (en) and the country code for United States (US) would be represented as en_US.properties. If Mura cannot find a direct language and region match, it will search for a language match. If a locale's language cannot be found, Mura will fall back to its default of English, or en_US.properties.

The file itself is comprised of key-value pairs. The keys remain the same throughout each of the .properties files, and the value is translated into the file's designated language. If Mura is searching for a specific key-value pair within a translation, and cannot locate it, Mura will fall back to the English translation.

The image below illustrates the en_US.properties file side-by-side with the es_ES.properties file:

Lookup Hierarchy

Mura automatically searches for resource bundles under specific directories, and uses the key-value pair(s) found in the order outlined below. If a resource_bundles directory does not exist in the following locations, you may safely create one, and place your resource bundle files there.

  • Module
    • ../{module}/resource_bundles/
    • Module (aka "Display Object") resource bundles are used for the specific module itself.
  • Content Types
    • ../content_types/{type}_{subtype}/resource_bundles/
    • Content Types resource bundles are used for the specified content type.
  • Theme
    • ../{ThemeName}/resource_bundles/
    • Theme resource bundles are only used when the specified theme is actively assigned to a site.
  • Site
    • {context}/sites/{SiteID}/resource_bundles/
    • Site resource bundles are shared across all themes within the specified site.
  • Global
    • {context}/resource_bundles/
    • Global resource bundles are shared across all sites under a single Mura instance.
  • Core
    • {context}/core/modules/v1/core_assets/resource_bundles/
    • If the requested key-value pair is not defined in any of the locations above, Mura will use the "core" resource bundles located here for Mura's modules.

Note: Admin-area resource bundles are located under {context}/core/mura/resourceBundle/resources/. However, many key-value pairs are not able to be overwritten using the technique described above.

Contribute

If you would like to contribute to the translations project, please visit https://crowdin.com/project/muracms. Your help will be greatly appreciated!

Custom Keys

As previously documented, Mura searches for custom ".properties" files, under the directories listed in the "Lookup Hierarchy" section.

You don't have to include all of the key-value pairs from the original files. You only have to include the key-value pairs you wish to override. In addition, if you have any custom keys you would like to use in your site, you can simply include them in your custom ".properties" files.

Displaying Custom Keys

To output a custom key-value from your ".properties" file, simply use m.rbKey({keyName}).

So, for example, to output a key of "myCustomString", use the following syntax.

<cfoutput>
  #m.rbKey('myCustomString')#
</cfoutput>

Custom Factories

Mura allows you to create your own resource bundle factories, and fall back to Mura's original lookup hierarchy when a requested key-value is not found. This is especially useful when creating plugins, or integrating a custom application.

The code example below demonstrates how you could go about creating a custom resource bundle factory.

customResourceBundleDirectory = ExpandPath('#m.globalConfig('context')#/path/to/your/RBFactory/');

customFactory = new mura.resourceBundle.resourceBundleFactory(
  parentFactory = m.siteConfig('rbFactory')
  , resourceDirectory = customResourceBundleDirectory
  , locale = m.siteConfig('JavaLocale')
);

You could wrap this up into a custom method to obtain a reference to your custom factory using something similar to the following example.

public any function getResourceBundleFactory(required struct m) {
  var resourceDirectory = ExpandPath('#arguments.m.globalConfig('context')#/plugins/MyPlugin/rb/');
  return new mura.resourceBundle.resourceBundleFactory(
    parentFactory = arguments.m.siteConfig('rbFactory')
    , resourceDirectory = resourceDirectory
    , locale = arguments.m.siteConfig('JavaLocale')
  );
}

Once you've created your custom resource bundle factory, simply use {yourCustomFactoryVariableName}.getKey({yourKey})

So, for example, to output a key of "myCustomString", with a custom factory variable named "customFactory", use the following syntax.

<cfoutput>
  #customFactory.getKey('myCustomString')#
</cfoutput>

Caching

Mura has a built-in caching mechanism that, when enabled, will store data in memory for reuse. The purpose for this is to improve overall site performance, by decreasing the amount of reads to the database. Mura's caching uses a "lazy load" approach, which means data won't be cached until it's called upon the first time.

How to Enable/Disable Site Caching

Follow the steps below to enable and/or disable site caching.

  1. From the back-end administrator, on the main navigation, click Site Settings, then select Edit Settings
  2. From the Site Settings screen, select the Basic tab.
  3. Scroll down to Site Caching.
    • Select On to enable site caching.
    • Select Off to disable site caching.
  4. After making your selection, click Save Settings.

Cache Free Memory Threshold

By default, when Site Caching is enabled, Mura will only store data into memory when the Java virtual machine (JVM) has at least sixty percent (60%) available memory. You may choose to set an alternate minimum desired percentage by following the steps outlined below.

  1. From the back-end administrator, on the main navigation, click Site Settings, then select Edit Settings.
  2. From the Site Settings screen, select the Basic tab.
  3. Scroll down to Cache Free Memory Threshold (Defaults to 60%), and enter in your desired percentage amount. If you enter zero (0), Mura will revert to using its default setting of sixty percent (60%).
  4. After entering your desired amount, click Save Settings.

cf_CacheOMatic Tags

One of the easiest ways to improve the performance of your site, is to use proven caching techniques. In addition to the native caching strategies for CFML, Mura also offers a special, custom tag, <cf_CacheOMatic>, to use for expensive database transaction code, or other time-consuming CFML code that doesn't need to be executed during each request.

Using Mura's <cf_CacheOMatic> tag allows you to add data to Mura's cache. The tag only works when Site Caching is enabled, which is a great reason to use it since you can easily disable it, if necessary.

The custom tag is located under {context}/core/mura/customtags/CacheOMatic.cfm if you would like to inspect the file to see how it works under the hood.

Tag Syntax

<cf_CacheOMatic>
  Code or data to cache.
</cf_CacheOMatic>

Attributes

Attribute Type Default Description
key string CGI.scriptname & CGI.query_string A unique string to associate with the specified data. Used to retrieve the cached data, when Site Caching is enabled.
timespan datetime CreateTimeSpan(0,0,30,0) The desired time period the data should be cached for before it expires. (Defaults to 30 minutes).
scope string application The desired CFML scope in which to store the data. Valid options are application, session, and server.
nocache boolean false If true, Mura will not cache the code/data contained within the tag. Useful for explicitly omitting code from being cached.
purgecache boolean request.purgecache If true, Mura will empty its cache.
siteid string request.siteid You may choose to specify an alternate SiteID to associate the cache to.

Usage

Use this custom tag to cache inline content or data within layout templates.

Examples

Using the "key" Attribute

This example uses the ContentID of the content item as the key with prefix of "page-".

<cf_CacheOMatic key="page-#m.content('contentid')#">
  <h2 class="page-title">#esapiEncode('html', m.content('pagetitle'))#</h2>
</cf_CacheOMatic>

Using the "nocache" Attribute

The following example demonstrates how you could use the nocache attribute to see an "un-cached" version of the output by simply appending ?nocache=true to the URL.

<cf_CacheOMatic 
     key="example-timestamp1" 
     nocache="#m.event('nocache')#">
  <p>The time is now: #LSTimeFormat(Now())#</p>
</cf_CacheOMatic>

Using the "timespan" Attribute

In this example, we're setting the cache to expire in five (5) hours.

<cf_CacheOMatic
     key="example-timestamp2"
     nocache="#m.event('nocache')#"
     timespan="#CreateTimeSpan(0,5,0,0)#">
  <p>The time is now: #LSTimeFormat(Now())#</p>
</cf_CacheOMatic>

Programmatic Caching

As covered in the cf_CacheOMatic Tags section, Mura allows developers to add data to Mura's cache. One thing to keep in mind is your data or code may be either intentionally or even inadvertently wrapped by cf_CacheOMatic tags, subjecting your output to the settings of the tag.

However, as a developer, you may have data or code you wish to either explicitly exclude from being added to Mura's cache. Or, you may wish to set a specific duration of time the data or code may be cached for. Mura also allows developers to achieve this using the code snippets described below.

request.cacheItem

This code snippet controls whether the code or data will be cached if wrapped by cf_CacheOMatic tags. If true, the code or data will be cached according to the settings of the containing cf_CacheOMatic tags. If false, the code or data will not be cached.

Note: A side-effect of setting request.cacheItem to false is none of the code or data within the containing cf_CacheOMatic tags will be cached at all.

Syntax

request.cacheItem = {true || false}

Example

<cfset request.cacheItem = false />
<!--- The following timestamp will NOT be cached --->
<cfoutput>
  <p>The date/time is #Now()#</p>
</cfoutput>

request.cacheItemTimeSpan

This code snippet controls the duration of time the code or data will be cached for.

Syntax

request.cacheItemTimeSpan = {TimeSpan Object}

Example

<cfset request.cacheItemTimeSpan = CreateTimeSpan(0, 0, 5, 0) />
<!--- The following timestamp will be cached for 5 minutes, if wrapped by cf_CacheOMatic tags --->
<cfoutput>
  <p>The date/time is #Now()#.</p>
</cfoutput>