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.
- "Theme" contentRenderer
../themes/{ThemeName}/contentRenderer.cfc
- "Site" contentRenderer
{context}/sites/{SiteID}/includes/contentRenderer.cfc
- "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:
|
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:
|
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.
- From Mura's back-end administration area, select Site Settings, click Class Extensions, and select Add Class Extension.
- 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.
- From the Add Class Extension screen, click the Base Type menu, and choose your desired option, (e.g., Page).
- 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.
- When finished, click the Add button, so save your new Class Extension.
- 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.
- From the back-end administration area of Mura, select Site Settings, click Class Extensions, and select Class Extensions.
- You should be directed to the Class Extensions screen.
- Select the Class Extension you wish to add an Extended Attribute Set to, from the listing of available Class Extensions.
- You should be directed to the Class Extension screen. Here, you can view any available Extended Attribute Sets or Related Content Sets.
- To add an Extended Attribute Set, click the Add button, then select Add Attribute Set.
- 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
- Once you've entered an Attribute Set Name, and selected your desired Container (Tab), click the Add button to create your new attribute set.
- 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.
- To create a new attribute, click the Add New Attribute button.
- 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
- 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.
- After you've completed the form, click the Add button to create your new attribute.
- Repeat these steps to create additional attributes for the Extended Attribute Set.
- 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.
- Then, hover over the attribute you wish to move, and then click, drag, and drop to your desired location.
- When finished reordering, click the Save Order button.
Related Content Sets
Related Content Sets 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. To create a Related Content Set, follow the steps outlined below.
- From the back-end administration area of Mura, select Site Settings, click Class Extensions, and select Class Extensions.
- You should be directed to the Class Extensions screen.
- Select the Class Extension you wish to add a Related Content Set to, from the listing of available Class Extensions.
- You should be directed to the Class Extension screen. Here, you can view any available Extended Attribute Sets and Related Content Sets.
- To add a Related Content Set, click the Add button, then select Add Related Content Set.
- You should be taken to the Add Related Content Set screen.
- Related Content Set Name
- Text entered here will display above the new field as the label for content managers to identify it.
- Allow users to add only specific subtypes?
- If Yes, you may select one, or more options from the available list. This will restrict the type of content that content managers are able to assign to the specific Related Content Set.
- When finished completing the form, click the Add button.
- Now, when a content manager edits content, and selects the Related Content tab, your new Related Content Set will appear. Also note that any
Subtype
restrictions will be displayed as well.
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 |
|
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 |
|
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.
- From the back-end administration area of Mura, select Site Settings, click Class Extensions, and select Class Extensions.
- You should be directed to the Class Extensions screen.
- Select the Class Extension you wish to export, from the listing of available Class Extensions.
- You should be directed to the Class Extension screen.
- Click the Export Class Extension button.
- You should directed to the Export Class Extensions screen.
- 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.
- Or, you can simply click the Download button at the bottom of the screen, to download the code as a XML file.
- 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.
- From the back-end administration area of Mura, select Site Settings, then click Class Extensions, and select Export Extensions.
- Or, from the Class Extension screen, select the Actions button, then click Export.
- You should be directed to the Export Class Extensions screen.
- 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.
- Click the Export button.
- You should now be directed to the Export Class Extensions screen.
- 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.
- Or, you can simply click the Download button at the bottom of the screen, to download the code as a XML file.
- 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.
- From the back-end administration area of Mura, select Site Settings, click Class Extensions, then select Import Extensions.
- Or, from the Class Extensions screen, select the Actions button, and click Import.
- You should be directed to the Import Class Extensions screen.
- Click the Browse or Choose File button, then select navigate to the exported XML file.
- When ready, click the Import button.
- 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.
- From the back-end administrator, on the main navigation, click Site Settings, then select Edit Settings
- From the Site Settings screen, select the Basic tab.
- Scroll down to Site Caching.
- Select On to enable site caching.
- Select Off to disable site caching.
- 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.
- From the back-end administrator, on the main navigation, click Site Settings, then select Edit Settings.
- From the Site Settings screen, select the Basic tab.
- 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%).
- 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>