Modules and Display Objects
Last updated
Was this helpful?
Last updated
Was this helpful?
With Mura 7.1 the Mura documentation seemed to make a shift in (previously) referring to Display Objects to using the term "modules". The re-branding of Display Objects better reflects the modularity and portability, as well as the fact that the modules/display objects don't need to have a display/view element to them whatsoever. For the remainder of this documentation we're using the new terminology "module". Mura has an array of included modules (collections, components, forms, navigation, etc.) and offers us the ability to create our own modules.
Mura provides us the ability to create our own modules that offer a great way to encapsulate business and display logic (even an entire application if we desired) and embed that within our theme or site template files. Mura modules can easily contain server-side logic, basic markup, styling, and even include JavaScript. Additionally, if portability is needed, modules can easily be wrapped with additional code/structure to create a Mura plugin.
As stated above, Mura comes with a lot of its core CMS user-accessing functionality encapsulated into modules that content editors can have access to manage page content and functionality. When using inline editing of a page, these modules are displayed in a right-side tool bar as follows:
We can create, register, and add our own modules to this listing providing drag-n-drop access to content managers or, alternatively, we can create modules that are invoked differently through triggered events or class extensions of Mura's built-in content types. For example, if we create a class extension of the Mura "Folder" content type and give it our own sub-type of "News", when we apply the "News" content sub-type, we can trigger the use of a module to control how the content is rendered for the content object. In such a case, our module is automatically invoked and therefore isn't listed in the inline editor module selector as content managers will not need to manually add the module to a content object.
There is a lot to modules so the easiest way to demonstrate the usability of modules is by taking an existing Mura module, "Collections", and modifying it to create a custom Folder view for a blog/news layout. This will skip a lot of the details associated with certain aspects of the modules, such as config.xml.cfm and configurator.cfm but will allow us to get into the meat of a module's ability to render a custom view for web page content.
Like many things in Mura, there is more than one way to do what we want to accomplish, which is to have our own version of the Folder content object rendering where Mura automatically loops through all of the content items under the folder and inserts elements of them on the folder view. In other words, we're trying to turn this:
Into this:
As stated, there is more than one way to make these changes which includes (but surely isn't limited to):
Modifying the default Mura Folder content object rendering by editing the Mura default modules in the /core/modules/v1/folder
and /core/modules/v1/collection
directories. Never do this. Ever. This would 1) affect all folder rendering on the site (not just what is being used for a blog) and 2) the changes could easily be wiped out when Mura is updated as these are not protected theme files and are instead, as can be seen by the directory structure, part of the core Mura framework.
Modify the styles that the collection object uses (e.g. "containerEl") from the theme's contentRenderer.cfc. This may get you what you desire as there are a lot of options for applying classes and tags that may meet the needs of your template to get the rendering you desire. However, your theme may require elements (specific sequencing of HTML elements, specific tags, specific classes) that is not presently supported by Mura's Collection module (which is the primary module that is used to produce the layout view of a Folder content object). In such cases, modifying the tags and classes for the Collection module that are configurable in the contentRederer.cfc will not suffice.
We could create a modules
directory in our site or global (we typically use global) theme (/themes/[theme name]/modules
), copy the contents of Mura's Collection module there, and then make the necessary changes to layouts and file paths to produce a working module. This can work, but it eliminates the invoking module, "Folder" that can invoke the module and make it configurable for us. If we don't need to allow the content manager(s) to configure this new module, then this will work.
We can do something similar to #3 above but, instead of creating a "modules" directory in our theme, we can create a "content_types" folder and put our modules under that. This makes a little more sense as we are tying this render to a specific content type (subtype) that we created, "News", and much of what we're doing is very view/display oriented (i.e. it is the "view" part of a MVC architecture) and thus it makes sense to treat this as what Mura used to call "Display Objects". We also gain the benefit that we can invoke the modified Collection module that will reside in our content_types folder environment using a method that will allow it to accept parameters that can be controlled/configured by content managers. The remainder of this "Creating Our Own Collection for News/Blogs" section examines this option for implementing a custom view for our "news" Folder content sub-type.
Our News/Blog section on the site is going to consist of a top-level folder, "News", and any number of "Posts" underneath of it. Thus we will need to create a Folder content subtype called "News" and a Page content sub-type called "Post". Because we are going to limit the "News" content subtype from allowing anything other than "Post" to be added, we need to create the Page "Post" content sub-type first. Although there are multiples ways to handle this in Mura (typical), we're going to take the simple approach of using the Mura Admin to add our Class Extensions. So, to create our "Post" Page content subtype we select the "Add A Class Extension option in the Site Settings Menu:
We then see a page that allows us to create the sub-type:
We create the Posts sub-type by selecting the base type of "Page" (since these will be pages within our News folder) and labeling it "Post" for the subtype. Do not leave it set as "Default" or you will not be creating a new subtype - instead you will be changing the default options for the Page content type, which isn't what we want to do. We will leave the remaining options set to their default, which will allow us to add a summary, body, and associated image when we create a new News post.
Click "Add" at the bottom of the page to complete this step.
We're now ready to add our Class Extension for the Folder sub-type that we're calling "News". We do this by, again, selecting the "Add A Class Extension" option in the Site Settings menu:
We then enter the information that we need into the "Add A Class Extension" page that opens just as we did when we created the Posts subtype:
As can be seen in the image above, we select that we are using a Base Type of "Folder" and giving it a Sub-type called "News" (this is so we can render it differently than other folders). As with "Posts", we will leave the default options selected (allowing us to add body content and an image to the News page). However, we will also chose the option to limit the News subtype to only allowing the "Page/Post" content subtype that we created in Step 1 to be added under the new "News" subtype.
Click "Add" at the bottom of the page to complete this step.
In this step we're create the necessary folders in our theme and populate them with some initial files to get us started. This first thing that needs to be done is we need to determine where are theme files are located, which means we need to know what theme we're currently using and if it is a global or site-level theme. The Site Settings menu in the Mura Admin will show your currently selected theme (see below) and the location of the theme files determines if the theme is a site or global theme. If the theme is located under a root folder called "themes", then it is a global theme. If it is located under the root folder "sites", then it is a site-specific theme.
Our example global "IIP" theme has a root directory of /themes/IIP/
Under this root directory we need to create a new folder called content_types
In the new "content_types" folder, we need to add a folder called folder_news
This will associate the code that falls under it with the "News" content subtype that we created. This means that, as soon as we add the "News" subtype to our website content (see example below), the code that we create in these new folders under "folder_news" will automatically control the rendering of the content view.
Finally, we need to populate this new folder with content. We'll start by grabbing the files/folders from Mura's "Folder" module located at /core/modules/v1/folder
Copy the config.xml.cfm, configurator.cfm, index.cfm, and the layout folder (with it's index.cfm file) into your new "folder_news" directory. You will then need to add a "modules" folder (empty for now) as well:
We now need to populate the new "Modules" folder with a copy of Mura's "Collection" module. To do this, the collection folder under /core/modules/v1 and copy it to your modules folder in your folder_news folder:
Now that all of the necessary Mura modules have been copied over to your new modules folder, you you will need to register your modules file folder with Mura so Mura can locate these modules when you references them. To do this, add the following code to you application.cfc in the root of your themes folder (/themes/application.cfc
):
Now that you have copied the Mura "Folder" and "Collection" modules to your subtype folder and your own modules folder and registered the modules folder with Mura, you will need to customize these modules to produce the desired results.
We start by modifying the config.xml.cfm file that is in the root of our new "folder_news" folder. At present it will have the settings for Mura's "Folder" component and we want to change it to be more reflective of how we are now using the "Folder" component for our purpose. This isn't critical, but it is more proper to change the one line in the file to ook something more like this:
These changes identify that our version of the "Folder" modules is called "News" (and will be dislayed as such when doing inline editing) and the only content type allowed underneath of it is the "Post" subtype.
Next we will want to change the index.cfm file in our new "folder_news" director as follows:
Everything within the <silent></silent>
tags should be as-is and unchanged (at least as of Mura 7.1). Our change is within the <cfoutput></cfoutput>
tags. The old dspObject_include() call is commented out (you can delete it - it was commented out here just for sowh of the previous content). We are now using a dspObject() call instead. We're feeding it the "collection" module as the object to be displayed and we are also feeding it the parameters in the objectparams structure created by the configurator.cfm file (fo rbrevity and simplicity, we're skipping how this file works). These objectparams are settings that the content manager can control (such as how many posts to display on the news page and other pagination settings) in the inline editor.
That is it for the index.cfm in our "folder_news" folder. All it does is act as a wrapper to call our version of the "Collection" module, which we will be configuring next.
Customizing the Collection module that we copied into our new modules folder under "folder_news" is accomplished by editing the display files (e.g. "dsp_content_list.cfm") in the folder_news/modules/collection/includes
folder. dsp_content_list.cfm will be our primary concern as, in our example, we're tailoring the dislay of the folder view when using it in the "list" view mode. Mura's folders also support a "grid" display view and, if we were using that, we would need to modify the dsp_meta_list.cfm file. All of these display files are called by the various index.cfm files in the "layouts" folder of the module. So let's focus on editing the dsp_content_list.cfm file to suit our needs.
The current version of the dsp_content_list.cfm file has a lot of code that looks like this:
This may look a little messy, but what is happening here is that the file is referencing the theme's (or site's) contentRenderer.cfm file to determine what tags (e.g. <div></div>
) to wrap content in and class to apply to the HTML elements to make the display compliant with the template that you're using. The idea behind this concept is that the existing Collection module that Mura provides can be configured to work with the styling of your template without having to make a custom copy of the module. However, in our case, we are hard-coding our rendering within our theme and using a custom content subtype to do so, so making a custom copy of the Collection module isn't an issue and it affords us the ability to render other folders in different ways. Thus we can eliminate all of the contentRenderer.cfm style importing code like that shown in the dsp_content_list.cfm snippet above and replace it with the specific HTML tags and classes that our theme calls for.
In addition to changing the styling used, the dsp_content_list.cfm file makes use of a core loop and switch() statement that loops through all of the fields (image, date, title, summary, etc.) selected for the module in the inline editor (if none are selected, it uses a default set of fields as specified in the displaylist parameter set in the root index.cfm of our collection module - folder_news/mosdule/collection/index.cfm). Each field has a corresponding case in the switch() statement that detects if the field has content and, if so, renders that content (with whatever HTML wrapping tags and classes you want to use). The looping will be done based on the order that the fields are specified in and that order is configurable through the inline editor. The problem is that many templates are not designed for the different elements in a particular page view to be in any random order. The HTML typically assumes a specific relationship/sequence to the content (e.g. image, then date, then summary, then "Read More" utton, etc.) and if the content sequence changes, the nesting of the HTML may change wrapping that content will change and, as a result, may produce invalid HTML (a <li></li>
is moved outside of the wrapping <ul></ul>
tags) or the CSS styles may not be applied correctly due to the change in the nesting of various HTML elements. As such, it is recommend that the core loop and switch statement be eliminated. By deleting these, you're left with the conditional <cfif></cfif>
statements that tests to see if there is content for a particular field and, if so, fetches the data and renders it. In these conditional statements, you can easily add a test to see if the field was included in the passed parameters so content is not rendered for any fields that the content manager didn't ask for. Thus:
becomes:
So, obviously a lot of lines were deleted and it cleaned up the readability significantly, so it begs the question as to why/how that is possible. First, we dropped the switch() statement since we didn't need it anymore. Second, we added a wrapped div with a "post-title" class as that is what our template uses (line 1 of the new dsp_content_list.cfm). In line two we are doing a basic conditional check for two things: 1 that the "date" argument was passed as a parameter in the configuration (in other words, the content manager selected "date" as one of the fields in the inline editor) and that there is a valid date entered in the "release date" field of the post. If those conditions are met, then insert the day and month of the release date, wrapped in the tags and classes use by the template (see line 3) and line 5 inserts the title of the post. Title is a required field in Mura and, although the content manager could have elected not to include it in the specified fields, we know that we must display a title for the page to be usable, so there si no conditional wrapper around it.
Here is some more modifications made to our new version of the dsp_content_list.cfm file:
For an explanation of the lines:
Line 1: inserts a <ul> element as used by our template
Line 2: determines if the content manager is asking for the credits (author) to be displayed
Lines 3 - 12: Inserts the credited author of the post as a formatted <li></li> to comply with the stylin gin our template.
Lines 14 - 25: As with the credits, these lines determine if the content manager is asking for the "tags" to be displayed that mayhave been applied to the post. If there are any tags, they will be displayed and formatted in compliance with our template.