Words about stuff, and things related to stuff

Fast easy 'current link' highlighting with CFML and jQuery

First the snippet (watch for line wrapping when copy/pasting this):

view plain print about
1// current link highlighting
2 $('#topLinksNav a[href="<cfoutput>#listLast(cgi.script_name,'/')#</cfoutput>"]').first().addClass('currentLink').parents('li').addClass('currentLink');
3// make sure top level link for this element is also highlighted
4 $('#topLinksNav ul').has('.currentLink').siblings('a').addClass('currentLink');

This finds any link with an 'href' attribute matching the name of your current page, e.g. "pagename.cfm" , and adds a class of 'currentLink' (note this is in a site where all pages are in the root directory - obviously this needs to be changed to match your site structure, but the same idea applies).

A sample of the ul/li menu structure I'm using is below.

Then you just need a CSS rule for the '.currentLink' class, perhaps

view plain print about
1#topLinksNav li.currentLink{
2 set some background color here
3}
4
5or
6
7#topLinksNav >
li > a.currentLink{
8 set a highlighted text color here only for top level links
9}

Here's the sample menu structure for the syntax above something like

view plain print about
1<ul id="topLinksNav">
2<li>
3<a href="index.cfm">Top Level Page</a>
4 <ul>
5 <li>
6 <a href="subpage1.cfm">Secondary Menu Page</a>
7 </li>
8 <li>
9 <a href="subpage2.cfm">Secondary Menu Page</a>
10 </li>
11 </ul>
12 </li>
13<li>
14<a href="contact.cfm">Top Level Page</a>
15 <ul>
16 <li>
17 <a href="subpage1.cfm">Secondary Menu Page</a>
18 </li>
19 <li>
20 <a href="subpage2.cfm">Secondary Menu Page</a>
21 </li>
22 </ul>
23 </li>
24</ul>

Start and stop ColdFusion localhost with .bat files (Windows)

Here's a simple trick that saves a few clicks. If you are running a ColdFusion local server on a windows PC, you can start and stop the CF service with a simple bat file.

Make a new text file on your hard drive somewhere (i keep mine right on the desktop), and name it "cfstart.bat" - in your text editor of choice, enter this one line and save the file:

    NET START "coldfusion 9 application server"

(with the quotes, just like that)

You can make another called "cfstop.bat" and, you guessed it, 

    NET STOP "coldfusion 9 application server"

To use the files, on my Windows 7 PC, I just right click and select "Run as administrator", and the service stops or starts up right away. Now instead of running all the time, consuming memory, CF only runs on my local machine when i need it. 

Note: you may also want to remove the ColdFusion service from the list of items that run on startup - use start > run > mscofig to see the list.

 

 

Mura CMS / CKeditor paste as plain text by default

Any developer who uses a CMS with a wysiwyg text editor knows the frustrations of clients pasting content from MS Word and other word processing programs directly into the editor, complete with unwanted styles, and even markup elements, causing all sorts of problems on our otherwise perfectly-formatted pages.

Mura CMS uses the ubiquitous CKeditor (formerly FCK) with a number of features enabled by default, including a "Paste as Plain Text" button. If clients remembered to use this, we would be all set. But, they don't.

Fortunately, there's an easy one-line fix.
Just open up [siteid]\includes\themes\[theme]\js\editor\styles.js

and paste in this line

CKEDITOR.config.forcePasteAsPlainText = true;

That's it. All pasting of content should now be clean, with extra styles and markup removed, just as if you had clicked "paste as plain text" in the editor toolbar. 

Adding Navigation Items to MuraCMS Admin

Here's a quick and easy enhancement you can make to the MuraCMS admin, adding links in the top-level navigation for quick and easy shortcuts to commonly-used sections of Site Manager.

Like so many things in Mura, the hooks already exist for this functionality, you just need to know what to put where. In this case, it is quite simple.

Continued...

Finding Available Mura CMS Content with getAllValues()

One of the first things I wanted to know as I started working with Mura CMS templates, is how I can dump out all the available variables.

I'm used to the versatility of CFML's CFdump tag, outputting the contents of any query or other CF object to the page for easy reading and reference as I wire up the css and html to display the dynamic content. In Mura, where everything is returned by a 'bean' via specifically named CF functions, cfdump doesn't always have the expected results.

For example, in a content-driven page in mura, dumping out #$.content()# will show the methods available, but not the actual values they'll return for the page you're working on.

In comes another Mura one-liner "getAllValues()". This can be attached to almost any Mura root-level object, to show all the values available, just as if you were dumping out the results of a single cfquery record, struct or nested array.

So, to get all the available goodies for a standard page or content-based item, simply add the getAllValues() function at the end of your cfdump:

