Archive for the ‘AJAX / JavaScript’ Category

The other day I discovered that the img tag has an error event. This can be used to automatically load a fall back image when the main image fails for some reason. We encounter this in our dev sites sometimes, because the data is often not 100% correct. For example, our application may ‘think’ there is an image for a product (according to the database), so it writes out an img tag for it. But the image file does not actually exist. So we may end up with a broken image icon, or depending on the browser there may be no indication at all that something is wrong. The tester may get confused as to what’s gone wrong. So I added this code to show an ‘image file does not exist’ image:

<img src="#productImage#" onerror="this.src='/images/icons/imageDoesNotExist.png'" >

That’s it. Be careful that in your error handling code you point to an image file that really exists, otherwise you could go into an infinite loop. One way to be safe regarding that would be to call a function, and remove the onerror attribute so that it only gets fired once.

<script>
function imageError(element) {
	element.onerror='';
	element.src='/images/icons/imageDoesNotExist.png';
	}
</script>

<img src="#productImage#" onerror="imageError(this)">

You could even use this to report a broken image:

<img src="#productImage#" onerror="this.src='logBrokenImage.cfm?image=' + this.src" >

The onerror event is supported in all major browsers. The other tags that support onerror are object, script, and style.

I thought this was some interesting JavaScript that I used recently to detect if form fields were filled in. This was a case where if any of a particular group of fields were filled in, I needed to validate and make sure they were all passed in.

var allValues = $("input.someClass").map(function() { return this.value; }).get().join('');

if (allValues.length) {
  // do validation here to make sure all fields are filled in
  }

Lately I’ve come across some online formatting tools that have been very helpful. I like these because they work regardless of what IDE you use, what operating system, etc. They work from any computer that has internet access. Handy when you are troubleshooting on a remote machine.

Here is one for formatting XML: http://www.shell-tools.net/index.php?op=xml_format

And one for JSON from the same site: http://www.shell-tools.net/index.php?op=json_format

Here is a SQL one that helped me out a lot tonight: http://www.dpriver.com/pp/sqlformat.htm

I fed it a horrible looking, very complex query and it made it easily readable. 🙂

A while back I had the need to do some formatting on a cfgrid. I was using a typical product/price table but the prices are stored with 4 decimals and we needed to display that much resolution. The html version of CFGRID does not directly support this.

Consider this “fake” query set:

<cfset materials=QueryNew("ProductCode,Description,Price","VarChar, VarChar, decimal")>  
</cfset><cfset Temp=QueryAddRow(materials,1)>
</cfset><cfset Temp=QuerySetCell(materials,"ProductCode","MAT1")>  
</cfset><cfset Temp=QuerySetCell(materials,"Description","Copper Bar")>  
</cfset><cfset Temp=QuerySetCell(materials,"Price",3.3400)>  
</cfset><cfset Temp=QueryAddRow(materials)>
</cfset><cfset Temp=QuerySetCell(materials,"ProductCode","MAT2")>  
</cfset><cfset Temp=QuerySetCell(materials,"Description","Feeler Gauge")>  
</cfset><cfset Temp=QuerySetCell(materials,"Price",2.2900)>  
</cfset><cfset Temp=QueryAddRow(materials)>
</cfset><cfset Temp=QuerySetCell(materials,"ProductCode","MAT3")>  
</cfset><cfset Temp=QuerySetCell(materials,"Description","Plastic Retainer")>  
</cfset><cfset Temp=QuerySetCell(materials,"Price",1.3201)>  </cfset>

Note the prices have 4 decimal values, this is how they come to us from the database. If you try to display these with this cfgrid code:

<cfform>
<cfgrid name="testgrid" format="html" query="materials">
</cfgrid>
</cfform>

You will end up with this:

Continue reading ‘Formatting CFGRID with JavaScript’ »

At work we had an issue where we had too many FCKeditor rich text controls on a page at once. We probably had 6 or 7, each on their own tab. For the tabs we are using the <cflayout type="tab"> tag. FireFox would handle the page with no problems, but IE would sometimes fail to load one or more of the rich text controls and would not throw any kind of error about it. The controls simply did not display.

A solution we came up with was to load the rich text controls on demand, when the user needed to use them, rather than load them all when the page first loads. At first I thought we’d have to install a separate, stand alone copy of FCKeditor (now called “CKEditor”) to do this, but we found out this is unnecessary, you use the version that comes with CF to do this.

First, we manually load the FCKeditor JavaScript:
<script type="text/javascript" src="/CFIDE/scripts/ajax/FCKeditor/fckeditor.js"></script>

Then create a function that can change a regular textarea into a rich text controls:

<script type="text/javascript">
function changeToRichText(elementToHide,id,width,height) {
	var oFCKeditor = new FCKeditor(id,width,height,'my_toolbar_set') ;
	oFCKeditor.BasePath = "/CFIDE/scripts/ajax/FCKeditor/";
	oFCKeditor.ReplaceTextarea();
	if (elementToHide) elementToHide.style.display = 'none';
	}
</script>

Then we changed the places on the page that used to have rich text controls to instead use plain textareas. Then placed an link next to each one the user can click on to change the textarea into a rich text. Sometimes they don’t need the functionality of rich text and will just enter plain text into a textarea. Here is the code:

<div id="rootCause_outter" style="text-align: left; width: 100%;">click to use editor<br /></div>
<textarea name="rootCause" style="width:740px; height: 290px;"></textarea><br />

This is used for creating records only, not editing. But it would not be hard to modify this to make it work on an edit page also.

Here is a little ‘Apply To All’ feature I added to a large form we had. There were many rows of data, each with several columns the user needs to fill out. Most of the time the values they were entering in the top row ended up being what they would set all the subsequent rows to. So I wanted to add an easy way they could set all the later rows to the value of the first.

This was actually very easy to do with jQuery. I added a class to each form element, and links on the first row, so my code ended up looking something like this:
Continue reading ‘Making an ‘Apply to all’ with jQuery’ »

The CFWindow tag can be useful to prompt for information on a form. We use this sometimes after a user has clicked the submit button. We do some client side validation in JavaScript, and if certain conditions are met, we use CFWindow to prompt for some additional information.

Its a little tricky though. If you try to use a CFWindow tag inside a CFForm tag you will get a ColdFusion error. If you use it inside a regular form tag you won’t get an error, but it won’t work like you expect. Lets take this code for example:
Continue reading ‘Using CFWindow within a form’ »

A while back I had to implement a captcha on a client’s site. The site owner wanted a simple small captcha (that ruled out reCAPTCHA). We decided to try the new captcha features of ColdFusion8. What you may not realize is that the new captcha feature does not provide the whole captcha system, instead it merely can create captcha images. Its up to you how you implement your captcha system.

Before I get too far just let me state for the record that I dislike captchas and will be happy when they are looked upon like we look at the <blink> tag now. So you don’t need to leave comments telling me how I shouldn’t be using a captcha in the first place. 🙂 The client specifically wanted this feature at this point in time.

I’ve seen some approaches that place the clear text value of the captcha in a hidden field. Then when the form is submitted they compare that value against what the user had typed in. I don’t feel this way is very secure. It will stop simple bots, but you need to guard against more than just that. Sometimes spammers code their bots to work against a specific site. If they find your hidden clear text captcha value, they will easily grab it and use it to submit your form. If this is a simple contact form then you might not have much to worry about, but if its a “send to a friend” feature – watch out, those are high value targets.

Encrypting the hidden value doesn’t help much either. That adds one more step to what the spammer needs to do. They will have to manually read one of your captcha images – then they have the clear text and encrypted values to your captcha system. Now they can just submit that encrypted/plain text pair over and over again to your form.
Continue reading ‘A secure, ajaxy captcha with cfimage’ »

Sometimes when writing JavaScript I need to have something run as soon as the page has finished loading. This is usually done by placing a call to the function in the body’s onload attribute like:

<body onload="myFunc()">

But this is not always possible. For example by the time you get to your logic that decides it necessary to call a function onload, the header may have already been displayed by a cfinclude or by your framework.

You could use JavaScript to set the onload event, like

window.onload = myFunc;

But what if there was already something in the onload attribute of the body tag? The above code will reset whatever was there. But here is a nice snippet of code that will add functions to the onload event. I can’t take credit for it, and I don’t remember exactly where I found it but its been quite useful to me. It works in all the popular browsers.

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

Then you can add as many functions as you want to be called when the page loads. Note you do not use parenthesis when specifying the function names – you aren’t calling then, just referencing them.

addLoadEvent(myFunc);
addLoadEvent(myFunc2);
addLoadEvent(yetAnotherFunction);

Sometimes its helpful to allow users to dynamically add or remove elements from a form. An example might be an image upload page, where you want to allow users to upload a varying number of images. Using JavaScript you can easily place more/less links on the page that show and hide form elements.

This is often done by placing a large number of elements on the form, and setting most of them to be initially hidden with CSS. When the user clicks the “show” link, the next element is unhidden. This is not the best solution however, especially when there is a possibility of having tens of elements – thats a lot of unnecessary html to send down the pipe and render.

Another method is to actually create and destroy elements using the DOM functions. Here’s how I did this recently on a page that need to have any number of form elements.
Continue reading ‘Dynamically adding and removing form elements’ »