Shaun Mccran

My digital playground
 
19
J
U
L
2010

Cross site AJAX HttpRequest problems and how to create a Proxy handler

Most of us are familiar with the AJAX post() and getJSON() methods of remotely calling and passing around data, I use them with abundance when building applications. One thing I had not considered until recently is that all my AJAX Http requests are usually internal to that application, which also means they are on the same server and domain.

I recently jumped into a project where the application spanned 24 domains, and had been developed to use a core component library to help code re use. The problem with this arose when you are on one domain (www.domain1.com) and you want to make a request to a different domain (www.domain2.com). You encounter something called the 'same-Origin' policy.

This article deals with how to create a proxy to handle cross site AJAX http Requests.

[More]

 
29
A
P
R
2010

JQuery Datatables plugin example using a server side data request (coldfusion)

Im my previous article on how to use the JQuery datatables plug I concentrated mainly on the JQuery script, and how to build the AJAX request to receive a JSON response.

In this article I will demonstrate the full application which will include the front end JQuery, building the back end server response and a few tips that I've picked up since implementing the plugin. I am using an MS SQL table filled with UK location data that I also used for a weather webservice, to fill the table.

A full example of this working can be seen here: Data table server side example

[More]

 
23
M
A
R
2010

What does "Invalid Label" mean in a JSON response, and how can I fix it?

I recently build an application that returned a JSON object of data based on a select field value. Whilst I was building this I encountered an error using the JavaScript eval() function on my JSON response. I am using the eval() function to parse a string from my JSON response, but firebug is showing a JavaScript error of "Invalid Label".

This is the code:

view plain print about
1function(data){
2    jsonResponse = eval(data);
3    var src = jsonResponse.DATA;
4    });

After having a Google around it appears that the eval function is interpreting the first item in the JSON response as a label, rather than data. By changing the code like this:

view plain print about
1jsonResponse = eval("(" + data + ")");

We are forcing eval to recognise the data as variable data. Now the JSON to string translation works.

 
22
M
A
R
2010

Creating an image preview using JQuery and a select form field

This article will deal with a user choosing a value from a Select field, and that selection being passed to a JQuery handler. The JQuery handler will perform an AJAX request to a CFC, which will return a JSON value (URL String) that we will use to populate an img html tag.

In this way when you select different options from the select field drop down, the image changes inline, without any page reloads.

[More]

 
15
M
A
R
2010

Using other plug-ins with the JQuery Carousel Plug-in and event issues

This entry examines how the JQuery Carousel object interacts with other Plug-ins, and how to combine those plug-ins with the Carousel functionality. I also cover an issue where the jCarousel plug-in does not apply functionality to non visible elements when the page loads.

[More]

 
25
F
E
B
2010

Using the JQuery dataTables plugin to display dynamic data in tables: part 1

Rather than writing out long winded table code to display your data in a tabulated fashion why not use the dataTables JQuery plugin to do it for you?

In this blog entry I'll be generating tables using a JQuery plugin, but I will also be generating the JQuery code from an XML document.

The theory behind the dataTables JQuery plugin is that when the template loads it makes an AJAX request to a remotely specified template. That template returns a JSON object of data which is formatted and used in a tabular display. This means that you can perfom filtering and sort functions inline, and the JQuery simply re submits the AJAX request, receiving new JSON each time. So no refreshing.

I'll be dealing with the auto generation of the JSON back end in the second part of this article. Here is how I setup the tabular display.

Build a standard html template, including the CSS and JQuery plugins.

view plain print about
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/transitional.dtd">
2<html lang="en-GB">
3<head>
4<InvalidTag http-equiv="Content-Type" content="text/html; charset=iso-8859-1" lang="en">
5<InvalidTag name="language" content="en-GB">
6
7<style type="text/css" title="currentStyle">
8    @import "demo_page.css";
9    @import "demo_table.css";
10</style>
11
12<s/cript type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
13<s/cript type="text/javascript" language="javascript" src="jquery.dataTables.js"></script>

Next we build our JQuery function. I wont go into massive detail about all the parameters and values being passed in here, but it is well documented on http://www.datatables.net/.

view plain print about
1<s/cript type="text/javascript" charset="utf-8">
2$(document).ready(function() {
3                $('#example').dataTable( {
4                    "bProcessing": true,
5                    "bServerSide": true,
6                    "sAjaxSource": "content.cfm",
7                    "aoColumns": [
8{ "sName": "Edit", "sTitle": "Edit", "sWidth":"10%"} ,
9{ "sName": "Band", "sTitle": "Band"} ,
10{ "sName": "Genre","sTitle": "Genre"} ,
11{ "sTitle": "Fake Column"}
12],
13                    "sPaginationType": "full_numbers",
14                    "aaSorting": [[1,'asc']],
15                    "oLanguage": {
16                        "sLengthMenu": "Page length: _MENU_",
17                        "sSearch": "Filter:"
18                    }
19                } );
20            } );
21</script>

The really important column here is the "aoColumns" JSON data block. This specifies what fields are returned from your AJAX call, and parameters they must adhere to.

In this example we are anticipating that we will receive four columns of data back (Edit,Band,Genre and Fake Column).

