Archive for October, 2010

Integer and String typing in Coldfusion

Monday, October 25th, 2010

Coldfusion is a loosely typed language meaning that, unlike many other languages, data types do not have to be typed explicitly. In Coldfusion the variable takes the type of the value that is assigned to it. For example, if a variable is created and set to structNew() that variable is typed as a struct since it has been clearly stated that the variable is to be a new struct.

While you can’t just go around concatenating and performing arithmetic on anything, like concatenating a string to a complex object or adding a number to a letter, Coldfusion will perform data typing changes on the fly for strings and numbers based upon the operation. Let’s take the following for example.

(more…)

Quick XML formatting with CF Builder

Sunday, October 17th, 2010

Pretty much every server-side language I’ve worked with has written XML to a file as compressed text. This is of course intentional in that any whitespace is indeed space and through the eyes of a program doesn’t matter. However, through the eyes of a human it does matter because large chunks of compressed xml is rather unreadable.

In the past I’ve always used Notepad++ to quickly format XML. However, this has always required opening the xml file in Notepad++ and formatting there. However, I just found in CF Builder the same feature. To use this you can either right-click anywhere in the editor containing the xml to be formatted and choose ‘Format’, or you can use the keyboard default shortcut “Shift-Command-F” on a mac or “Shift-Ctrl-F” on windows.

While I would recommend maintaining its compressed format in the file, this is a great feature for quickly making compressed XML readable.

Suppressing whitespace and saving content with cfscript

Monday, October 11th, 2010

I was writing a while back some script based components. In one function I needed to save some HTML content into a variable and I needed to make sure that the whitespace was controlled. In tag-based CF it would look something like the following.

<cfprocessingdirective suppresswhitespace="true">
	<cfoutput>
		<cfsavecontent variable="loc_data">
			<div>
				<p>
					This is some HTML content!
				</p>
			</div>
		</cfsavecontent>
	</cfoutput>
</cfprocessingdirective>

When I went to look up the documentation on how to write the equivalent of this in script the relevant bits and pieces were few and far between. So I ended up just trying some different ways of writing it that made sense and sure enough the processingdirective tag does have a script equivalent. The script version of this will look like the following. It’s actually much simpler and cleaner if you ask my opinion.

processingdirective suppresswhitespace=true
{
	savecontent variable="this_data"
	{
		writeOutput('<div><p>This is some HTML content!</p></div>');
	}
}

So in the end pretty simple. The documentation just isn’t very user friendly on the cfscript end. Hopefully this will get better as it is a cleaner way to write components.

Resizing text with jQuery and window resize

Friday, October 8th, 2010

The other night my wife brought up the question of being able to resize font dynamically as a user resizes their browser window. Knowing that javascript can do most anything and jQuery makes doing most anything with javascript quick, I immediately responsed – yes, of course. At the time I had an idea of how it could be accomplished, and had never attempted it nor thought about it. So I wrote up a quick example of one way to pull this off.

**A programmers note to designers: This can probably be done with CSS3, and maybe previous versions, and if you can do it with CSS I would definitely recommend it as it will certainly be a safer route and most likely a lighter route as well. I’m not known for my skill with CSS however.

Before looking at any code I’ll give a quick explanation of what it is I’m doing with the code. First, I have a fixed-width div containing a ‘p’ tag with some text. That’s it for the HTML.

The javascript assigns immediately a font-size of 30px to the text and gets the width and height of the window in its original state of page load. Also before any processing is done a ‘ratio of change’ is set. This is the number of pixel change to every one change in pixel font size. So a 10:1 ratio means that the font will decrease one pixel for every ten pixels that the window width decreases from its original size. It also works in the opposite direction for every ten pixels that the screen gets bigger than the original size the font will increase by a single pixel. Of course ten pixels means that in no time the font will be either huge or tiny. A more realistic number is something like 50 or 100. Simply put, the smaller the number the faster the font will change, and the bigger the number the slower the font will change on window resize.

First let’s look at the little bit of HTML.

<body>
	<div id="container">
		<p>
			This is some sample text that I have written for the purpose of watching it resize as I resize my window on my screen. Enjoy!
		</p>
	</div>
</body>

