jquery.validate Range Method Patch

If you use the range attribute inline to validate against using the jquery.validate plugin 1.8.1, your validation will probably always fail and receive the message “Please enter a value between NaN and {1}.” or “Please enter a value between {0} and NaN.”.

This drove me nuts for almost a whole day looking for a fix. I finally got smart and looked at the current issues in the Github project. “markusblair” submitted a patch, but that was also incorrect.

To correct this issue, modify the jquery.validate.js file on line 852:

		$.each(['rangelength', 'range'], function() {
			if (rules[this]) {
				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
			}
		});

and replace it with:

		// Patch by Chris Tierney (CF Webtools 7/13/2011)
		// Issue logged at https://github.com/jzaefferer/jquery-validation/issues/112
		$.each(['rangelength', 'range'], function() {
			if (typeof rules[this] == 'string') {
				rules[this] = rules[this].split(",");
			}
			if (rules[this]) {
				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
			}
		});

Be sure to update your minified version as well and this should solve the range and potentially a similar rangelength method issue immediately.

jquery.validate Better Date Method

The jquery.validate plugin currently has the validation method “date” which will correctly validate the format “xx/xx/xxxx”. However you can enter a date such as “40/01/2011” and it will pass. Obviously there is no month 40 or even day 40.

Borrowing from the “dateITA” validation method in the additional-methods.js I created a “dateUS” validation method that will detect for not only a correctly US formatted date but a valid date as well using the “mm/dd/yyyy” format.

Add this to your additional-methods.js file or load in another methods file (ex:my-methods.js):

/**
  * Return true, if the value is a valid date, also making this formal check mm/dd/yyyy.
  *
  * @example jQuery.validator.methods.date("01/01/1900")
  * @result true
  *
  * @example jQuery.validator.methods.date("13/01/1990")
  * @result false
  *
  * @example jQuery.validator.methods.date("01.01.1900")
  * @result false
  *
  * @example <input name="pippo" class="dateUS" />
  * @desc Declares an optional input element whose value must be a valid date.
  *
  * @name jQuery.validator.methods.dateUS
  * @type Boolean
  * @cat Plugins/Validate/Methods
  */

jQuery.validator.addMethod(
	"dateUS",
	function(value, element) {
		var check = false;
		var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
		if( re.test(value)){
			var adata = value.split('/');
			var mm = parseInt(adata[0],10);
			var dd = parseInt(adata[1],10);
			var yyyy = parseInt(adata[2],10);
			var xdata = new Date(yyyy,mm-1,dd);
			if ( ( xdata.getFullYear() == yyyy ) && ( xdata.getMonth () == mm - 1 ) && ( xdata.getDate() == dd ) )
				check = true;
			else
				check = false;
		} else
			check = false;
		return this.optional(element) || check;
	},
	"Please enter a date in the format mm/dd/yyyy"
);

Use “dateUS” as your validation method.
Example: <input type=”text” class=”dateUS” name=”myDate”>

Returning Multiple Value Elements to ColdFusion Remote Method via jQuery AJAX

Lets say I have a select element that supports multiple selected values:

<form>
<select id="mySelect" multiple size="3">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</form>

I wish to return this information to my ColdFusion CFC that contains a remote method via AJAX:

$.ajax({
	type: 'POST',
	url: 'myCFC.cfc',
	dataType: 'JSON',
	data: {
		'method':'myMethod',
		'value':$('mySelect').val()
	}
});

My CFC method looks like:

<cffunction name="myMethod" access="remote" output="false">
	<cfargument name="value" required="true" type="string">

	<cfset local.myVar = arguments.value>
	<!--- more logic --->
</cffunction>

This solution will error out due to the fact that the key “value” passed via AJAX is actually passed as “value[]”. Note the appended brackets denoting an array. I can’t reference “#arguments.value[]#” as this tries referencing an array and “#arguments[‘value[]’]#” is not allowed.

I tried all sorts of ways to try and get at that key value in the method. The only way I could come up with was to reference the argument via an index such as “arguments[1]”. But my real code was too complex to rely upon this method.

Another way was to append “.toString()” call the the end of the “val()” call when retrieving the values selected. This converts the array of values to a comma-delimited string of values. However this method will not allow the use of commas.

What I ended up doing was inserting some logic to convert any arrays into a pipe-delimited list. It’s not the best solution in the world but I think it’ll work.

var thisVal = $(this).val();
if ($.isArray(thisVal))
	var thisValRtn = thisVal.join("|");
else
	var thisValRtn = thisVal;

$.ajax({
	type: 'POST',
	url: 'myCFC.cfc',
	dataType: 'JSON',
	data: {
		'method':'myMethod',
		'value':thisValRtn
	}
});

If you have a better method than this, I’d love to hear about it.

What Constitutes an Attribute or Property in jQuery 1.6.1

jQuery 1.6.1 RC1 was released today, helping resolve the .attr() backwards compatibility issue along with a few other fixes.

jQuery.com released a nice chart on what .attr() and .prop() should be used for going forward from jQuery 1.6+. I thought I’d publish this for future reference. Note that all properties can still be accessed via 1.6.1, but not necessarily via 1.6.

According to jQuery.com the .prop() method should be used for boolean attributes/properties and for properties which do not exist in html (such as window.location). All other attributes (ones you can see in the html) can and should continue to be manipulated with the .attr() method.

