Words about stuff, and things related to stuff

Download CFQuery results as Excel with CFspreadsheet

Goal: convert a ColdFusion query object into a spreadsheet, save the spreadsheet to the server, and download it in the browser (without the annoying Excel warning about the wrong file extension):


view plain print about
1<cfparam name="session.searchQuery" default="#queryNew('')#">
2    <cfset fileDir = expandPath('.' & '/searchdata/')>
3    <cfif not directoryExists(fileDir)>
4        <cfdirectory action="create" directory="#fileDir#">
5    </cfif>
7 <cfset filename = dateFormat(now(),'yyyy-mm-dd') & '-' & timeFormat(now(),'hh-mm-ss') & '.xls'>
9    <cfset fileLocation = fileDir & filename>        
10    <cfspreadsheet action="write" filename="#fileLocation#" query="session.searchquery">
12    <cfheader name="Content-Disposition" value="attachment;filename=#filename#">
13    <cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" file="#fileLocation#">

When I used content type of mxexcel, or x-msexcel (or a few others I tried), i would get a warning from excel that the format specified did not match the extension.

This method, cobbled together from a few different forum threads and blog posts, seems to get around those issues.

Add index.cfm as default doucment in .htaccess

Simple tip: Add this line to your .htaccess file

view plain print about
1DirectoryIndex index.cfm

This tells the server to default to /index.cfm inside of any directory.

Why I needed it: I just installed Mura CMS on a Railo/cPanel server where index.cfm is not set as a global default document, and the mura admin kept redirecting me back to the home page. I just added that line to the .htaccess in the web root, and we're good to go.

Bootstrap Screen Size indicator

Working with Bootstrap's default system of 4 screen size ranges, I wanted a way to know, quickly and visually, which size BS is reporting on each page view.

Here's a quick snippet which will create 4 divs, each visible only to the Bootstrap screen size currently in use.

view plain print about
2        <cfloop list="xs,sm,md,lg" index="i">
3            <span class="visible-#i#">#i#</span>
4        </cfloop>
5    </div>

As you resize your browser window, the value changes. Simple.

Dynamic Bootstrap Layout on any markup with make-column and make-row via LESS

If you've spent any time working with bootstrap templates, or the new Bootstrap grid system in BS3, you've probably seen markup with the col-x grid classes, for example a two column layout:

view plain print about
1<div class="container">
2<div class="row">
3<div id="primary" class="col-lg-9 col-md-9 col-sm-8 col-xs-12">
5<div id="sidebar" class="col-lg-3 col-md-3 col-sm-4 col-xs-12">

This will result in a two column layout on large screens, with the proportions shifting for "sm" or small screens, and stacked columns on "xs" or extra-small screens.

While amazingly simple to use once you get the hang of it, maintaining this code is messy and can be both a visual and mathematical challenge when working in a multi-column layout.


Reviving an old BlogCFC blog

If you've been blogging for any length of time in the ColdFusion / CFML community, you're familiar with and probably using BlogCFC, as is this old blog. I've been intending to be more active blogging for a while now, and the recent CF Summit has me all the more eager to get back to writing in this space. 

Lately I've been working a lot with Bootstrap and jQuery, so I decided to give my blog a new skin.


Adobe ColdFusion Summit 2013 #CFsummit2013