Lastly we create a table with an ID of "example", as this is what the JQuery is looking for. This table must be formatted in a certain way, as the JQuery plugin will re write the specified elements.

view plain print about
1<table cellpadding="0" cellspacing="0" border="0" class="display" id="example">
2<thead>
3<tr>
4 <th>Edit</th>
5 <th>Band</th>
6 <th>Genre</th>
7 <th>Fake Column</th>
8</tr>
9</thead>
10 <tbody>
11 <tr>
12 <td colspan="3" class="dataTables_empty">Loading data from server</td>
13 </tr>
14 </tbody>
15</table>

The code also contains the header elements that will match the returned column values from the AJAX request. The last part of the table is displayed when the data is loading.

This all works well, but to extend it further I have altered the code to read from an XML document. The XML document Is loaded when the template starts, and the data fields and attributes are read, and looped over to create the JQuery code and table headers. In this way it is a generic table display template, driven from an XML document.

The XML doc:

view plain print about
1<?xml version="1.0"?>
2 <form>
3 <field sName="Edit" source="data" sTitle="Edit" sWidth="10%">Edit</field>
4 <field sName="Band" source="data" sTitle="Band">Band</field>
5 <field sName="Genre" source="data" sTitle="Genre">Genre</field>
6 <field sName="fake column" source="" sTitle="Fake Column">Fake column</field>
7 </form>

Read the XML file and parse it out into an Array:

view plain print about
1<!--- parse the xml file --->
2<cfset variables.xml = XMLParse("test.xml") />
3<!--- <cfdump var="#variables.xml#" label="Raw xml document"> --->
4<cfset variables.fields = XMLSearch(variables.xml,"form/field")>
5<cfset variables.totalRecords = ArrayLen(variables.fields)>

Use something like this to dynamically generate the JQuery and table values:

view plain print about
1<cfoutput>
2<cfloop index="variables.index" from="1" to="#ArrayLen(variables.fields)#">
3 { <cfif variables.fields[variables.index].XmlAttributes.source EQ "data">"sName": "#variables.fields[variables.index].XmlAttributes.sName#",</cfif>
4 <cfif structkeyexists(variables.fields[variables.index].XmlAttributes, 'sTitle')>"sTitle": "#variables.fields[variables.index].XmlAttributes.sTitle#"</cfif>
5 <cfif structkeyexists(variables.fields[variables.index].XmlAttributes, 'sWidth')>,"sWidth":"#variables.fields[variables.index].XmlAttributes.sWidth#"</cfif>
6 } <cfif variables.index NEQ variables.totalRecords>,</cfif>
7</cfloop>
8</cfoutput>
9<!--- table values --->
10
11<cfoutput>
12 <cfloop index="variables.index" from="1" to="#ArrayLen(variables.fields)#">
13 <th align="left">#variables.fields[variables.index].XmlText#</th>
14 </cfloop>
15</cfoutput>

The JSON response is hard coded in this example, so the result will not filter or search. I'll handle that in article two.

There is a full example of this here.

 
20
A
U
G
2009

Connecting Select form fields based on data selections Pt 3

I've been exploring various methods of using JQuery to populate Select form fields. In the previous article I used an intermediary file to act as a handler for the JSON returned object. In this last article I have removed the extra handler template, interfacing directly with the CFC.

Firstly there are some small changes to the JQuery url call.

view plain print about
1<scr/ipt src="jquery-1.2.3.js" type="text/javascript"></script>
2<scr/ipt src="select-chain.js" type="text/javascript" charset="utf-8"></script>
3<scr/ipt type="text/javascript">
4 jQuery.noConflict();
5 jQuery(function () {
6 var type = jQuery('#series');
7 var sp = jQuery('#issueno');
8 var selectedSeries = jQuery('#series').val();
9
10 type.selectChain({
11 target: sp,
12 url: 'jquerySeries.cfc?method=getIssueNos',
13 type: 'post',
14 data: { ajax: true, returnformat: 'plain', series: selectedSeries }
15 }).trigger('change');
16
17 });
18</script>

Now we are directly referencing the CFC. Simply append the function name as a url parameter. In the "DATA" element we place the data we are passing in the form of key value pairs. This will build all the values into the JQuery url, so the final URL would be:

view plain print about
1jquerySeries.cfc?method=getIssueNos&ajax=true&returnformat=plain&series=selectedSeries

At this point I was getting an parse error, until I found the 'returnFormat' value. Coldfusion will return WDDX encoded packets by default, problem was my handler was looking for Json. Adding this value will stop this.

Next we have the same form as before, there are no changes at all: (here for completeness really)

view plain print about
1<cfset variables.series = createObject("component","jquerySeries").getSeries()>
2 <form action="" method="post">
3 <select name="series" id="series">
4 <cfoutput query="variables.series">
5 <option value="#variables.series.intId#">#variables.series.varName#</option>
6 </cfoutput>
7 </select>
8 <select name="issueno" id="issueno">
9 <option></option>
10 </select>
11 <button type="submit">Submit</button>
12 </form>

Lastly there are one or two small changes to our CFC function.