view plain print about
1<cfdump var="#$.content().getAllValues()#">

This also works for other Mura beans, such as a Mura feed:

view plain print about
1<cfdump var="#variables.feedBean.getAllValues()#">

or any record being parsed by Mura's "iterator":

view plain print about
1<cfdump var="#arguments.item.getAllValues()#">

or even the content of another page, by ID:

view plain print about
1<cfdump var="#application.contentManager.getActiveContent('[content id]', '[site id]').getAllValues()#">

or by filename (the filename is the name of the content-node, same as seen in url):

view plain print about
1<cfdump var="#application.contentManager.getActiveContentByFilename('[filename]', '[siteid]').getAllValues()#">

As I understand it, most of these values are directly available via the CF request scope, but dumping out #request# in mura is huge, and takes a while to dig through. GetAllValues() is the one you want.

The Mura Docs list a number of methods for getting content via the Mura API. I believe the getAllValues() method can be used with all of the 'read' functions.

Persist form values on reload w/ jQuery & ColdFusion

A designer friend presented me with a somewhatlong and complicated HTML form. It is a survey/contest entry for employees of a specific industry, with dozens of fields which include regular text inputs, text areas, and radio buttons.

My task is to create a routine to submit this form via e-mail and store the contents in the database. ColdFusion makes that easy with the built-in #form# scope. And for validation, I simply made his HTML < form > into a <cfform>, and all of the <input> and < textarea > elements into <cfinput> and <cftextarea>, adding 'required="true"' and a validation rule and/or message for each. Whipping up a quick server-side validation for the required fields was also a snap with CF.

Then it occurred to me - if there is in fact some error with the user submission, we will return the user to the form showing an error message at the top of the page.

However, unless we somehow persist the values that were entered, the form will be blank, and the user will no doubt be a little frustrated. This is a long form!

one method would be to create <cfparam> values for each element in the form, and then give each input the a value like value='#form.thisFieldName#" - that's common practice, and works great, but I don't want to do the tedious work. Also, I will be passing this form back to the designer, and don't want him to have to create the default value if he decides to change the names of any inputs, or at other input to the form.

So, I came up with this.

Assuming you already have jQuery in your page, this little block of code will loop through all of the posted values in the ColdFusion form scope, then, using jQuery, will assign the given value to any form element with a matching "name" attribute, allowing us to easily re-populate all the form fields in the page, in one fell swoop with javascript.

Since i only had input / textarea / select / radio button inputs, this just handles those types, but could easily be ammended to include checkboxes and more.

<!--- if form scope exists --->
<cfif isDefined('form.fieldnames')>
    <cfsavecontent variable="hcode">
    <script type="text/javascript">
    $(document).ready(function(){
    <cfloop list="#form.fieldNames#" index="ff">
    <cfset rawVal = form[ff]>
    <cfset ffVal = jsStringFormat(form[ff])>
    <cfoutput>
    $('input[type="text"][name="#lcase(ff)#"]').val('#ffval#');
    $('select[name="#lcase(ff)#"]').val('#ffval#');
    $('textarea[name="#lcase(ff)#"]').text('#ffval#');
    $('input[type="radio"][name="#lcase(ff)#"][value="#rawval#"]').attr('checked','checked');
    </cfoutput>
    </cfloop>
    //end jQuery
    });
    </script>
    </cfsavecontent>
<cfhtmlhead text="#hcode#">
</cfif>


Yes, this makes a big long looped jQuery script in the head of the user's page. But in this instance, it is working perfectly, with no noticeable slowing of page load, or other drawbacks that i can see.

Filtering content in Mura CMS

In my ongoing adventures w/ Mura ColdFusion CMS , I have been setting up a calendar of events for a local tourism website.  A 'calendar' is a built in content type in Mura, with many options for showing and filtering the content.

For this calendar, we want our events to show up as soon as they are entered, remain on the site until 2 days after the event date has passed , and then be removed from view. So, we need a filter that compares the current date to a date two days in the future - easy with ColdFusion's dateAdd() function, but the trick was getting that function into the Mura "filter" settings.

Here's how I set it up:

1) create the calendar

- in site manager, click the "+" next to home page (or wherever) and choose 'add calendar'

- give your calendar a title, and click 'publish' (other details can be added as desired)

2) create the "content collection" to show the calendar's info

- click 'content collections' , then select 'add new Local Index'

- give it a name

-  next to the heading "Choose content from section:", click the (less than obvious) "[select section]" link , and type in part of the name of your calendar to search for that content**

- in the search results, click the "+" on the far right to add your calendar, making sure "include features only" is set to "no"