Now let’s take a look at the javascript.

$(document).ready(function()
{
	//set the originals
	var originalWinWidth = $(window).width();

	//set the original font size
	var originalFontSize = 30;

	//set the ratio of change for each size change
	var ratioOfChange = 50;

	//set the font size using jquery
	$("#container").css("font-size", originalFontSize);

	$(window).resize(function()
	{
		//get the width and height as the window resizes
		var winWidth = $(window).width();

		//get the difference in width
		var widthDiff = winWidth - originalWinWidth;

		//check if the window is larger or smaller than the original
		if(widthDiff > 0)
		{
			//our window is larger than the original so increase font size
			var pixelsToIncrease = Math.round(widthDiff / ratioOfChange);

			//calculate the new font size
			var newFontSize = originalFontSize + pixelsToIncrease;

			//set new font size
			$("#container").css("font-size", newFontSize);
		}
		else
		{
			//our window is smaller than the original so decrease font size
			var pixelsToDecrease = Math.round(Math.abs(widthDiff) / ratioOfChange);

			//calculate the new font size
			var newFontSize = originalFontSize - pixelsToDecrease;

			//set the new font size
			$("#container").css("font-size", newFontSize);
		}
	})
});

First of all, this is around 50 lines of code, about half of which are comments. I say this every time, but seriously hats freakin’ off for jQuery. It really is amazing how much can be accomplished with such a few pleasant lines of code. On that note I do realize that there are better ways of writing this code, and if you so choose to use it for any type of production purpose I would recommend refactoring it into something a little more encapsulated and flexible with what it resizes.

Anyways, I digress. What are we doing here. Initially we need to set up a simple listener that watches for when the user decides to resize the window. When the window changes size we need to do two things initially – get the current window size, and then compare that to the original window size. A simple comparison of that difference to zero reveals whether the window is getting bigger or smaller.

The math behind determining the amount of change for the font size is pretty elementary. We of course want to make sure we come out with a positive integer whether the window is getting bigger or smaller. To make sure we get an integer we can use javascripts Math class function round(). If the window is getting smaller we will have a negative number representing the difference. Here javascripts Math class function abs(), for ‘absolute’ can be used to make that number a positive integer. Having these tools in hand, we simply need to divide the window difference by the ratio of change. The result will be the number of pixels that the font will need to change by. If the window is getting bigger we will using jQuery’s css() function to reset the new font size to the original plus the number returned. If the window is getting smaller we, of course, subtract it from the original font size.

While I’m not sure why this would be used outside of dynamically adapting a page between window sizes for different devices, I can see a lot of ways that this can be expanded upon and made significantly better than what I have presented here. But again, I was very pleased with just how simple this was to pull off.

Finally broke down and purchased Coldfusion Builder

Monday, October 4th, 2010

It’s almost embarrassing to even admit, but I just now purchased Coldfusion Builder (which also comes with Flash Builder to make a sweet deal even sweeter). I worked in Dreamweaver for some time originally and then made the move to the standard Eclipse with the cfEclipse workbench. I used this for some time and continue to use it at the workplace. When the beta release of CF Builder came out I anxiously adopted it, and even with all of its preliminary bugs I could see it was going to become by far the best way to develop a Coldfusion site. Once the product was released, I of course absorbed my 60 day trial. But for some reason after the trial expired I numbly began using Eclipse again.

After installing a javascript editor plugin the other day and watching my SQLExplorer plugin come crashing down (and eventually Eclipse itself) I decided that maybe it was time I get with the game. And here I am, enjoying and fluently writing cfscript the way it was meant to be written – with ease.

Javascript debugging with MS Visual Web Developer 2010 Express

Monday, October 4th, 2010

A colleague of mine let me in on a pretty cool tip today. I think we’ve all been in a position where we needed to debug javascript for IE, but of course IE 6 and 7 do not have built in debuggers. As it turns out the Microsoft Visual Web Developer IDE has a built in javascript debugger for IE7 and 8 (unfortunately I couldn’t get the errors in IE6 to translate to the debugger). To get the debugger you will first need to download the free Visual Web Developer 2010 Express from here.

