MASS EFFECT checkboxes with jQuery and CF!

If you've struggled with emulating GMail or Yahoo style Select All functionality for tabular forms and you're in love (or just curious) about jQuery and ColdFusion then this post is for you! If you love MASS EFFECT and you just want to see where someone has come up with a legitimate reason to use the words MASS EFFECT in code then this post if for you too!

So first off, I'm not building yet another browser based mail client. However, there are other uses for list style forms that feature a checkbox Select - such as applying a massive update to many records at once. In this case we'll be looking at applying a mass Status update to a potentially large number of Warehouse Containers.

For this example to work properly you'll probably want to pay close attention to how you've auto-generated the names of your checkboxes because your form processor will thank you for doing so!

The following code shows a simple cfloop on a query that's dynamically building controls based on user search results that were collected from a parent form...

view plain print about
1<cfloop query="qryContainer">            
2    <cfif qryContainer.JobNo EQ "">
3        <cfset qryContainer.JobNo = "N/A">
4    </cfif>
5    <cfif qryContainer.ItemID EQ "">
6        <cfset qryContainer.ItemID = "N/A">
7    </cfif>
8    <cfif qryContainer.ItemDesc EQ "">
9        <cfset qryContainer.ItemDesc = "N/A">
10    </cfif>
11    <tr>
12        <td class="results">
13            <cfif Static EQ true>
14                N/A
15            <cfelse>
16                <input type="checkbox" name="cont#containerID#">
17            </cfif>                    
18        </td>
19        <td align="left" class="results" width="90"><a href="javascript:showContWin(#ContainerID#)">#ContainerID#</a></td>
20        <td class="results">
21            <cfinput name="pur#ContainerID#" type="text" size="5" value="#PurityLevel#" style="background-color:yellow;" onChange="manageEditedControlState(this)">
22        </td>
23        <cfif Static EQ true>
24            <td align="left" class="results" width="140" valign="top"><a href="javascript:showContWin(#ContainerID#)">#StatusDisplay#</a></td>
25        <cfelse>
26            <td class="results">
27                <cfselect name="status#ContainerID#" query="qryContainerStatusSelector" value="ContainerStatusCode" display="ShortDesc" selected="#StatusCode#" style="background-color:yellow;" onChange="manageEditedControlState(this)"/>
28            </td>    
29        </cfif>                
30        
31        <td align="left" class="results"><a href="javascript:showContWin(#ContainerID#)">#JobNo#</a></td>                
32        <td align="left" class="results"><a href="javascript:showContWin(#ContainerID#)">#ItemID#</a></td>
33        <td align="left" class="results" width="140" valign="top"><a href="javascript:showContWin(#ContainerID#)">#ItemDesc#</a></td>
34        <td align="left" class="results"><a href="javascript:showContWin(#ContainerID#)">#LocationCode#</a></td>
35        <td align="left" class="results"><a href="javascript:showContWin(#ContainerID#)">#ZoneCode#</a></td>
36        <td align="left" class="results"><a href="javascript:showContWin(#ContainerID#)">#CubeCode#</a></td>
37        
38    </tr>                        
39</cfloop>

We also have a checkbox control named selectAll which will essentially control our toggle...

view plain print about
1<cfinput type="checkbox" name="selectAll" value="Select All" onClick="toggleContainerFilters(this)">

So basically when we click Select All we want for all checkbox controls that uniquely identify a Warehouse Container to be Selected or Deselected. The following bit of jQuery will handle that quite easily for us.

view plain print about
1toggleContainerFilters = function(selectAll){
2    var checkAll = selectAll.checked;
3    $("input[type=checkbox]").each(function(){
4        if (this.name != 'searchJobs' && this.name != 'onlyFinishedMaterial' && this.name != 'searchPosition'){
5            this.checked = checkAll;
6        }            
7    });    
8}

One thing that you need to make certain of is that you explicitly exclude any checkboxes that you don't want included in this toggle. If you notice I'm doing just that so that we don't change the value of my searchJobs, onlyFinishedMaterial or searchPosition checkboxes that live in the parent search filter page shown in the image below. Please note that you can most certainly avoid conflicts like this by using specific CSS classes for each type of checkbox but for my purposes addressing the controls using input[type=checkbox] was a good fit.