** this has been one of the key Mura admin concepts I've had to adjust to - this type of content search is used a lot in the admin, rather than dropdowns or other standard ways of presenting existing selections. It works well once you get used to it.

3) set up the filtering

- on the "advanced filters" tab, add two filters, with the following selections:

i) Start Date / Time : Greater Than or Equal To : [mura]dateAdd('d',2,now())[/mura]

ii) Or : Stop Date / Time : Greater Than or Equal To : [mura]dateAdd('d',2,now())[/mura]

The key was the use of The Mura Tag , which allows you to use any standard CF functions in place of a static value ( documentation here ) - in this usage, we are comparing today's date to a date 2 days from now (if you wanted to be more specific you could add 48 hours instead of 2 days ... or anything you like )

As I am quickly learning, Mura contains a number of filtering options for its content collections. I'm interested in seeing your examples if you've got 'em!

 

How to set up local vs. production settings for Mura CMS

In an effort to become acquainted with Mura CMS, I have been spending some time looking at the overall way the application is structured - what is included into what, where settings are stored or specified, and what the options are for modifying the default way things are done, in order to retain some of the in-house workflow concepts I have developed over the years.

One of the main aspects of my production workflow involves the easy use of both a local and live server, running from the same database. Generally, when starting a new ColdFusion project, I like to:

- Set up a local directory for the project, where i can work in the browser via a local host url
(something like http://172.16.17.5:8500/SiteName/wwwroot/  or http://localhost:8500/sitename/wwwroot )

- Set up a database on my live production server at www.GoWestHosting.com

- Create a DSN on the live server, pointing to the database

- Create a DSN on my local CF server, pointing to the same remote database

Now I can work locally and view my changes instantly without the need for FTP.

Or, as needed, I can push changes to the live site with a few clicks, and view the changes there as well (such as posting work for clients, or working with routines that require server-specific settings, launched from the site's "real" location)

My application.cfc contains both sets of DSN info, and uses a switch, based on the current cgi. server variables , to determine which DSN to run from, along with other server specific settings (such as google map key). So, wherever the site is viewed, my application 'knows' which content paths and other settings to use for each page request or query.

(So... what about MuraCMS?)

One of the first things I noticed when installing Mura locally was the way that it cached the local directory structure. So if my Mura site was installed in a subdirectory of the local site, e.g. http://localhost:8500/sitename/wwwroot/test/ , Mura would store the setting "/sitename/wwwroot/test" automatically, and prepend this path to all required assets. Wonderful. Superb. But...

Then I pushed the Mura files to the live server, uploading the works via FTP. And found I had a problem. That path was still being prepended to all assets... but didn't exist.
On the live server i was simply working from http://sitename.com/test/ , so everything was instantly broken - images, javascript, css.

Unlike my own usual practices, where all primary templates or pages live in the site root,  Mura is designed to use 'root relative' paths, rather than location relative, which makes sense if content will be served from different directory levels.

So instead of simply looking in ../css/ for a css file, it wants to use the path /sitename/wwwroot/test/css

(So... how did I fix this? Get to the point already... )

Half of any solution is identifying the problem. In this case, I needed to find out "how to use two different sets of configuration variables" , and set out to find the answer.

On setup, mura creates and populates a file called 'settings.ini.cfm', which is a simple text file with variables and values stored one per line. And inside, I could see the paths were being stored as text strings. Cool. Now I know where it lives... but how to change it on the fly, and keep two different versions?

I asked my question to the very friendly, patient guys on the Mura Show , but must not have asked correctly, or clearly enough. I came away thinking the solution was to set up a domain 'alias' and somehow map a direct IP to my subfolder locally , which doesn't work since you can't put paths in the Windows hosts file... and i got into a right frustrating mess.

Deciding to take another crack at it with fresh morning-coffee eyes, I got smart and did a bit of googling. And I found this, the settings.ini reference from the Mura site: http://docs.getmura.com/index.cfm/installation-set-up/settingsinicfm-reference/

and... AHA! a classic RTFM moment.

(finally... the fix !)

wouldn't you know it, the very first line of the settings.ini.cfm file is for the "mode", (which i completely overlooked before, and the Mura team must not have thought of in reference to my seemingly vague questions. )

The default mode is 'production' and beyond the first few lines, all settings in the file are under a heading of [production]. The light started coming on right about now... they really did think of everything!

So, all I had to do was create another grouping, and change that master 'mode' setting. I simply duplicated all the lines below [production], added a new heading of [localdev] , and changed the settings to match those of my local server. (I also changed 'production' paths to match the settings of my live production server with the simpler root directory structure)

Just a few more steps - upload the changed file to the live server, and click 'reload application' in the Mura admin.  Then, change my local copy of the settings.ini.cfm file to 'mode=localdev' , and click 'reload application' in my local admin as well.

This caused the local settings to be loaded for the local site, and the production settings to be loaded for the production site ... and i am back in business, working in both locations with ease!

Bearing in mind that any uploaded images will need to be manually copied with FTP, and some other things might need a little hand-holding, I am very pleased to be back in business with the freedom to work the way I am used to, with live, functioning copies of the complete site on both my local server and the live location.

The only caveat at this stage - I'll have to be careful not to upload the settings.ini.cfm file, since I still don't have an 'automatic' switch for which group of settings to use. But as long as my production version of the file says "mode=production" and my local file says "mode=localdev" , I should be good to go.

 

HTML Formatter ColdFusion-friendly code cleanup tool

No matter how clean your code, there's something to be said for a fast, clean pre-launch cleanup with a reliable code formatter . My favorite by far is the HTML Formatter from LogicHammer.com:  http://www.logichammer.com/html-formatter/

Complete with a full set of ColdFusion-friendly options, this simple tool makes cleaning your code a snap. I use it as I'm working, to clean up the work-so-far at any point, and before final launch to make sure the production code will be as easy as possible to maintain and revisit later on. It is a standalone executable, which means there's no installation, and you can put in anywhere you like on your hard drive.

I simply create a taskbar shortcut on my Windows PC and drag the files I want to clean directly from the 'project' view in Eclipse onto the icon - couldn't be faster, simpler or easier. I prefer to have my original files altered, with the originals automatically put in a specified backup location - you can also assign the option to leave the original alone and create a cleaned-up copy.

Among other fav features, HTML Formatter ships with a simple text-based config file which makes it incredibly easy to specify tags to ignore or to indent, and file extensions to be formatted or skipped ( you can run the formatting on specific files, or an entire directory).

For only $14.99 you get all the features and 2 years of updates (there is also an 8.99 version with a basic feature set). The program's developer has answered every question I ask directly and has been very helpful with customizations, even building in some features I requested a while back (for the record - I'm not affiliated with logichammer in any way, just very pleased with this slick little tool).

How to find lowercase (no caps) values in mySQL (and Capitalize them with ColdFusion)

I have a request from a client to help clean up some customer-entered data in a mySQL database, specifically, we need to capitalize all of the values in a column called 'user_city'

For the actual capitalization, I am using the very handy CapFirstTitle() function from CFlib : http://www.cflib.org/index.cfm?event=page.udfbyid&udfid=116

But first, I need to find all of the entries that are not already capitalized. This dataset has tens of thousands of records , including some with a blank value in the 'city' field - no need to loop all of that just to fix our caps!

So, here's the SQL query code to find all of the records with no capital letters at all, by comparing to a lower() all lowercase version of the same value:

view plain print about
1SELECT user_city, ID
2FROM site_users
3WHERE user_city = lower(user_city)
4AND NOT user_city = ''
5ORDER by user_city

And here is the full CFoutput / CFquery code for the loop and update with Coldfusion, and the CapFirstTitle() function in the head of the page:

view plain print about
1<cfoutput query="myQueryAbove">
2    <cfquery datasource="#application.dsn#">
3    UPDATE site_users
4    SET user_city = '#capFirstTitle(myQueryAbove.user_city)#'
5    WHERE ID = #myQueryAbove.ID#
6    </cfquery>
7</cfoutput>

for other columns you could use OR in the first query and an additional statement in the second, or just change the queries, run the page again, or even, make the column name a variable and just change it once in the head of the page... easy.

Show any Twitter Feed on your site with ColdFusion and CFFEED

This is so simple, I'll let the comments do the 'splainin:

view plain print about
1<!---
2start CF Twitter Feed
3--->

4
5<!--- SET THE URL: add your username instead of mine --->
6
7<cfset feedurl="http://search.twitter.com/search.atom?q=from%3Agowestweb" />
8
9<!--- CFFEED does all the work --->
10
11<cffeed
12 source="#feedurl#"
13 properties="feedmeta"
14 query="feeditems"
15 overwrite="true" />

16
17<!--- CFOUTPUT shows the feed like a query --->
18
19<ul class="tweet">
20<!--- change maxrows to suit your layout --->
21<cfoutput query="feeditems" maxrows="3">
22<li>#content#</li>
23</cfoutput>
24</ul>
25
26<!---
27end CF Twitter Feed
28--->

29
30<!---
31NOTE: in addition to #content#, you can show date and other columns related to each feed item.
32Use <cfdump var="#feeditems#"> to see all the available columns in the query
33--->

...Show Newer Read More...

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]

_UNKNOWNTRANSLATION_