Prompted by Ray Camden's post on this week's CF Summit in Las Vegas, I want to CFdump a few thoughts while the mental ink is still wet. There will no doubt be recaps of sessions, slide decks posted, and other technical follow-up (search twitter for #CFsummit2013 to find all sorts of useful links and posts). What I'm left with on the day after, more than anything, is the experience.


Access Restricted message in Mura: a workaround

When creating custom display objects using ajax, the response from any file inside of the site /includes directory will be a simple message, "Access Restricted". This is by design, but it is easy to get around.

The message comes from Mura's default Application.cfc file, which is inside the /includes directory, and contains only the message, and a tag. The purpose of this file is to keep any content stored inside the /includes directory from being delivered directly, i.e. if a user guessed the path to a display object, or some poorly-executed code was to somehow direct a user to a file in /includes.

But, since the Application.cfc has a cascading priority, you can simply place your own Application.cfc file inside the directory where your desired content is stored.


Searching and collecting Mura CMS content by Extended Attribute Value with feed.addParam()

The Extended Attributes functionality in Mura CMS is remarkably powerful, allowing developers to extend their content objects to include custom fields and attributes of almost any type.

However, it isn't always clear how to collect or search on the values of the custom attributes you have added, since Mura's default 'feed' object does not contain the extended attributes you have added.


CFML debugging: cfdump shown to specific site visitor

Here's a quick little snippet to show CFDUMP content only to your IP, without interrupting the flow of traffic for anyone else who may be using the same site:

view plain print about
1<cfif cgi.REMOTE_ADDR is 'My.IP.Address.Here'>
2<cfdump var="#form#">

If you aren't sure of your outward-facing IP address, visit www.whatismyip.com

In this example we are dumping out the #form# scope, but you can dump out whatever you like (by changing the "var" attribute of the cfdump tag) or put any code at all inside the and it will only be executed for views from your specific location.

I wouldn't leave this in a live site but for a quick view of what's going on, without interrupting the experience of others, I find it quite useful.

Importing Events Calendar Data into Mura CMS

I needed a quick 'n dirty way to import an existing spreadsheet of events data into a Mura calendar. After a little trial and error, and much cobbling together of snippets from the Mura forums, here's my result.

Events from XLS data are imported into a table "temp_data" then gathered using the query below. This could be the base for a mura plugin, with an upload option and cfspreadsheet.

Before I ran the import, I created a custom extended attribute set and a page subtype of 'event listing', so we could import this client's custom data attributes.

I also made a parent page called 'events' and got the ID from the mura admin, which is used as the parent ID for all the new entries.

The page subtype is also hard coded below, you'll want to change that to match your own subtype (if not called 'event listing'), and remove the custom attributes stuff, or change those to match your own extended attributes for your events.

This is a crude-but-working example of adding custom attributes, categories, and the main content data all in a single pass, along with the 'start and stop' dates for each event, which I'll use on the front end to group and display the coming events (rather than using those dates to actually show or hide the content directly).

Ideally, the parent ID, site ID and other things would be set by the plugin or site you were working on. But for a one-time import this worked great.

view plain print about
2<cfquery name="dataQ" datasource="#application.configBean.getDatasource()#">
4FROM temp_data
7<!--- loop data, save content for each --->
9    <cfloop query="dataQ">
10        <cfset contentBean = application.contentManager.getBean() />
11        <cfset contentBean.setSiteID('calendarsite')>
12        <cfset contentBean.setType('Page')>
13        <cfset contentBean.setSubtype('Event Listing')>
14        <!--- data --->
15        <cfset contentBean.setBody('#dataQ.eventName#') />
16        <cfset contentBean.setTitle('#dataQ.eventName#') />
17        <!--- to use display per start/stop dates, set to type '2' --->
18        <cfset contentBean.setDisplay(2)>
19        <cfset contentBean.setDisplayStart('#dateFormat(dataQ.datestart,'yyyy-mm-dd')#') />
20        <cfset contentBean.setDisplayStop('#dateFormat(dataQ.dateend,'yyyy-mm-dd')#') />
21        <!--- import categories from our data 'type' (this data only uses one category or 'type' per entry)--->
22        <cfset c = trim(dataQ.type)>
23        <cfset category = application.categorymanager.getBean("category").loadBy(name="#c#",siteid='calendarsite')>
24        <!--- save category if not already available for this site --->
25        <cfif category.getIsNew() eq 1>
26            <cfset category.setName(c)>
27            <cfset category.setSiteID('calendarsite')>
28            <cfset category.save()>    
29        </cfif>
30        <!--- add category ID --->
31        <cfset contentBean.setCategories(category.getCategoryID())>
32        <!--- events custom attributes --->
33        <cfset contentBean.setLocation('#dataQ.location#') />
34        <cfset contentBean.setChannel('#dataQ.channel#') />
35        <cfset contentBean.setLevel('#dataQ.level#') />
36        <!--- events calendar parent id --->
37        <cfset contentBean.setParentID('A48EAF6D-1EC9-549D-5210B43882960200')>
38        <cfset contentBean.save() />
39    </cfloop>
41// #dataQ.recordCount# events imported //

I put that into a blank page called 'import.cfm' right in the root of this site, and pointed my browser at it... done!

Adding Styles to Mura CMS Wysiwyg Editor

In the Mura interface you can select predefined text styles to add to your rich text content, right from the editor toolbar.

To extend the list of available styles is simple

Find the 'styles.js' file, usually at: \[site]\includes\themes\[theme]\js\editor\styles.js **

Then, add your styles, using the same format as those already in the file, for example

view plain print about
1{ name : 'Caption Paragraph', element : 'p', attributes : { 'class' : 'caption-text' } },
2    { name : 'Center Text', element : 'p', attributes : { 'class' : 'center' } },
3    { name : 'Large Intro Paragraph', element : 'p', attributes : { 'class' : 'intro' } },
4    { name : 'Image w/ Spacing', element : 'img', attributes : { 'class' : 'imageborder' } },

In general all you need to do is apply a class to an element. While you could provide other attributes, it is recommended to let your stylesheet handle those wherever possible.

** (Update: I had trouble with the browser caching this file, even on a forced reload. However, I found you can also use "styles.js.cfm" as the file name, and it will be included and updated as expected when making changes and refreshing the page)

As for how those actually look inside the editor window, the editor gets its CSS styles from a file


and, opening that you can see, below the long mura comment, something like

view plain print about
1@import url(../../../../css/reset.css);
2@import url(../../../../css/mura.css);
3@import url(typography.css);

So as long as one of those imported files has a class to match your styles in the editor.js, e.g.

view plain print about
2font-size 11px;
the style will be applied in the editor just as it will on the front end (presuming your display templates are using the same css files).


Recent Comments

Importing Events Calendar Data into Mura CMS
Jon said: Hi Michael, Thanks for this post - similarly looking to import data from excel spreadsheet into mur... [More]

New TinyMCE lets you paste as plain text automatically
PRR said: I am using tinyMCE 4.2.3 and configured as suggested in this post but when i try pasting in editor i... [More]

Searching and collecting Mura CMS content by Extended Attribute Value with feed.addParam()
Armando Faes said: After a few hours of head banging - finally thanks to this - Once more THANK YOU! [More]

CF Gallery Creator & jQuery Slider Gallery !New and Improved!
Jan Willis said: Okay, I realized that you are calling my root as the Site - not the wwwroot. So, I moved the JS, CS... [More]

CF Gallery Creator & jQuery Slider Gallery !New and Improved!
Michael Evangelista said: @Jan, it has been a long time (6+ years) so my memory of the details is vague, but I think the image... [More]