So far we've dynamically named our checkboxes and we have a way to turn them on and off - buy WHY? Well, we need to be able to mass update all selected Containers to have the same Status. Please keep in mind that this form also has other controls on it that are NOT allowed to be mass updated so that's why you see the standard Save button on the bottom right in the photo shown above.

In the following image and code snippet, you'll see where I'm invoking a cfwindow to allow the end user to select the new Status...

The code for the cfwindow is pretty simple as it will ultimately fire up JavaScript functions on the parent page and if the user is really sure that they're sure that they're certain :0 they want to update Mass Effect style then they can go ahead and "Make it so"...

view plain print about
1<cfinvoke component="#REQUEST.cfcDir#.containerstatus" method="getContainerStatusSelector" nonStaticOnly="true" returnvariable="qryContainerStatusSelector">
2
3invokeMassEffectProcessing = function(){
4    var newSelectedStatusCode = ColdFusion.getElementValue("newContainerStatus", "selectContainerStatusAll", "value");
5    execMassEffect(newSelectedStatusCode);
6}
7
8<div align=center style="font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;">
9    <cfform format="html" name="selectContainerStatusAll">
10        New Container Status&nbsp;<cfselect name="newContainerStatus" query="qryContainerStatusSelector" value="ContainerStatusCode" display="ShortDesc"/>
11        <br/><br/>
12        <cfinput type="button" name="btnCancelSetNewStatusAll" value="Cancel" onClick="closeMassStatusWin()">
13        <cfinput type="button" name="btnSetNewStatusAll" value="Set New Container Status" onClick="invokeMassEffectProcessing()">
14    </cfform>
15</div>

Back on parent page land we've got the following series of JavaScript functions that will start the process of talking to our form processor if the user decides to go ahead with the update...

view plain print about
1postChanges = function(massEffect){
2        if (massEffect == false){
3            confirmPost = confirm('Are you sure that you want to Save All Container Purity and Status Changes?');    
4        }
5        else{
6            confirmPost = confirm('Are you sure that you want to Update the Status of All Selected Containers?');
7        }
8        if (confirmPost == true){
9            ColdFusion.Ajax.submitForm('containerMgmtDetail', 'formprocs/proccontainermanagement.cfm?massEffect=' + massEffect, postChangesCallback, errorHandler);
10            //ColdFusion.Ajax.submitForm('containerMgmtDetail', 'testpost.cfm');
11        }
12        else{
13            massEffectInProcess = false;
14        }
15    }
16    
17    postChangesCallback = function(callbackMsg){
18        massEffectInProcess = false;
19        document.containerMgmtDetail.newMassStatusVal.value = '';
20        $("#containerSearchResults").load('savedcontainerchanges.cfm');
21        alert('Container Updates have been Applied and Saved.');
22    }
23
24
25    showMassStatusWin = function(containerID) {        
26        var day = new Date();
27        contWin = 'contInfo' + day.getTime();
28        var windowOptions = new Object();
29        windowOptions.width = 700;
30        windowOptions.height = 300;
31        windowOptions.center = true;
32        windowOptions.modal = true;
33        windowOptions.resizeable = true;
34        windowOptions.initshow = true;
35        windowOptions.draggable = true;
36        windowOptions.closable = true;
37        windowOptions.headerstyle = 'font-family: verdana; background-color: #0066FF;';
38                
39        ColdFusion.Window.create(contWin,'Mass Status Update','selectcontainerstatusall.cfm?containerID=' + containerID, windowOptions);    
40        ColdFusion.Window.onHide(contWin, killMassStatusWin);
41    }        
42
43    killMassStatusWin = function(winToKill){
44        ColdFusion.Window.destroy(winToKill, true);
45        if (massEffectInProcess == true){
46            postChanges(true);
47        }
48    }
49    
50    closeMassStatusWin = function() {
51        ColdFusion.Window.onHide(contWin, killMassStatusWin);
52        ColdFusion.Window.hide(contWin);
53    }    
54
55    execMassEffect = function(newStatusCode){
56        document.containerMgmtDetail.newMassStatusVal.value = newStatusCode;
57        massEffectInProcess = true;
58        closeMassStatusWin();
59    }

