|
Controlling show() hide() Divs with a JQuery powered Select field |
There are many ways of hiding all your page elements then only showing specific areas based on user selection. One old school way of changing the displayed page content was with a select field that had an onchange event that posted to the same page, but with a URL variable.
I have been testing out a variation on this using the JQuery show() / hide() functions.
We attach an event to the select field, and pass the selected option to a JQuery function, as in the example code below.
2
3<select name="field_data_loc[key]" class="form-select required" id="edit-field-data-loc-key" onChange="showHide(this.value)" >
4<option value="didnotchoose" selected="selected">Choose</option>
5<option value="web">Website</option>
6<option value="file">File to upload</option>
7<option value="url">Url</option>
8</select>
We have a series of DIV's that are named the same as the select field options. All these DIV's will be hidden by default, apart from the "start" div.
2
3<div id="url">url</div>
4
5<div id= "file">file</div>
6
7<div id= "web">web</div>
Lastly we have our JQuery script. Here we have our showHide function. This accepts a DIV id, which is then shown. All other DIV's are hidden.
The last piece of script here simply hides all the DIV's on the page load, so that they are all hidden by default.
2
3 function showHide(obj)
4 {
5 var showDiv = "#"+obj;
6 $("div").hide();
7 $(showDiv).show();
8 }
9
10 // hide all the divs on start up
11 $('#web').hide();
12 $('#file').hide();
13 $('#url').hide();
14
15</script>
Putting it all together, and making it dynamic based on a list, it looks like this:
2
3<s/cript type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
4
5<cfoutput>
6<select name="field_data_loc[key]" class="form-select required" id="edit-field-data-loc-key" onChange="showHide(this.value)" >
7<option value="didnotchoose" selected="selected">Choose</option>
8
9 <cfloop list="#variables.mylist#" index="variables.index">
10 <option value="#variables.index#">#variables.index#</option>
11 </cfloop>
12
13</select>
14
15<div id="start">Starting div</div>
16
17<cfloop list="#variables.mylist#" index="variables.index">
18 <div id="#variables.index#">#variables.index#</div>
19</cfloop>
20
21<s/cript language="javascript">
22
23 function showHide(obj)
24 {
25 var showDiv = "##"+obj;
26
27 <cfloop list="#variables.mylist#" index="variables.index">
28 $('###variables.index#').hide();
29 </cfloop>
30 $('##start').hide();
31
32 //$("div").hide();
33 $(showDiv).show();
34 }
35
36<cfloop list="#variables.mylist#" index="variables.index">
37 $('###variables.index#').hide();
38</cfloop>
39
40</script>
41</cfoutput>
An example is here.
The code as you have isn't very flexible and it uses embeded event handlers--which I'd generally recommend avoiding.
Something like this is more flexible:
<select name="field_data_loc[key]" class="form-select required" id="edit-field-data-loc-key">
<option value="didnotchoose" selected="selected">Choose</option>
<option value="web">Website</option>
<option value="file">File to upload</option>
<option value="url">Url</option>
</select>
<div id="messages">
<div id="didnotchoose">Starting div</div>
<div id="url">url</div>
<div id="file">file</div>
<div id="web">web</div>
</div>
<InvalidTag type="text/javascript">
$("#edit-field-data-loc-key")
// attach the onchange behavior
.change(function (){
var value = $(this).val();
$("#messages > div").hide().filter("#" + value).show();
})
// run the change event now
.trigger("change");
</script>
You can see a preview of the code here: http://jsbin.com/iwoye3
Thanks for the feedback! I didn't like having the onchange event still in the select field, but was unsure of the change to make to de-couple it.
Also I can see why you would change the div handling, it is much neater having a cascading target (right terminology?) IE "#messages > div". I thought I would have to build an Array of divs then loop through it, but this is much better.
Thanks
Shaun
You don't have to use a parent container, you could assign all those divs with a unique class name as well. The container trick works really well when you have a lot of DOM elements, because directly accessing an element by ID is the fast way to reference something.
Another thing to keep in mind (although my example doesn't implement it) is that whenever you can cache the results of a jQuery selection, the better the performance will be. If you're going to be accessing the jQuery collection over and over, then make sure to cache the results so that you're not always re-doing the lookup.
<td>Type of finish</td>
<td>
<cfset variables.shapeList = "Standard,Shape,Braid,Pole">
<cfoutput>
<select name="tof" class="form-select required" id="tof" onChange="showHide(this.value)" >
<option value="didnotchoose" selected="selected">Choose</option>
<cfloop list="#variables.shapeList#" index="index">
<option value="#index#">#index#</option>
</cfloop>
</select>
</cfoutput>
</td>
</tr>
</table>
<table>
<tr>
<td>
<cfoutput>
<cfset variables.shapeList = "Standard,Shape,Braid,Pole">
<cfloop list="#variables.shapeList#" index="x">
<div id="#x#">
<cfswitch expression="#x#">
<cfcase value="Shape">
<table>
<tr>
<td width="146">Shapes</td>
<td>
<cfset thisList = ValueList(shapesSelect.SHAPE_NAME)>
<select name="shape_name" class="form-select required" id="edit-field-data-loc-key" onChange="showHide(this.value)">
<option value="didnotchoose" selected="selected">Choose</option>
<cfloop list="#thisList#" index="s">
<option value="#s#"<cfif form.shape_name eq "#s#">selected</cfif>>#s#</option>
</cfloop>
</select>
<div id="start">Starting div</div>
<cfset thisList = ValueList(shapesSelect.SHAPE_NAME)>
<cfloop list="#thisList#" index="l">
<div id="#l#"><img src="/customblinds/webroot/images/#l#.JPG"></div>
</cfloop>
<InvalidTag language="javascript">
function showHide(obj)
{
var showDiv = "##"+obj;
<cfloop list="#thisList#" index="l">
$('###l#').hide();
</cfloop>
$('##start').hide();
//$("div").hide();
$(showDiv).show();
}
<cfloop list="#thisList#" index="l">
$('###l#').hide();
</cfloop>
</script>