|
Connecting Select form fields based on data selections Pt 1 |
Whilst building a new form I discovered that I needed two select fields, one that contained a series of publication titles, and the second that contained the Issue numbers of whatever title was selected in the first field.
IE two selects, with the first controlling the seconds data.
I had a search around and it seems like there are many ways to do this, this by far seems to be the best, but it has a fatal flaw (detailed at the end).
Start off by creating a function call to setup your initial state. This will set the default value of the first select field, and populate the second field with its options.
2<!--- Set the default Series --->
3<cfset defaultSeries = 7>
4
5<scri pt type="text/javascript">
6var done = false;
7function SelectDefault(x,val) {
8 if(!done) {
9 var dd = document.getElementById('intId');
10 for(var i = 0; i < dd.length; i++){
11 if(dd.options[i].value == val){
12 dd.selectedIndex = i;
13 }
14 }
15 done = true;
16 }
17}
18</scri pt>
Next create the form, and use the cfajaxproxy to bind the default values set above.
The form itself is a pair of cfselects, with the values bound to the response from a CFC (Series). I really like the way the notation works with this, the cfc:Name . function is really intuitive.
Notice how the binding on the second cfselect is passing through the value from the first 'intId' in this example. This is the argument passed to the CFC.
2<cfajaxproxy bind="javascript:SelectDefault({intId},#defaultSeries#)">
3
4<cfform name="exampleform" method="post">
5
6<cfselect name="intId" id="intId" value="intId" display="varName" bindonload="true" bind="cfc:Series.GetIssues()"/>
7<cfselect name="issueNo" id="issueNo" value="intIssueNo" display="intIssueNo" bind="cfc:Series.GetIssueNos({intId})"/>
8<cfinput type="submit" name="submit" value="Submit"/>
9</cfform>
10</body>
11</html>
So that is our form. The next code block is the CFC. It is a relatively straight forward CFC with two functions, each returning a list of data. The second requires an argument passed in from the cfselect above.
2 <cffunction name="GetIssues" access="remote" returntype="query">
3
4 <cfquery name="data" datasource="#application.dsn#">
5 SELECT [intId],[varName],
6FROM [dbo].table
7 Order by varName
8 </cfquery>
9
10 <cfreturn data>
11 </cffunction>
12
13 <cffunction name="GetIssueNos" access="remote" returntype="query">
14 <cfargument name="intId">
15 <cfquery name="data" datasource="#application.dsn#">
16 SELECT [intIssueNo]
17 FROM [dbo].table
18 where intSeriesId = <cfqueryparam value="#arguments.intId#" cfsqltype="cf_sql_integer">
19 </cfquery>
20 <cfreturn data>
21
22 </cffunction>
23
24</cfcomponent>
This just returns two different query objects. When this is all hooked up it works fantastically. Changing the first select changes the issue numbers in the second select.
My problem lies in the fact that this is all ColdFusion 8 functionality. Both cfajaxproxy and cfselect are coldfusion server version 8 tags. My hosting company is still using version 7! Which I discovered when I rolled this code out. (doh!)
So I have to find another solution, which follows shortly.
N.B. Thanks to several of Ben Forta and Ben Nadel's blog posts around similar subjects for guidance on this, they got me over a few stumbling blocks.
|
Writing back to a multi select box using javascript |
During the building of an online form I discovered that there was the need for a user to select multiple values from a select form field. This is done easily enough using multiple="true". What I then found was that I wanted them to be able to add more options to the select field, preferably without reloading the entire template. These options would then also be 'selected' on being added to the select box. Below is a test script demonstrating this.
Initially I created a standard select form field, and populate it with a simulated query.
2<cfset variables.qOptions = QueryNew( "id, name" ) />
3
4<cfset QueryAddRow( variables.qOptions ) />
5<cfset variables.qOptions[ "id" ][ variables.qOptions.RecordCount ] = "1" />
6<cfset variables.qOptions[ "name" ][ variables.qOptions.RecordCount ] = "Value 1" />
7
8<cfset QueryAddRow( variables.qOptions ) />
9<cfset variables.qOptions[ "id" ][ variables.qOptions.RecordCount ] = "2" />
10<cfset variables.qOptions[ "name" ][ variables.qOptions.RecordCount ] = "Value 2" />
11
12<cfset QueryAddRow( variables.qOptions ) />
13<cfset variables.qOptions[ "id" ][ variables.qOptions.RecordCount ] = "3" />
14<cfset variables.qOptions[ "name" ][ variables.qOptions.RecordCount ] = "Value 3" />
15
16<cfset QueryAddRow( variables.qOptions ) />
17<cfset variables.qOptions[ "id" ][ variables.qOptions.RecordCount ] = "4" />
18<cfset variables.qOptions[ "name" ][ variables.qOptions.RecordCount ] = "Value 4" />
19<select name="item" id="item" class="input_text" size="4" multiple="true">
20<cfloop query="variables.qOptions">
21 <option value="#variables.qOptions.id#">#variables.qOptions.name#</option>
22 </cfloop>
23</select>
Next we will add the form button that allows the user to add new values to the select field. The 'Add' button invokes the javascript function AddItem().
So a user enters their new item into the text box, and it is inserted into the select field drop down, and automatically selected.
2
3 var newItemValue = document.getElementById("newItem").value;
4 var list = document.getElementById('item');
5 var startNewNum = document.getElementById('item').options.length;
6
7 var newOption = new Option((newItemValue), newItemValue);
8
9 // do it if there is a value
10 if(newItemValue.length !== 0) {
11
12 newOption.selected = true;
13 list.options.add(newOption);
14
15 newItem.value = "";
16 window.alert('You new value has been added');
17
18 }
19 }
The javascript above gets the new item value, and inserts it as the last item in the select list. There is also a check to see if there is any text value in the form field. Just to round it off I remove the text field value, and alert the user.
There is probably a shinier way of doing this in something like JQuery, but I'm not that up to speed on that. It would be interesting to see an example though. (hint!).
|
Firefox not displaying Google maps generated images |
My latest Google maps lookup template was not working in Firefox 3.n. It was working fine in IE 8 (and 8) so I thought maybe IE was compensating for some shaky JavaScript code, and 'working out' what I was trying to do and fixing it for me.
After spending half an hour painstaking going through my Google JavaScript and removing everything out of my FuseBox framework, just in case anything was mysteriously interfering, I was at a dead end.
A quick flick around online and it seems that there is a setting in FireFox that blocks this sort of functionality.
- Type 'about:config' (without quotes) in the browser's address bar.
- Type 'image' (without quotes) in the 'Filter' field.
- Verify that 'dom.disable_image_src_set' is set to FALSE.
- Verify that 'permissions.default.image' is set to 0 (the default setting).
For some reason in my FireFox installation the 'permissions.default.image' was set to 1, which blocks the function return from Google.
Google has a tech note on it here:
http://maps.google.com/support/bin/answer.py?answer=18529&topic=10789
It is really frustrating when 'controls' are set outside of the development environment. Now to put all my code back!
|
Google Analytics tracking across multiple domains |
I recently came across an issue where an online application was crossing several domains during the customer experience, and the Google Analytics tracking was losing the referrer when they left the originating domain.
The usual Google Analytics tracking code is:
2var tracker = _gat._getTracker("#GACode#");
3 tracker._setDomainName("none");
4 tracker._setAllowLinker(true);
5 tracker._initData();
6 tracker._trackPageview();
7</script>
With the addition of two extra lines:
2tracker._setAllowLinker(true);
We can force each link to carry the cookie data over to the next domain, maintaining the user data throughout.
There is one other small change. Any href that transitions from one domain to the next has to include an onclick event that tells it to use a tracker method.
We need to do something similar to form submissions:
In this way the user cookie is maintained across multiple domains.