view plain print about
1<cffunction name="getIssueNos" access="remote" output="false" hint="returns related series issue numbers">
2        <cfargument name="series" type="numeric" required="false" hint="Id of the publication">
3        <cfset var result = "">
4
5        <cfquery name="result" datasource="#application.ds#">
6            SELECT [intIssueNo]
7            FROM [dbo].[tbl_cn_series_issueNos]
8            where intSeriesId = <cfqueryparam value="#arguments.series#" cfsqltype="cf_sql_integer">
9        </cfquery>
10        
11        <cfsetting showdebugoutput="false">
12        <cfset ojson = createObject("component","cfjson")>
13        <cfset theresults = ojson.encode(listToArray(valuelist(result.intIssueNo)))>
14        <cfsetting enablecfoutputonly="true">
15    <cfreturn theresults>
16    </cffunction>

The access method has changed, so we add an "access=remote" value to expose the function as a service. Then we serialize the query result into JSON, and return it. This seems like a much more succinct way of doing this.

 
18
A
U
G
2009

Connecting Select form fields based on data selections Pt 2

I want to be able to dynamically change a second select field based on the value of the first select field.

Following on from the cfajaxproxy example I wrote last week, where I discovered I could not use ColdFusion 8 functionality on my live server, I have arrived at a variant solution.

In this example I am using a similar JQuery url request to process the output from a CFC. The first template is the form itself. This includes references to the JQuery libraries and the binding of the response to the form elements. It also builds the url request to the 'request_processor.cfm' file, which handles the CFC.

view plain print about
1<scr/ipt src="jquery-1.2.3.js" type="text/javascript"></script>
2<scr/ipt src="select-chain.js" type="text/javascript" charset="utf-8"></script>
3<scr/ipt type="text/javascript">
4 jQuery.noConflict();
5 jQuery(function () {
6 var type = jQuery('#series');
7 var sp = jQuery('#issueno');
8
9 type.selectChain({
10 target: sp,
11 url: 'request_processor.cfm',
12 type: 'post',
13 data: { ajax: true }
14 }).trigger('change');
15
16 });
17</script>

Next build a simple form, and populate the first select field with data from a method.

view plain print about
1<cfif not structisempty(form)>
2 <cfdump var="#form#">
3<cfelse>
4 <cfset variables.series = createObject("component","jquerySeries"). getSeries()>
5 <form action="" method="post">
6 <select name="series" id="series">
7 <cfoutput query="variables.series">
8 <option value="#variables.series.intId#">#variables.series.varName#</option>
9 </cfoutput>
10 </select>
11 <select name="issueno" id="issueno">
12 <option></option>
13 </select>
14 <button type="submit">Submit</button>
15 </form>
16</cfif>

Next is the intermediately file that handles the data manipulation, this is triggered when the user chooses an option from the first select field. It passes through the selected value, and returns the query object. This is then serialised using the cfJson object, to return the data in Json. If you do anything like this remember to watch your debug output, it was destroying my Json response for a good ten minutes before I remembered to turn it off. Doh!

view plain print about
1<cfsetting showdebugoutput="false">
2<cfsetting enablecfoutputonly="true">
3<cfparam name="form.series" default="8">
4<cfset variables.issues = createObject("component","jquerySeries").getIssueNos(series=form.series)>
5<cfset ojson = createObject("component","cfjson")>
6<cfset theresults = ojson.encode(listToArray(valuelist(variables.issues.intIssueNo)))>
7<cfoutput>#theresults#</cfoutput>

Finally a CFC that performs the database functions. This is a pretty straight forward CFC that performs two database queries, the second based on an id passed in from the first.

view plain print about
1<cfcomponent>
2
3    <cffunction name="getSeries" output="false" hint="Returns publication series">
4        <cfset var result = "">
5
6    <cfquery name="result" datasource="#application.ds#">
7        SELECT [intId],[varName]
8        FROM [dbo].[table]
9        Where intActive = '1'
10        Order by varName
11    </cfquery>
12
13    <cfreturn result>
14    </cffunction>
15
16    <cffunction name="getIssueNos" output="false" hint="returns related series issue numbers">
17        <cfargument name="series" type="numeric" required="false" hint="Id of the publication">
18        <cfset var result = "">
19
20        <cfquery name="result" datasource="#application.ds#">
21            SELECT [intIssueNo]
22            FROM [dbo].[table]
23            where intSeriesId = <cfqueryparam value="#arguments.series#" cfsqltype="cf_sql_integer">
24        </cfquery>
25
26    <cfreturn result>
27    </cffunction>
28</cfcomponent>

Once you have these elements hooked up you'll see that the response from the first select field changes the values in the second field. You can download a rar'd version of the code base here.

This works well, but I'm not massively happy about the 'remote_processor' file. I think I'll see if there is a way of directly calling the CFC, and moving the JSON serialisation into the functions.

More Entries


This content is purely my opinon, any offence or errors are unintentional, please comment your views appropriately
Site Credits
Aggregated by ColdfusionBloggers.org Powered by Coldfusion

Technology & Science Blogs - BlogCatalog Blog Directory Blog Directory & Search engine