Once you have the IDE, open the version of IE you will be debugging in and choose Tools > Internet Options. Click the Advanced tab. Make sure that debugging in (Internet Explorer) is unchecked and the Always display errors is checked. Also make sure that you set it as your default browser.

Now open the VWD and create a new empty asp.net website. You don’t need to actually create any files since this site will only be used for debugging. So click the green arrow in the top toolbar to begin debugging. Confirm the prompt and it should open IE and throw a 404 error because you have no files for your empty website. But now you can simply navigate to the site you wish to debug. If any javascript errors are thrown on the page they will translate into the VWD debugger. Here you can now add break points and watches. Refresh the page and begin stepping through the script.

duplicateDirectory() UDF

Saturday, October 2nd, 2010

For a project I’m working on I needed to grab an existing directory and duplicate it to another location. My quick search through the Coldfusion docs didn’t return any methods that would allow me to do this. As a result, I built one that is fairly simple. It accepts two arguments: 1. directory to copy, and 2. the directory to copy to. Let’s first take a look at the function itself.

<cffunction name="duplicateDirectory" displayname="Duplicate Directory" hint="Duplicates the specifed directory in another specified directory." access="private" output="false" returntype="void">

    <cfargument name="directoryToCopy" displayname="Directory To Copy" hint="The full path to the directory that is to be duplicated." type="string" required="true" />
    <cfargument name="directoryToCopyTo" displayname="Directory To Copy To" hint="The full path to the directory that the duplicated directory is to be copied to." type="string" required="true" />

    <cfset var loc_dirList = "" />
    <cfset var loc_rootDir = listLast(arguments.directoryToCopy, "/") />
    <cfset var loc_thisRootDir = arguments.directoryToCopyTo & "/" & loc_rootDir />
    <cfset var loc_thisDirName = "" />
    <cfset var loc_thisDirPath = "" />
    <cfset var loc_thisFileName = "" />
    <cfset var loc_thisFilePath = "" />
    <cfset var loc_createThisDir = "" />
    <cfset var loc_createThisFile = "" />
    <cfset var loc_i = 0 />
    <cfset var loc_dirExt = "" />
    <cfset var loc_record = false />

    <!--- create this root directory --->
    <cfdirectory action="create" directory="#loc_thisRootDir#" />

    <!--- get a list of everything in the directory to copy.  **IMPORTANT: sort by 'type' and then 'directory' to ensure that all directories in the root are created before any directories
    insde of those directories.  After all directories have been created then the files can be copied over. --->
    <cfdirectory action="list" name="loc_dirList" recurse="true" directory="#arguments.directoryToCopy#" sort="type, directory" />

    <!--- loop over all directories and files --->
    <cfloop query="loc_dirList">
        <!--- determine if a file or directory --->
        <cfif type eq "dir">
            <!--- set the name and path --->
            <cfset loc_thisDirName = name />
            <cfset loc_thisDirPath = directory />

            <cfset loc_dirExt = "" />

            <cfset loc_record = false />

            <!--- get the dir structure after the root dir --->
            <cfloop list="#loc_thisDirPath#" delimiters="/" index="loc_i">
                <cfif loc_i eq loc_rootDir>
                    <cfset loc_record = true />
                </cfif>

                <cfif loc_record eq true>
                    <cfset loc_dirExt = loc_dirExt & "/" & loc_i />
                </cfif>
            </cfloop>

            <!--- set the path to create the directory --->
            <cfset loc_createThisDir = arguments.directoryToCopyTo & loc_dirExt & "/" & loc_thisDirName />

            <!--- create the directory --->
            <cfdirectory action="create" directory="#loc_createThisDir#" />
        <cfelse>
            <cfset loc_thisFileName = name />
            <cfset loc_thisFilePath = directory />

            <cfset loc_dirExt = "" />

            <cfset loc_record = false />

            <!--- get the dir structure after the root dir --->
            <cfloop list="#loc_thisFilePath#" delimiters="/" index="loc_i">
                <cfif loc_i eq loc_rootDir>
                    <cfset loc_record = true />
                </cfif>

                <cfif loc_record eq true>
                    <cfset loc_dirExt = loc_dirExt & "/" & loc_i />
                </cfif>
            </cfloop>

            <!--- set the desination path for the file to be copied to --->
            <cfset loc_createThisFile = arguments.directoryToCopyTo & loc_dirExt />

            <!--- copy the file to its project destination --->
            <cffile action="copy" source="#loc_thisFilePath#/#loc_thisFileName#" destination="#loc_createThisFile#" />
        </cfif>
    </cfloop>

