+1

Related checkbox validation with JQuery

ColdFusion, Javascript, Tips and Tricks

I was given a problem yesterday where I needed to do the following client-side validation. If a user selects a checkbox that they wish to enable credit card transactions, I need to display a panel of specific credit card companies and they need to select at least one before submitting.

If you think about writing the JS to do this without a library it is a somewhat lengthy task. In essence, you would need to do some type of an onsubmit function on your form, check the value of the key checkbox. If it was checked, check the value of each credit card checkbox to see if the user had selected one of the children. After writing this in JQuery, I thought it might be worth demonstrating what an easy task this is.

Let's start with the specific part of my form that has my checkboxes:

<label for="RequireCCInfo">Require Credit Card Information?</label>
<input name="RequireCCInfo" id="RequireCCInfo" value="1" type="checkbox">
<div id="CreditCardCompanyPanel">
	<div>
		<input id="ccAmex" class="ccCheckBox" value="1" type="checkbox">
		<label for="ccAmex">American Express</label>
	</div>
	<div>
		<input id="ccVisa" class="ccCheckBox" value="1" type="checkbox">
		<label for="ccVisa">Visa</label>
	</div>
	<div>
		<input id="ccDiscover" class="ccCheckBox" value="1" type="checkbox">
		<label for="ccDiscover">Discover</label>
	</div>
	<div>
		<input id="ccMc" class="ccCheckBox" value="1" type="checkbox">
		<label for="ccMc">Master Card</label>						
	</div>
</div>

 

There is nothing too notable in all of that other than the fact that you should notice that I have added a class "ccCheckBox" to all of my dependent checkboxes. I will explain more on that in a bit, but I wanted to point out that it is there. You will also notice that I am not doing anything in the way of hiding the "CreditCardCompanyPanel" div. We need to determine at request time whether that will be hidden or not based on whether the "RequireCCInfo" checkbox is checked.

Now, here is the fun part... I am including the JS that I use for this task below:

<script language="javascript">	
(document).ready(function(){
	$("#RequireCCInfo").change(function(){
		toggleCreditCardCompanyPanel();
	}); 	
	function toggleCreditCardCompanyPanel()	{
		if ($("#RequireCCInfo").attr("checked") == true) 	$("#CreditCardCompanyPanel").show();	
		else $("#CreditCardCompanyPanel").hide();
	}
	$("#SaveButton").click(function(){
		var pass = false;
		if ($("#RequireCCInfo").attr("checked") == true){
			$(".ccCheckBox").each(function() {
               			if ($(this).attr("checked") == true) pass = true;
            		});
		}
		else pass = true;
		if (pass) $("#frmMyForm").submit();
		else alert('You must select at least on credit card company if "Require Credit Card Information" is checked.');
	}); 
	toggleCreditCardCompanyPanel();
});
</script>

First, by using the $(document).ready() function we are telling JQuery to run this JS once the DOM has been completely loaded. Let's look at each section within that ready() block...

The first thing you will see is the $("#RequireCCInfo").change() method. JQuery gives us the concept of binding a listener to an element. For our example, this listener says that anytime that an element with an ID of "RequireCCInfo" is changed, that we will run the code in its function(). You will see that anytime our "RequireCCInfo" checkbox is changed we are going to run a function called toggleCreditCardCompanyPanel(). As you can see we have that method defined immediately after our "RequireCCInfo" checkbox.

In our toggleCreditCardCompanyPanel() method, we are making the decision as to whether or not our "CreditCardCompanyPanel" will be displayed based on whether our user has decided to check the box labeled "Require Credit Card Information?". By using the JQuery selectors we are in essence saying: If a checkbox with an ID of "RequireCCInfo" is checked, display an element with the ID "CreditCardCompanyPanel". Otherwise we will hide this element.

Next comes our validation on form submit... and pretty cool stuff!

Basically I have added a listener which is bound to our submit button with the ID of "SaveButton" which will submit our form "frmMyForm". Anytime that this button is clicked, we will run the code in the function() block. We start this function by setting a value pass=false. We will use this variable to determine whether our form has passed validation. Next we get just a small taste of the magic of JQuery selectors. First, as we did in the toggleCreditCardCompanyPanel() function, we are determining if the element with the ID of "RequireCCInfo" is checked. If so, by using the each() function, we are going to loop through all elements on the page with the class "ccCheckBox" (remember that from above?). In each iteration of the loop we are going to determine if the element has been checked. If so, we are going to set pass=true since we know that our validation has passed.

