|
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!).
|
Function for getting the last modified date of a template |
Whilst looking at creating dynamic Sitemaps for Google bot spidering I found that I needed to populate an XML node with the last modified date of the templates. I figured there must be a programmatic way of doing this, so after some searching around this is what I ended out with:
This creates a java object, using the date and file utilities we can use 'getcurrenttemplatepath()' to provide the path data, finally referencing the lastModified property.
A handy and relatively quick way of getting the last modified date.
It is a bit of a mouthful though, so might be easier to create it as a handy referencable object:
2 <cfargument name="file" type="string" required="yes" hint="File to get mod date">
3 <cfset var mod_time = now()>
4
5 <cfif fileexists(arguments.file)>
6 <cfset mod_time = createObject("java", "java.util.Date").init(createObject("java", "java.io.File").init(arguments.file).lastModified())>
7 </cfif>
8
9 <cfreturn mod_time>
10</cffunction>
Then you can just do:
|
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!
|
Geo coding Latitude and Longitude address in coldfusion using CFhttp |
One piece of recently functionality to a site I'm writing is the ability to look up places on a Google powered map.
There are a variety of ways to insert a Google map into your site, but the first real hurdle is the lookup code.
Google does not use an address to position its map, it uses the Latitude and Longitude co-ordinates to place the map area around the desired location.
Google has pretty extensive documentation around this here:
http://code.google.com/apis/maps/documentation/geocoding/index.html
Rather than translate the locations on the fly on a per-hit basis I thought I would perform the lookup when the record is submitted to the database, that way I can cut down the number of google hits, and just reference the local data. Google also prefers this method, as it is less process intensive on their end of things.
First you need an API key:
http://code.google.com/apis/maps/signup.html
This application already has methods for setting the data in a table, so I am simply going to call another packaged method to calculate the latitude and longitude, and store them in the table with the other data.
2 <cfargument name="address" displayName="Address to Geo" type="string" hint="String of the address to Geo code" required="true" />
3 <cfset var geoDetails = structNew()>
4
5 <cfset var apiKey = "Your API key here">
6
7 <!--- initial string --->
8 <cfset var requestString = "http://maps.google.com/maps/geo?">
9
10 <!--- q= address to geo code --->
11 <cfset requestString = requestString & "q=28+Morley+Street,Swindon,SN1+1SG" & "&">
12
13 <!--- key = API key --->
14 <cfset requestString = requestString & "key=" & apiKey & "&">
15
16 <!--- sensor = does the requestor have a location sensor? --->
17 <cfset requestString = requestString & "sensor=false" & "&">
18
19 <!--- output = output format --->
20 <cfset requestString = requestString & "output=csv" & "&">
21
22 <!--- oe = output encoding format --->
23 <cfset requestString = requestString & "oe=utf8" & "&">
24
25 <!--- gl= Country code pointer --->
26 <cfset requestString = requestString & "gl=uk">
27
28 <cfhttp url="#requestString#" method="get" result="response"></cfhttp>
29
30 <!--- returns 4 elements statuscode/accuracy/lat/long
31 Higher accuracy is better --->
32 <cfset geoDetails.status = listGetAt(response.filecontent,'1',',')>
33 <cfset geoDetails.accuracy = listGetAt(response.filecontent,'2',',')>
34 <cfset geoDetails.lat = listGetAt(response.filecontent,'3',',')>
35 <cfset geoDetails.long = listGetAt(response.filecontent,'4',',')>
36
37 <cfreturn geoDetails />
38 </cffunction>
As you can see from above, I am simply creating a text string URL, and using cfhttp to GET the result from http://maps.google.com/maps/geo?
The screenshot below show the returned responses, and the http status code.
The result is parsed into a struct and returned to the parent function to be stored. Far less overhead than doing this for every map call.
Please note that this is far more heavily commented for Blog purposes. Now to actually call the service using the lat and long variables stored, but thats another article.