Attribute Property
accesskey async
align autofocus
class checked
contenteditable location
draggable multiple
href readOnly
id selected
label
rel
src
tabindex
title
type
width

Understanding jQuery 1.6’s DOM Attribute and Properties

jQuery 1.6 released a significant change to the way it handles DOM attributes and properties.

Take for example in version 1.5.2, the following code would return isCheckedAttr as “true”.

<input type="checkbox" checked="checked" />

<script type="text/javascript">
var isCheckedAttr = $('input').attr("checked");
</script>

In version 1.6 the addition of .prop() and .removeProp() changes what the .attr() method will return when referencing DOM properties. The following example will return isCheckedAttr as “” and isCheckedProp as “true”. Notice 1.5.2 returned “true” instead of “” for isCheckedAttr.

<input type="checkbox" checked="checked" />

<script type="text/javascript">
var isCheckedAttr = $('input').attr("checked");
var isCheckedProp = $('input').prop("checked");
</script>

Now… check this out. In HTML and XHTML you can set the checked property as an attribute. This example in jQuery 1.6 will return “checked” for isCheckedAttr (remember 1.5.2 returned “true”). The isCheckedProp will still return “true”.

<input type="checkbox" checked="checked" />

<script type="text/javascript">
var isCheckedAttr = $('input').attr("checked");
var isCheckedProp = $('input').prop("checked");
</script>

Try this case on for size… If I don’t set the checked attribute or property isCheckedAttr will always return “undefined” (not an empty string) and isCheckedProp will return false (until I click the checkbox which will make it true).

<input type="checkbox" />

<script type="text/javascript">
var isCheckedAttr = $('input').attr("checked");
var isCheckedProp = $('input').prop("checked");
</script>

This all makes sense, though a bit confusing since the attribute is basically converted into a property at DOM load making upgrading to version 1.6 much more difficult than most recent version upgrades, so be sure to do some extra testing.

Okay, ready for this, one more item to throw at you… if I’m reading the bug ticket right, if an attribute does not exist but the property does, the .attr() will bring back the property boolean value as the attribute in the next release (probably 1.6.1). This appears to be a backwards compatibility fix for reading properties, but not setting them.

UPDATE 5/9/2011: appendTo, a jQuery company I highly respect, released an executive brief on jQuery 1.6 stating that it recommends not upgrading to jQuery 1.6 until 1.6.1 is released. This version will return either the name of the attribute (if true) or undefined (if false) for .attr(BooleanAttribute) and could be released as early as Tuesday, May 10, 2011. It also has a good read on the rest of the features new to this version.

John Resig also released an example:

“Let’s pretend we’re working with a checkbox that isn’t checked at all:

<input type="checkbox" id="c"/>

$("#c").attr("checked") => false // 1.5.2
$("#c").attr("checked") => undefined // 1.6
$("#c").attr("checked") => undefined // 1.6.1

The user then checks the checkbox OR we set the check by doing .prop(“checked”, true) OR we set the check by doing [0].checked = true, the result would be:

$("#c").attr("checked") => true // 1.5.2
$("#c").attr("checked") => undefined // 1.6
$("#c").attr("checked") => "checked" // 1.6.1

Note that if we had done .attr(“checked”, “checked”) OR .attr(“checked”, true) to set the checked property then .attr(“checked”) would’ve returned “checked” in both 1.6 and 1.6.1.

In short: In jQuery 1.6.1 .attr(BooleanAttribute) now returns either the name of the attribute (if true) or undefined (if false). Which is consistent with the rest of the API and with the DOM itself.

I should note that all of this is a moot point if you’re using .prop(“checked”) – that will just return true/false consistently based upon the current checked state of the checkbox.”

Playing Interference with jQuery and Prototype

Lately I’ve had to deal with jQuery conflicting with Prototype.

For starters I was forced to upgrade from jQuery 1.4.2 to 1.5.2 to fix a conflict when doing clones.

But of course there’s always the ‘$’ conflict. So I wanted to come up with a slick way of keeping the ‘$’ alias available for use by jQuery code.

For starters the existing code looks like this:

<script src="prototype.js" type="text/javascript"></script>
<script src="jQuery.min.js" type="text/javascript"></script>
<script type="text/javascript">
	jQuery.noConflict();
	jQuery(document).ready(function(){
		/* js code here */
	});
</script>

The ‘jQuery.noConflict()’ statement kills off the jQuery ‘$’ alias for me. So to have ‘$’ available for my use I wrapped everything around a Self-Invoking Anonymous Function looking like this:

(function( $ ) {
	$(document).ready(function() {
		/* js code here */
	});
})(jQuery);

https://gist.github.com/firefighter990/5340332

Notice that the jQuery object is now being passed in via the $ argument inside a JavaScript closure. Thus everything I do inside the closure will not conflict with any other library.

Coldfusion Builder 2 Beta and jQuery Code Assist

I am currently using ColdFusion Builder 2 Beta for my primary projects. One item I noted was the lack of jQuery code assist.

I did find a way to turn code assist on for jQuery 1.3. After some research I really haven’t found a way to include 1.4, 1.5 or 1.6RC. But 1.3 is better than nothing.

To turn on jQuery 1.3 code insight go to [ preferences > HTML > Editors > JavaScript > Code Assist ] and select jQuery 1.3. After you click [OK] jQuery code insight will work right away.

If anyone knows how to upgrade the versions w/o major work please let me know. Thanks!