Lastly, now that we have determined that our form is either going to pass/fail, we take the appropriate action. If pass==fail, we are simply going to alert a message telling the user that if they are going to enable credit cards that they have to choose at least one credit card company. Otherwise, we are going to call the submit() method on our form.

I almost took the time to write out the equivalent of this in POJS (plain old JavaScript) to show how much easier life is with JQuery, but I realized I didn't have the time, patience, or will. JQuery has spoiled me!

0

Javascript library of ColdFusion functions

Javascript

I often find myself working in Javascript and thinking "Man I wish there was a JS equivalent of the CFML xyz() method!" Tonight was one of those nights as I was about to make my own ListAppend() method. Instead, I came across a Javascript library that is collection of ColdFusion functions ported into Javascript, written by a guy named Randy Anderson. If you are ever looking for any of the functions listed below, go check out Randy's Javscript Library of ColdFusion Functions.

Here is the list of functions included in the library:

Abs(number)
ArrayAppend(array, value)
ArrayLen(array)
ArraySort(array, sort_type [, sort_order ])
ArrayToList(array [, delimiter ])
Ceiling(number)
Compare(string1, string2)
CompareNoCase(string1, string2)
DateDiff(datepart, date1, date2)
DecimalFormat(number)
DollarFormat(number)
Find(substring, string)
FindNoCase(substring, string)
Insert(substring, string, position)
IsDate(date)
IsNumeric(string)
LCase(string)
Left(string, count)
Len(sting)
ListAppend(list, value, [, delimiters])
ListDeleteAt(list, position [, delimiters ])
ListFind(list, value [, delimiters ]))
ListFindNoCase(list, value [, delimiters ]))
ListGetAt(list, position [, delimiters ]))
ListLen(list [, delimiters])
ListToArray(list [, delimiters])
LTrim(string)
Mid(string, start, count)
Replace(string, substring1, substring2 [, scope ])
ReplaceNoCase(string, substring1, substring2 [, scope ])
Reverse(string)
Right(string, count)
Round(number [, number of decimal places])
RTrim(string)
Trim(string)
UCase(string)
URLDecode(string)
URLEncodedFormat(string)
tags:
Javascript
0

Evidence Item #12826 in the case of Microsoft VS Web Developers

Javascript

I feel like a misguided Kanye West proclaiming "Bill Gates doesn't care about web people!", but seriously... What is it? Why is it so hard to just follow the same standard that other browsers don't seem to have such a hard time with?

After my 3rd Internet Explorer specific problem in about 24 hours, I had to share this one since it is very easy to demonstrate, and I am sure that someone will bang their head on it in the future. I have come to the conclusion that without some hack workaround of setting temp javascript variables, it is not possible to scrub the value of a form field with an onKeyUp event, and then take action on that scrubbed value at onChange.

Here is a simple example:

The idea behind that code is that with each keystroke, we are going to pull out invalid characters from the field. Then on our update, we are going to do something with that value. Presumably, that would be something more helpful than an alert, such as in my case where I wanted to do an Ajax update to a session scoped bean that was child of a user facade, but you get the idea. This works in Firefox and Opera without a hitch. IE6? nope. IE7? nope...

I wondered if it might have been simply a problem with the way that I was modifying the string and then returning it. So I tried just returning the original string like this:

Nope... still the same.

So what the hell is going on here? At this point I had a suspicion that it had to do with the fact that we are resetting the value of the field before the onChange, which I confirmed with this:

So there it is... Apparently, Microsoft does not think that you ought to be able to alter a field's data with onKeyUp, and then do something onChange. For what it is worth I found that this exact same behavior happens with TMT_Validator when using field filtering. I used to feel that this was an issue with TMT itself, but obviously it is IE itself.

So... a big thanks to IE Team for once again killing part of my day.

tags:
Javascript
0

Javascript examples - removeElement() and replaceAll()

Javascript

I am currently working on a heavily Ajax-injected loan application project. This morning I created a couple of Javascript menthods that I thought might be useful to others. First is one named replaceAll() that will replace all instances of a substring within a string. Secondly is a removeElement() function that will remove a DOM element based on its ID. I am sure that some Javascript gurus out there are going to correct me on my approach, but these are functional and will hopefully save someone some time.

First is my:

replaceAll([original string],[find string],[replace string])


function replaceAll(OldString,FindString,ReplaceString) {
  	var SearchIndex = 0;
  	var NewString = ""; 
  	while (OldString.indexOf(FindString,SearchIndex) != -1)    {
    	NewString += OldString.substring(SearchIndex,OldString.indexOf(FindString,SearchIndex));
    	NewString += ReplaceString;
    	SearchIndex = (OldString.indexOf(FindString,SearchIndex) + FindString.length);         
 	}
  	NewString += OldString.substring(SearchIndex,OldString.length);
  	return NewString;
}