</cffunction>

So an example of calling this function would look something like:

<cfset variables.existingDirPath = expandPath("./") & "/templates/mytemplate" />
<cfset variables.copyDirToPath = expandPath("./") & "/duplicates" />

<cfset duplicateDirectory(variables.existingDirPath, variables.copyDirToPath) />

Also, in case you prefer using script, the same function can a be written as the following. Take your pick. **do note that most likely the cfscript version will not work on CF7MX or CF8. I believe the tag based one should work on all three versions.

component
{
	public void function duplicateDirectory(required string directoryToCopy, required string directoryToCopyTo)
	{
		var loc_dirList = "";
		var loc_rootDir = listLast(arguments.directoryToCopy, "/");
		var loc_thisRootDir = arguments.directoryToCopyTo & "/" & loc_rootDir;
		var loc_thisDirName = "";
		var loc_thisDirPath = "";
		var loc_thisFileName = "";
		var loc_thisFilePath = "";
		var loc_createThisDir = "";
		var loc_createThisFile = "";
		var loc_i = 0;
		var loc_j = 0;
		var loc_dirExt = "";
		var loc_record = false;
		var loc_fileToCopy = "";

		//check if the directory exists
		if(directoryExists(loc_thisRootDir))
		{
			//delete the directory
			directoryDelete(loc_thisRootDir, true);
		}

		//create this root directory
		directoryCreate(loc_thisRootDir);

		//get a list of all directories/files in the root directory being copied
		loc_dirList = directoryList(arguments.directoryToCopy, true, "query", "", "type, directory");

		//loop over the query of directories and files
		for(loc_i = 1; loc_i <= loc_dirList.recordcount; loc_i++)
		{
			//check if a directory or a file
			if(loc_dirList["type"][loc_i] == "dir")
			{
				loc_thisDirName = loc_dirList["name"][loc_i];
				loc_thisDirPath = loc_dirList["directory"][loc_i];

				loc_dirExt = "";
				loc_record = false;

				//loop over the directory structure and get anything after the root
				for(loc_j = 1; loc_j <= listLen(loc_thisDirPath, "/"); loc_j++)
				{
					//if the root directory has been reached
					if(listGetAt(loc_thisDirPath, loc_j, "/") == loc_rootDir)
					{
						loc_record = true;
					}

					if(loc_record == true)
					{
						loc_dirExt = loc_dirExt & "/" & listGetAt(loc_thisDirPath, loc_j, "/");
					}
				}

				//set path of the directory to create
				loc_createThisDir = arguments.directoryToCopyTo & loc_dirExt & "/" & loc_thisDirName;

				//create the directory
				directoryCreate(loc_createThisDir);
			}
			else
			{
				loc_thisFileName = loc_dirList["name"][loc_i];
				loc_thisFilePath = loc_dirList["directory"][loc_i];

				loc_dirExt = "";
				loc_record = false;

				for(loc_j = 1; loc_j <= listLen(loc_thisFilePath, "/"); loc_j++)
				{
					if(listGetAt(loc_thisFilePath, loc_j, "/") == loc_rootDir)
					{
						loc_record = true;
					}

					if(loc_record == true)
					{
						loc_dirExt = loc_dirExt & "/" & listGetAt(loc_thisFilePath, loc_j, "/");
					}
				}

				//create path of the file to create
				loc_createThisFile = arguments.directoryToCopyTo & loc_dirExt;

				//set the location of the file to be copied
				loc_fileToCopy = loc_thisFilePath & "/" & loc_thisFileName;

				//create copy the file to its new destination
				fileCopy(loc_fileToCopy, loc_createThisFile);
			}
		}
	}
}

I haven’t had a chance to test this on anything outside of my current project. So if anyone runs into any troubles using please post and I can update appropriately.

So feel free to use and adapt this as you please!