You may have noticed that I've snuck a global in there and that I'm referencing some form variables. massEffectInProcess will help me maintain state if I'm working with the non-Select All style update and newMassStatusVal is a hidden form field that my form processor will use here in just a sec!

Moving onto the How, I've got a form processor that we'll call using ColdFusion.Ajax.submitForm and it will actually process both of the aforementioned scenarios - a "Mass Effect Status Update" (yes, I'm an XBOX Gaming Nerd and I love the Mass Effect games) or the more common "I just updated 3 or 4 of these decimals so please save my changes".

Notice in the code below that I'm parsing the inputs and I'm also looking for a boolean named massEffect that will instruct my code as to whether or not we're performing a Mass Status Update...

view plain print about
1<cfparam name="containerIDList" default="0">
2    
3<cftransaction>    
4    <cfloop list="#FORM.fieldnames#" index="i">
5        <cfif URL.massEffect EQ false>
6            <cfif Left(i, 3) EQ "pur">
7                <cfset currentContainerID = ReplaceNoCase(i, "pur", "")>
8                <cfset newPurityVal = FORM[i]>
9                <cfif NOT IsNumeric(newPurityVal)>
10                    <cfthrow message="Invalid Purity - You must enter a valid numeric value for the Purity field of Container ID #currentContainerID#">
11                <cfelse>
12                    <cfquery name="qryUpdatePurity" datasource="#REQUEST.ds1#">
13                        UPDATE        Container
14                        SET                PurityLevel = <cfqueryparam cfsqltype="cf_sql_decimal" value="#newPurityVal#" scale="2">
15                        WHERE        ContainerID = <cfqueryparam cfsqltype="cf_sql_integer" value="#currentContainerID#">
16                    </cfquery>    
17                </cfif>
18            <cfelseif Left(i, 6) EQ "status">
19                <cfset currentContinerID = ReplaceNoCase(i, "status", "")>
20                <cfset newStatusVal = FORM[i]>
21                    <cfquery name="qryUpdateStatus" datasource="#REQUEST.ds1#">
22                        UPDATE        Container
23                        SET                StatusCode = <cfqueryparam cfsqltype="cf_sql_integer" value="#newStatusVal#">
24                        WHERE        ContainerID = <cfqueryparam cfsqltype="cf_sql_integer" value="#currentContainerID#">
25                    </cfquery>            
26            </cfif>
27        <cfelse>
28            <cfif Left(i, 4) EQ "cont">
29                <cfset containerIDList = containerIDList & "," & ReplaceNoCase(i, "cont", "")>
30            </cfif>    
31        </cfif>
32    </cfloop>
33    <cfif URL.massEffect EQ true>
34        <cfset containerIDList = Replace(containerIDList, ",,", "", "all")>
35        <!---<cfthrow message="Container ID Listing is #containerIDList#">--->
36        <cfquery name="qryUpdateStatus" datasource="#REQUEST.ds1#">
37            UPDATE        Container
38            SET                StatusCode = <cfqueryparam cfsqltype="cf_sql_integer" value="#FORM.newMassStatusVal#">
39            WHERE        ContainerID IN (<cfqueryparam cfsqltype="cf_sql_integer" value="#containerIDList#" list="true" separator=",">)
40        </cfquery>                    
41    </cfif>    
42</cftransaction>

This started off as a short entry and then turned into a bigass pile of solution. At least this way I won't forget it and I know that I've got it safely stored in my very own BlogCFC in case I can't remember how to cast this spell next month! I will add that there are a lot of other pieces to this application that are definitely outside of the scope of checkbox magic, but hey ~ I've shown you how to play Mass Effect with jQuery and ColdFusion. So remember folks - ALL YOUR CHECKBOXES ARE BELONG TO US.

Comments
# Posted By coach outlet | 5/20/10 4:45 AM
# Posted By chanel bags | 5/29/10 4:42 AM
new era red bull hats for sale's Gravatar Dear customers,
Welcome to our website, we provide company for many years ,and the caps or hats in here are so cool and fashion.http://www.prowantgo.net/
# Posted By new era red bull hats for sale | 7/10/10 7:01 AM
batterie's Gravatar the caps or hats in here are so cool and fashion.
# Posted By batterie | 7/20/10 8:49 AM
labatterie's Gravatar we provide company for many years
# Posted By labatterie | 7/20/10 8:50 AM
r4 ds's Gravatar Dear customers……
# Posted By r4 ds | 7/20/10 8:51 AM
handychina's Gravatar It is very interesting Sciphones i68,ciphone c6,Ciphone,cect handy,Sciphones ,cecthandys,hiphone,HIPHONE 4,pinphone 3gs?Grosshandel in http:/www.efox-shop.com/
# Posted By handychina | 7/24/10 12:02 AM
NFLjerseys's Gravatar [url=http://www.nfljerseys-shopping.com/]NFL jerseys[/url] of 32 teams are available, other [url=http://www.nfljerseys-shopping.com/]football jerseys[/url] are also supplied. Welcome to nfljerseys-shopping.com and purchase a [url=http://www.nfljerseys-shopping.com/]cheap jerseys[/url].
# Posted By NFLjerseys | 7/27/10 12:13 AM
affliction hat, kid robot hast, billionaire boys c's Gravatar Develops, people’s living standards improve, people increasingly value the quality of life, of course, this also includes food and clothing and so on. This is mainly manifested in the form of the stress on the wear is, such as caps: we all have hobbies, pursue their favorite
handyking's Gravatar eFox-shop.com puts quality at the top of business plan. Our Quality Control team carries out various testing processes to ensure only quality products are sold on the web. No counterfeits or reimbursed items would appear on our selling lists.
www.efox-shop.com
<a href="http://www.efox-shop.com"> chinahandy</a>
<a href="http://www.efox-shop.com"> dual sim handy</a>
<a href="http://www.efox-shop.com"> touchscreen handy</a>
c
# Posted By handyking | 7/29/10 6:22 AM
NFL Jerseys's Gravatar Ha, that’s actually a really good suggestion. Thanks so much for this!
http://www.onesunglasses.com oakley sunglasses
http://www.onesunglasses.com ray ban sunglasses
http://www.onesunglasses.com gucci sunglasse
# Posted By NFL Jerseys | 8/23/10 11:50 PM
cheap nfl jerseys's Gravatar I love it,Excellent article.I am decide to put this into use one of these days.Thank you for sharing this.To Your Success!
http://www.nfljerseyspaypal.com cheap nfl jerseys
http://www.nfljerseysgo.com NFL Shop
http://www.nfljerseysgo.com NFL Jerseys
http://www.eightshop.com polo shirts
# Posted By cheap nfl jerseys | 8/24/10 12:01 AM
fast easy runescape's Gravatar <a href="http://www.rs2happy.com/runescape-money">f... easy runescape</a>
<a href="http://www.rs2king.com/">runescape sale</a>
<a href="http://www.hzgames.com/">buy runescape</a>
<a href="http://www.rs2seller.com/">rs sale</a>
<a href="http://www.myrsmoney.com/">fast easy runescape</a>
# Posted By fast easy runescape | 9/3/10 8:51 AM
runescape sale's Gravatar [url=http://www.rs2happy.com/runescape-money]fast easy runescape[/url]
[url=http://www.rs2king.com/]runescape sale[/url]
[url=http://www.hzgames.com/]buy runescape[/url]
[url=http://www.rs2seller.com/]rs sale[/url]
[url=http://www.myrsmoney.com/]fast easy runescape[/url]
# Posted By runescape sale | 9/3/10 8:52 AM
buy runescape's Gravatar Life is a pure flame, and we live by an invisible sun within us.
# Posted By buy runescape | 9/3/10 8:53 AM
rs sale's Gravatar And forever has no end.
# Posted By rs sale | 9/3/10 8:53 AM
fast easy runescape's Gravatar Don’t cry because it is over, smile?because it happened.
# Posted By fast easy runescape | 9/3/10 8:54 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.5.007. Contact Blog Owner