Next up is:

removeElement([element ID])

function removeElement(id)	{
	var Node = document.getElementById(id);
	Node.parentNode.removeChild(Node);
}

If anyone has a better approach for either of these, I am all ears.

EDIT:

That didn't take long! Richard Leggett posted a much cleaner solution to replaceAll() in the comments below. Just to make sure no one misses it, I am adding it here:


function replaceAll( str, searchTerm, replaceWith, ignoreCase )	{
	var regex = "/"+searchTerm+"/g";
	if( ignoreCase ) regex += "i";
	return str.replace( eval(regex), replaceWith );
}

tags:
Javascript
0

InnerHTML no more! Swapping content using the DOM.

Javascript
Companions to this post:

Although it is very common to see swappable divs in web applications, it is remarkable how many times you see the innerHTML property of an element used to either insert or remove content from an element. Why is this remarkable? The innerHTML property is not part of the current HTML specification, in part due to the fact that it can render content invalid for assitive technologies that support scripting.

Even the majority of the Ajax frameworks that I have been exposed to seem to make liberal use of innerHTML. I am not suggesting in anyway that it is "wrong" to use it, and I have certainly used it on occasion, but for those interested in staying with the HTML 4.0 specs, there are other ways to accomplish the same result.

Using the DOM your document is nothing more than a series of parent/child relationships, which you can traverse through using native Javascript methods that are part of each element. For instance, say I have the following div hierarchy:


If I wanted to find out the background color of the parent div of "Child2", I could access it like this:


document.getElementById("Child2").parentNode.style.backgroundColor

You can go up or down throughout the entire hierarchy using parentNode and childNodes (array) properties. Once you get into the mindset that everything is part of a bigger whole and has its own space in the relationship, it becomes simpler to get your head around working with the DOM.

I have put together a small example showing how to create swappable divs using only the DOM and valid scripting as an example for those interested. The basic idea in this example is that we have a display div named DisplayContainer where our dynamic content will be displayed. We also have a hidden div named HoldingContainer. Within that div, we store the divs that that will be displayed in the DisplayContainer div on various onclick actions.

As we click on various items, we call a function named wwwWriteContent which accepts an object argument that is to be displayed in the content container. That method first loops through its childNodes and sends any children back to the HoldingContainer div. It does this by saying "as long as the condition exists that the DisplayContainer has a first child, send that child to the holding container and repeat". When this loop finishes, it then moves the object argument into the display container so that it is displayed.

In this code you will also see another helpful function wwwClearElement() which accepts an object argument as well. It runs a similar loop but rather than moving children to another location, it simply erases them permanently from the document.

So with that preface, let's walk through the code. In the head of our document, we are going to define the functions I described above:


// this function clears all child elements out of the object that is passed in
function wwwClearElement(obj) {
	while(obj.firstChild) obj.removeChild(obj.firstChild);
}


// this function sends any child objects back into the 'HoldingContainer' div
function wwwWriteContent(contentObject)	{
	// Here we will define our Containers
	// this is the display container
	var ContentContainer = document.getElementById("DisplayContainer");
	// this is a repository for divs not currently in the display
	var ContentHolding = document.getElementById("HoldingContainer");
	// send any children objects currently in the display to the holding div
	while(ContentContainer.firstChild) {
		ContentHolding.appendChild(ContentContainer.firstChild);
	}
	// put the active content in thd display div
	ContentContainer.appendChild(contentObject);
}

Hopefully with the inline comments and the description above, that Javascript makes sense to you at this point. Now that we have defined, we can walk through the body of the document. First, let's take a look at the HoldingContainer div.


		

You can see that the outer div HoldingContainer is set to "display:none". This means that it, nor any of its child nodes within can be viewed. You may also notice our suicidal div "divCLoseMe". The button within it calls our wwwClearElement() function, wiping itself off the face of the earth.

Next we create some links:

You can see that each of those links call our wwwWriteConent() function and pass the object that we wish to be displayed in our DisplayContainer.


Here is where we will show our dynamic content:

That is it! Hopefully from this you will go on and play with the childNodes array, and practice walking up and down the object heirarchy in some of your own code.

tags:
Javascript

Search

Various Links

HikeTheCanyon.org - Rim-to-Rim hike of the Grand Canyon.
Dave Shuck on Twitter - Follow me on Twitter.
Scriptalizer - Minify your Javascript and CSS