<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Orange is my favorite color &#187; jQuery</title>
	<atom:link href="http://www.ghidinelli.com/c/webinternet/jquery/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ghidinelli.com</link>
	<description></description>
	<lastBuildDate>Wed, 04 Jan 2012 08:06:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.3</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Javascript for Mobile</title>
		<link>http://www.ghidinelli.com/2011/09/06/javascript-for-mobile</link>
		<comments>http://www.ghidinelli.com/2011/09/06/javascript-for-mobile#comments</comments>
		<pubDate>Tue, 06 Sep 2011 17:49:15 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1344</guid>
		<description><![CDATA[Packt Publishing's "jQuery Mobile First Look" arrives at a timely juncture]]></description>
			<content:encoded><![CDATA[<p>Richard Dias from Packt Publishing dropped me a note recently asking if I was interested in taking a look at their latest jQuery title: <a href="http://link.packtpub.com/qhDdWa">jQuery Mobile First Look</a>.  The timing is perfect since we just had a team meeting to discuss how we wanted to continue evolving <a href="http://www.motorsportreg.com">MotorsportReg.com</a> for mobile consumption.  About 10% of our usage is on mobile devices and while our HTML/CSS system today is pretty solid on iOS and Android devices, we want to improve the experience.   We already use jQuery extensively on MSR so <a href="http://jquerymobile.com/">jQuery Mobile</a> is a leading candidate before we even crack the book.  I&#8217;m hoping HTML5 matures quickly so we can leverage the skills and technologies we&#8217;re already using rather than go down the path of platform-specific applications.  Once I dig in I&#8217;ll post a short review of the book.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/09/06/javascript-for-mobile/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Batch-change jQuery Quicky</title>
		<link>http://www.ghidinelli.com/2010/01/20/batch-change-jquery-highlight-checked-boxes</link>
		<comments>http://www.ghidinelli.com/2010/01/20/batch-change-jquery-highlight-checked-boxes#comments</comments>
		<pubDate>Thu, 21 Jan 2010 00:32:17 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1013</guid>
		<description><![CDATA[One line of jQuery makes a batch change user experience a little safer]]></description>
			<content:encoded><![CDATA[<p>Had a user call in &#8211; she accidentally deleted half of her attendees in our web app.  She thought she was deleting two but instead hit the &#8220;toggle all&#8221; and ignored the pop-up confirmation dialog which hosed half of her data the afternoon before she needs to deliver it to her team.  Awesome.</p>
<p>What does this have to do with jQuery?  Well, while I&#8217;m waiting for a database dump in the background to finish downloading so I can extract some data, I whipped up a UI enhancements with a few lines of jQuery that might help someone else:</p>
<h2>Highlight table rows with checked checkbox in a column</h2>
<p>What if we highlighted the selected rows when the confirmation dialog pops up?  It would be one more way of pointing out what is about to happen.  Here&#8217;s what it looks like now:</p>
<p><a href="http://www.ghidinelli.com/wp-content/uploads/2010/01/batchcange.png"><img src="http://www.ghidinelli.com/wp-content/uploads/2010/01/batchcange-300x143.png" alt="batch change demonstration" title="batch change demonstration" width="300" height="143" class="aligncenter" /></a></p>
<p>In conjunction with Dan Switzer&#8217;s qForms library&#8230; </p>
<pre><code>objForm.onSubmit = function() {
	// only ask for confirmation when they change more than 1
	if (objForm.uid.getValue().indexOf(",") != -1)
	{
		$('input[name="uid"]:checked')
			.parents('tr')
			.css('backgroundColor', '#fc0');
		var res = confirm('You are about to make a batch change in registration status.\n\nAre you sure you want to continue?');
		if (!res)
			$('input[name="uid"]:checked')
				.parents('tr')
				.css('backgroundColor', '#fff');

		return res;
	}
	else
		return true;
};</code></pre>
<p>The checkboxes are all named &#8220;uid&#8221; so when it&#8217;s submitted to the server I get a list of IDs to work with.  I&#8217;m using jQuery to select all of the checked checkboxes named &#8220;uid&#8221;, then get their parent &lt;tr&gt; tags and then update their backgrounds to be a bright gold color while the confirmation dialog asks them if they&#8217;re really, really, <em>seriously</em> sure they want to do this.  If they click cancel, we restore the background back to white.</p>
<p>My download is about done, so time to restore!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2010/01/20/batch-change-jquery-highlight-checked-boxes/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Flowplayer plugin for Codex wiki</title>
		<link>http://www.ghidinelli.com/2009/08/13/flowplayer-plugin-for-codex-wiki</link>
		<comments>http://www.ghidinelli.com/2009/08/13/flowplayer-plugin-for-codex-wiki#comments</comments>
		<pubDate>Fri, 14 Aug 2009 00:35:14 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[codex]]></category>
		<category><![CDATA[coldbox]]></category>
		<category><![CDATA[flowplayer]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[wiki]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=899</guid>
		<description><![CDATA[Embed video in your Codex wiki with the excellent YouTube-like Flowplayer and this plugin!]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m busy setting up a <a href="http://www.codexwiki.org">Codex Wiki</a> as a help system and needed the ability to embed screencast tutorials inline.  There is a flash embed plugin but I wanted something more Youtube-like that didn&#8217;t download the video unless the user clicks on it in order to save bandwidth and keep the page loading quickly as we plan to have <em>lots</em> of videos.</p>
<p>Cue <a href="http://www.flowplayer.org">FlowPlayer</a> and a short plugin I wrote.  FlowPlayer is pretty impressive&#8230; it&#8217;s a SWF and a JS file you drop into your site and it leverages the jQuery built into Codex.  If you want to use it in conjunction with Codex, you can use my plugin below.  The wiki syntax looks like:</p>
<pre><code>{{{ev url="http://url/to/your/movie.flv"
         height="300"
         width="400"
         alt="My alternate text description"
         splash="http://url/to/a/static/splash/screen.jpg"}}}</code></pre>
<p>That code will give you a player that looks roughly like:</p>
<p><img src="http://www.ghidinelli.com/wp-content/uploads/2009/08/evembed.png" alt="Embed Video plugin for Codex Wiki example" title="Embed Video plugin for Codex Wiki example" width="421" height="321" class="aligncenter" /></p>
<p>This was my first plugin for a <a href="http://www.coldboxframework.org">Coldbox</a> application and it was pretty easy to take an existing one and create another.  It&#8217;s also the first Coldbox application I&#8217;ve worked with and so far I&#8217;m pretty impressed.  I am looking at giving it a test drive for a mini app I have to build later this month for club elections and surveys.</p>
<p>Just drop this into your codex/plugins/wiki directory as ev.cfc.  The way I&#8217;ve written the code, you can have multiple players per page as they&#8217;ll all be tagged with a class &#8220;flowplayer&#8221;:</p>
<pre><code>&lt; !-----------------------------------------------------------------------
********************************************************************************
Copyright 2009 by Brian Ghidinelli (http://www.ghidinelli.com)
********************************************************************************
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
********************************************************************************
$Build Date: @@build_date@@
$Build ID:	@@build_id@@
********************************************************************************
-----------------------------------------------------------------------&gt;
&lt;cfcomponent name="EmbedVideo"
			 hint="A wiki plugin to embed video using FlowPlayer"
			 extends="codex.model.plugins.BaseWikiPlugin"
			 output="false"
			 cache="false"&gt;

&lt; !------------------------------------------- CONSTRUCTOR -------------------------------------------&gt;	

    &lt;cffunction name="init" access="public" returntype="ev" output="false"&gt;
		&lt;cfargument name="controller" type="any" required="true"&gt;
		&lt;cfscript&gt;
  		super.Init(arguments.controller);
  		setpluginName("EmbedVideo");
  		setpluginVersion("1.0");
  		setpluginDescription("A video embedding plugin that uses FlowPlayer");
  		setPluginAuthor("Brian Ghidinelli");
  		setPluginAuthorURL("http://www.ghidinelli.com");
  		setPluginURL("http://www.ghidinelli.com");

  		//Return instance
  		return this;
		&lt;/cfscript&gt;
	&lt;/cffunction&gt;

&lt; !------------------------------------------- PUBLIC -------------------------------------------&gt;	

    &lt; !--- today ---&gt;
	&lt;cffunction name="renderit" output="false" access="public" returntype="string" hint="This plugin will embed a video on the page using FlowPlayer"&gt;
		&lt;cfargument name="url"  required="true" type="string" hint="The url to the video to display" /&gt;
		&lt;cfargument name="height" type="numeric" required="false" default="300" /&gt;
		&lt;cfargument name="width" type="numeric" required="false" default="400" /&gt;
		&lt;cfargument name="splash" type="string" required="false" default="" /&gt;
		&lt;cfargument name="alt" type="string" required="false" default="" /&gt;

		&lt;cfset var event = getController().getRequestService().getContext() /&gt;
		&lt;cfset var content = "" /&gt;

		&lt; !--- use a jquery onready block ---&gt;
		&lt;cfoutput&gt;
		&lt;cfsavecontent variable="content"&gt;
			<a href="#arguments.url#"
			   class="flowplayer"
			   style="width: #arguments.width#px; height: #arguments.height#px;">&lt;cfif len(arguments.splash)&gt;&lt;img src="#arguments.splash#" height="#arguments.height#" width="#arguments.width#" alt="&lt;cfif len(arguments.alt)&gt;#HTMLEditFormat(alt)#&lt;cfelse&gt;Click to start playing&lt;/cfif&gt;" /&gt;&lt;/cfif&gt;</a>
			&lt;script language="javascript" type="text/javascript"&gt;
				$(document).ready(function()
				{
					flowplayer("a.flowplayer", "/js/flowplayer/flowplayer-3.1.2.swf");
				});
			&lt;/script&gt;
		&lt;/cfsavecontent&gt;
		&lt;/cfoutput&gt;

		&lt;cfreturn content /&gt;
	&lt;/cffunction&gt;

&lt;/cfcomponent&gt;</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2009/08/13/flowplayer-plugin-for-codex-wiki/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to bypass cross-domain restrictions when developing AJAX applications</title>
		<link>http://www.ghidinelli.com/2008/12/27/how-to-bypass-cross-domain-restrictions-when-developing-ajax-applications</link>
		<comments>http://www.ghidinelli.com/2008/12/27/how-to-bypass-cross-domain-restrictions-when-developing-ajax-applications#comments</comments>
		<pubDate>Sat, 27 Dec 2008 20:08:33 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Dojo Toolkit]]></category>
		<category><![CDATA[Research/HOWTO]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[ext]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[xmlhttprequest]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=461</guid>
		<description><![CDATA[I have been working with a contractor in India recently on a Javascript project using Ext.  I wanted to outsource the front-end development since we have extensive APIs that would take an outside developer longer to get up to speed on.  Due to PCI DSS and general security practices however, we can&#8217;t just [...]]]></description>
			<content:encoded><![CDATA[<p>I have been working with a contractor in India recently on a Javascript project using Ext.  I wanted to outsource the front-end development since we have extensive APIs that would take an outside developer longer to get up to speed on.  Due to PCI DSS and general security practices however, we can&#8217;t just let the contractor log in and push code or make changes to our development server.  In fact, we didn&#8217;t even give him Subversion access meaning he would have to code against our data services remotely.</p>
<h2>The Setup</h2>
<p>Development server at dev.domain.com.  Off-site developer building an application on his laptop and connecting his AJAX/xmlHttpRequest calls to dev.domain.com.</p>
<h2>The Problem</h2>
<p>Browsers restrict cross-domain requests for security purposes.  So Javascript at http://localhost can&#8217;t retrieve data from a remote API like http://dev.domain.com.  In Firefox + Firebug, you would see the following:</p>
<p><code>Error: uncaught exception: Permission denied to call method XMLHttpRequest.open</code></p>
<p>There is a <a href="http://www.zachleat.com/web/2007/08/30/cross-domain-xhr-with-firefox/">hack for Firefox</a> but that doesn&#8217;t help you with IE, Safari or Chrome.   We started out this way but when it came time to deploy we found <a href="http://www.ghidinelli.com/2008/12/18/webkit-fail-on-javascript-indented-with-spaces">issues with Safari and Chrome</a>.  </p>
<p>These were things we could have detected much earlier in the development cycle had the Javascript developer been able to test in those browsers.  It was a big mistake on our part to delay the cross-browser testing and it&#8217;s a testament to the stability of the <a href="http://www.extjs.com">Ext components</a> that we didn&#8217;t have 10,000 other issues.</p>
<h2>The Solution</h2>
<p>If you&#8217;re developing with Apache, the answer is quite simple actually: use a reverse proxy.  Apache&#8217;s <a href="http://httpd.apache.org/docs/2.0/mod/mod_proxy.html">mod_proxy</a> will take a request for something like &#8220;/foo&#8221; and actually tunnel the request to some remote destination like &#8220;http://dev.domain.com/bar&#8221;.  The end result is that your web browser thinks you&#8217;ve made a call to http://localhost/foo but in reality you&#8217;re sending and retrieving data from a remote server.  Security implications solved!</p>
<p>I searched for a long time but never found an intersection between AJAX development, cross-domain xmlHttpRequest restrictions and Apache&#8217;s mod_proxy.  It wasn&#8217;t until I thought, &#8220;hey, that might work&#8221; and started searching specifically for reverse proxy details did I <a href="http://publib.boulder.ibm.com/infocenter/wsmashin/v1r0/index.jsp?topic=/com.ibm.websphere.sMash.doc/core/zero.core/docs/en/ProxyConfiguration.html">turn up an example</a>.</p>
<h2>Apache Configuration</h2>
<p>This is a pretty basic Apache feature &#8211; first you will need to load the required modules:</p>
<pre><code>LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so</code></pre>
<p>Let&#8217;s assume that I want to access a file at http://dev.domain.com/remote/api.php.  You would put all of the following into a &lt;VirtualHost&gt;:</p>
<pre><code># start mod_rewrite
RewriteEngine On

ProxyRequests Off
&lt;Proxy&gt;
	Order deny,allow
	Allow from all
&lt;/Proxy&gt;

ProxyPass /apitest/ http://dev.domain.com/remote/api/
ProxyPassReverse /apitest/ http://dev.domain.com/remote/api/
RewriteRule ^/apitest/(.*)$ /remote/api/$1 [R]</code></pre>
<p>Restart Apache and make a browser request to http://localhost/apitest/api.php and you should receive a response from the remote server at http://dev.domain.com/remote/api/api.php.  The RewriteRule will pass along any query-string parameters too.  Done!</p>
<p>If you use IIS instead of Apache, you should be able to do something similar with ISAPI_REWRITE to accomplish the same functionality.  This is also applicable to other technologies like <a href="http://www.adobe.com/products/flex/">Adobe Flex</a> or Flash which also have cross-domain restrictions.</p>
<p>The advantage over other solutions like a vanilla proxy server or server-side script that translates the request for you is that it requires few, if any, changes to your code.  It&#8217;s also payload-agnostic so it will work with any number of remote services without care for the request or response format.  </p>
<p>There&#8217;s one final tweak we could make so our development environment mirrors our staging and production servers.  If the final endpoint for the Javascript will be:</p>
<p><code>http://dev.domain.com/service/foo?var=value</code></p>
<p>Then we could use the same relative URL &#8220;/service/foo?var=value&#8221; and make our reverse proxy mirror that structure:</p>
<pre><code>ProxyPass /service/ http://dev.domain.com/service/
ProxyPassReverse /service/ http://dev.domain.com/service/ </code></pre>
<p>Now there is no change necessary in the Javascript; just make your request to &#8220;/service/foo?var=value&#8221; on either localhost or dev.domain.com and the browser will be properly routed to the right destination without running into any security restrictions!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2008/12/27/how-to-bypass-cross-domain-restrictions-when-developing-ajax-applications/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tricking serializeJSON to treat numbers as strings</title>
		<link>http://www.ghidinelli.com/2008/12/19/tricking-serializejson-to-treat-numbers-as-strings</link>
		<comments>http://www.ghidinelli.com/2008/12/19/tricking-serializejson-to-treat-numbers-as-strings#comments</comments>
		<pubDate>Fri, 19 Dec 2008 19:05:17 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[ext]]></category>
		<category><![CDATA[json]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=445</guid>
		<description><![CDATA[Quick tip for anyone using ColdFusion&#8217;s serializeJSON routine for Javascript applications.  The type conversion from CF to JSON is finicky and there are times when you need more finely grained control.  Specifically using an Ext combobox, we ran into an issue where an &#60;option&#62; value of 0 was treated as false preventing selection [...]]]></description>
			<content:encoded><![CDATA[<p>Quick tip for anyone using ColdFusion&#8217;s <a href="http://livedocs.adobe.com/coldfusion/8/functions_s_03.html">serializeJSON</a> routine for Javascript applications.  The type conversion from CF to JSON is finicky and there are times when you need more finely grained control.  Specifically using an Ext combobox, we ran into an issue where an &lt;option&gt; value of 0 was treated as false preventing selection of that item.</p>
<p>SerializeJSON encodes numeric values as floats so 0 becomes 0.0, 1 becomes 1.0, and so on.  The solution is to pass the combobox a string (&#8217;0&#8242;) instead of a number (0).  While JavaCast and other techniques failed, it is possible by putting a <em>leading</em> space on your numeric value:</p>
<p><code>&lt;cfset records["someValue"] = ' 0' /&gt;<br />
&lt;cfreturn serializeJSON(records) /&gt;</code></p>
<p>The result is {&#8221;someValue&#8221;: &#8221; 0&#8243;} which Javascript (or at least Ext&#8217;s combobox) handles just fine.  Nice little trick to have in the toolbox when you need to treat numeric data like strings.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2008/12/19/tricking-serializejson-to-treat-numbers-as-strings/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Control JSON formatting with Coldspring Remote Proxy</title>
		<link>http://www.ghidinelli.com/2008/11/21/control-json-formatting-with-coldspring-remote-proxy</link>
		<comments>http://www.ghidinelli.com/2008/11/21/control-json-formatting-with-coldspring-remote-proxy#comments</comments>
		<pubDate>Fri, 21 Nov 2008 15:18:50 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=277</guid>
		<description><![CDATA[I&#8217;m building a series of APIs that bypass Model-Glue for use by Javascript applications using jQuery and EXT.  I wired the whole deal up using the super-cool Remote Proxy Beans.  When it came time to request JSON back from the CFC using remote.cfc?returnFormat=json, there were four problems:

Extraneous whitespace being returned
Content-type was understood by [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m building a series of APIs that bypass Model-Glue for use by Javascript applications using jQuery and EXT.  I wired the whole deal up using the super-cool <a href="http://www.coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=remote">Remote Proxy Beans</a>.  When it came time to request JSON back from the CFC using remote.cfc?returnFormat=json, there were four problems:</p>
<ol>
<li>Extraneous whitespace being returned</li>
<li>Content-type was understood by Firefox, meaning it was <a href="http://jibbering.com/blog/?p=514">potentially insecure</a></li>
<li>Keys were all being forced upper-case which is plain ugly.</li>
<li>Integers are being represented as floats which is a <a href="http://livedocs.adobe.com/coldfusion/8/functions_s_03.html">feature, not a bug</a> (see comments at bottom)</li>
</ol>
<p>To solve these problems, I used Coldspring&#8217;s aspect oriented programming (AOP) and wrote a custom around advice that I applied to my remote proxy to better control the JSON formatting for the client.</p>
<h2>jsonAroundAdvice.cfc</h2>
<p>The following Around Advice eliminates the built-in ?returnFormat=json support in a remote CFC in favor of more explicit conversion:</p>
<pre><code>&lt;cfcomponent output="false" name="jsonAroundAdvice" extends="coldspring.aop.MethodInterceptor"&gt;

&lt;cffunction name="invokeMethod" access="public" returntype="any"&gt;
	&lt;cfargument name="mi" type="coldspring.aop.MethodInvocation" required="true" /&gt;

	&lt;cfset var record = structNew() /&gt;

	&lt;cftry&gt;
		&lt;!--- just pass results straight through ---&gt;
		&lt;cfset record = arguments.mi.proceed() /&gt;

		&lt;cfcatch type="any"&gt;
			&lt;cfset record["data"] = "Serialization failed" /&gt;
			&lt;cfset record["result"] = false /&gt;
		&lt;/cfcatch&gt;
	&lt;/cftry&gt;

	&lt;!--- control output, forcing json ---&gt;
	<strong>&lt;cfset URL.returnFormat = "plain" /&gt;
	&lt;cfheader name="Access-Control" value="allow &lt;*&gt;" /&gt;
	&lt;cfcontent reset="true" type="application/json"&gt;&lt;cfreturn serializeJson(record) /&gt;&lt;cfabort /&gt;</strong>

&lt;/cffunction&gt;
&lt;/cfcomponent&gt;</code></pre>
<p>Basically this code takes any results from the actual method that was called and creates a Javascript object with two keys, data and result, that are serialized and returned with a proper header.  We set the URL.returnFormat = &#8220;plain&#8221; so we can override any parameter passed by the user to the method.  Note that we can use the CF8 SerializeJSON method or we could use Epiphantastic&#8217;s <a href="http://www.epiphantastic.com/cfjson/">CFJSON.cfc</a>.  Only the latter, in my experience, will solve the decimal formatting of integers (#4 in my list above).</p>
<h2>Coldspring Configuration</h2>
<p>To complete the example, this is the Coldspring configuration required to set up my remote proxy:</p>
<pre><code><strong>&lt;bean id="jsonAroundAdvice" class="model.aop.jsonAroundAdvice" /&gt;
&lt;bean id="jsonAdvisor" class="coldspring.aop.support.NamedMethodPointcutAdvisor"&gt;
	&lt;property name="advice"&gt;&lt;ref bean="jsonAroundAdvice" /&gt;&lt;/property&gt;
	&lt;property name="mappedNames"&gt;&lt;value&gt;*&lt;/value&gt;&lt;/property&gt;
&lt;/bean&gt;</strong>

&lt;bean id="remoteFormService" class="coldspring.aop.framework.RemoteFactoryBean" lazy-init="false"&gt;
	&lt;property name="target"&gt;&lt;ref bean="formService" /&gt;&lt;/property&gt;
	&lt;property name="serviceName"&gt;&lt;value&gt;remoteFormService&lt;/value&gt;&lt;/property&gt;
	&lt;property name="relativePath"&gt;&lt;value&gt;/myMapping/myDirectory&lt;/value&gt;&lt;/property&gt;
	&lt;property name="beanFactoryName"&gt;&lt;value&gt;cs&lt;/value&gt;&lt;/property&gt;
	&lt;property name="interceptorNames"&gt;
		&lt;list&gt;
			&lt;!-- run in reverse order; or think of first being "around" second being "around" third --&gt;
			<strong>&lt;value&gt;jsonAdvisor&lt;/value&gt;</strong>
			&lt;value&gt;authorizationAdvisor&lt;/value&gt;
			&lt;value&gt;authenticationAdvisor&lt;/value&gt;
		&lt;/list&gt;
	&lt;/property&gt;
	&lt;property name="remoteMethodNames"&gt;&lt;value&gt;*&lt;/value&gt;&lt;/property&gt;
&lt;/bean&gt;	</code></pre>
<p>Note that I have more than one around advice here.  Coldspring evaluates them from the bottom up so jsonAdvisor is &#8220;around&#8221; authorizationAdvisor which is &#8220;around&#8221; authenticationAdvisor.  I have them stacked like this so I can reuse authorization/authentication in other remote proxies as well.</p>
<h2>Formatting</h2>
<p>One thing I didn&#8217;t like about CF8&#8217;s SerializeJSON() is that it changes your data slightly (as compared to JSON.cfc).  Take for example the following structure:</p>
<p><code>str.camelHumpName = "Some Value";<br />
str.NumericValue = 52;</code></p>
<p>SerializeJSON translates that to:</p>
<p><code>{"CAMELHUMPNAME": "Some Value", "NUMERICVALUE": 52.0}</code></p>
<p>That&#8217;s kind of goofy although the case issue is consistent with how the structure functions treat your key names.  Because CF is not case-sensitive, we can still refer to them with our normal mixed case.  Not so in case-sensitive Javascript-land.  You can get around the upper case keys by using a slightly different structure notation:</p>
<pre><code>// maintains mixed-case key in json serialization
str["camelHumpName"] = "Some Value"; 

// when quoted, value remains an integer (52) rather than a float (52.0)
str["NumericValue"] = "52"; </code></pre>
<p>This structure produces the following JSON:</p>
<p><code>{"camelHumpName": "Some Value", "NumericValue": 52.0}</code></p>
<h2>Mashup Controls</h2>
<p>You might have noticed the line above that read:</p>
<p><code>&lt;cfheader name="Access-Control" value="allow &lt;*&gt;" /&gt;</code></p>
<p>This is a new header used to better control XSS attacks that is understood by Firefox 3&#8217;s <a href="https://developer.mozilla.org/En/Cross-Site_XMLHttpRequest">XHR implementation</a>.  You can control which web sites can and cannot request data using this header. </p>
<p>There we have it.  A couple of tricks and tips for building AJAX applications using ColdSpring&#8217;s RemoteProxyBean and AOP!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2008/11/21/control-json-formatting-with-coldspring-remote-proxy/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tablesorter Quickies</title>
		<link>http://www.ghidinelli.com/2008/11/11/tablesorter-quickies</link>
		<comments>http://www.ghidinelli.com/2008/11/11/tablesorter-quickies#comments</comments>
		<pubDate>Tue, 11 Nov 2008 20:48:46 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=293</guid>
		<description><![CDATA[Doing a little Javascript hacking today and have a few parsers to share for the TableSorter jQuery plugin.  I&#8217;ve written some in the past but more is always merrier.  
Sorting alphanumeric data in numeric order
I have member numbers which can look like &#8216;A23423423&#8242; or &#8216;2000-342&#8242; or &#8216;220342BMW&#8217; but I want to sort them [...]]]></description>
			<content:encoded><![CDATA[<p>Doing a little Javascript hacking today and have a few parsers to share for the <a href="http://www.tablesorter.com">TableSorter jQuery plugin</a>.  I&#8217;ve <a href="http://www.ghidinelli.com/2007/06/27/tablesorter-add-ons-plus-jquery">written some in the past</a> but more is <a href="http://beckelman.net/post/2008/11/11/Sorted-Column-Highlighting-Widget-for-jQuery-TableSorter-Plugin-Demo.aspx">always</a> <a href="http://www.koders.com/javascript/fidFC12CFF43D6B218FB3F5FF4C5643256285B19B49.aspx?s=checkbox#L2">merrier</a>.  </p>
<h2>Sorting alphanumeric data in numeric order</h2>
<p>I have member numbers which can look like &#8216;A23423423&#8242; or &#8216;2000-342&#8242; or &#8216;220342BMW&#8217; but I want to sort them in numeric order since the characters often refer to associate members or some sub-qualifier.  It takes a pretty simple parser with a regular expression to accomplish it:</p>
<p><code>$.tablesorter.addParser({<br />
	id: 'memNumber',<br />
	is: function(s) {<br />
		return false;<br />
	},<br />
	format: function(s) {<br />
		return s.replace(/[^0-9]/g, "");<br />
	},<br />
	sorter: 'numeric'<br />
});</code></p>
<h2>Adspeed Parsers &amp; Widgets</h2>
<p>I also came across a recent post <a href="http://www.adspeed.org/2008/10/jquery-extend-tablesorter-plugin.html">over at Adspeed.org</a> that includes several parsers and widgets:</p>
<ol>
<li>Parser for sorting values like &#8220;$1,300.50&#8243;</li>
<li>Parser for sorting values like &#8220;2 months ago&#8221;,&#8221;3 years ago&#8221; (actual timestamp hide in the comment)</li>
<li>Parser for sorting values like &#8220;SMALLER&#8221;,&#8221;SMALL&#8221; (actual text value hide in comment)</li>
<li>Widget to highlight a row when mouse hovers it</li>
<li>Widget to highlight a header when mouse hovers it</li>
<li>Widget to save/memorize sort order via AJAX</li>
</ol>
<p>I particularly like the idea of embedding the sortable value in a comment and using that to sort.  It gives you total freedom in how you display versus sort (and could work just as well as my custom member number parser above).</p>
<p>You can write your own <a href="http://tablesorter.com/docs/example-parsers.html">parsers</a> and <a href="http://tablesorter.com/docs/example-widgets.html">widgets</a> easily to extend TableSorter for your own requirements.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2008/11/11/tablesorter-quickies/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Neat Dropdown Menu jQuery Plugin</title>
		<link>http://www.ghidinelli.com/2008/06/22/neat-dropdown-menu-jquery-plugin</link>
		<comments>http://www.ghidinelli.com/2008/06/22/neat-dropdown-menu-jquery-plugin#comments</comments>
		<pubDate>Sun, 22 Jun 2008 18:55:40 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/2008/06/22/neat-dropdown-menu-jquery-plugin/</guid>
		<description><![CDATA[Dan Switzer has been up to more good with jQuery releasing a multi-column dropdown plugin developed for Giva that can handle an arbitrary number of elements from a series of nested unordered lists.
There are two things that I like about this plugin in particular:

Full support for keyboard input
Designed to handle a lot of data

I have [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.pengoworks.com/">Dan Switzer</a> has been up to more good with jQuery releasing a <a href="http://www.givainc.com/labs/mcdropdown_jquery_plugin.htm">multi-column dropdown plugin</a> developed for <a href="http://www.givainc.com/index.htm">Giva</a> that can handle an arbitrary number of elements from a series of nested unordered lists.</p>
<p>There are two things that I like about this plugin in particular:</p>
<ol>
<li>Full support for keyboard input</li>
<li>Designed to handle a lot of data</li>
</ol>
<p>I have been working with RIAs for a long time, trying to bridge the gap between the power of desktop applications and the distribution model of web applications.  When trying to build data-heavy applications, we were regularly disappointed by either the lack of design for lots of data or the poor performance experienced once we exceeded a sample screen of data.  I&#8217;m glad to see more emphasis on this type of performance at the requirements gathering phase.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2008/06/22/neat-dropdown-menu-jquery-plugin/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Finding the row and cell index of a clicked table cell with jQuery</title>
		<link>http://www.ghidinelli.com/2008/03/27/finding-the-row-and-cell-index-of-a-clicked-table-cell-with-jquery</link>
		<comments>http://www.ghidinelli.com/2008/03/27/finding-the-row-and-cell-index-of-a-clicked-table-cell-with-jquery#comments</comments>
		<pubDate>Fri, 28 Mar 2008 01:19:23 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/2008/03/27/finding-the-row-and-cell-index-of-a-clicked-table-cell-with-jquery/</guid>
		<description><![CDATA[I needed to find where I was at in a table so I could report back the row and cell position for another function.  There aren&#8217;t any easy-to-find answers from the Google so I set about doing my standard Javascript DOM exploration:
for (var ii in this)
  console.info(" ii = " + ii);
I explore [...]]]></description>
			<content:encoded><![CDATA[<p>I needed to find where I was at in a table so I could report back the row and cell position for another function.  There aren&#8217;t any easy-to-find answers from the Google so I set about doing my standard Javascript DOM exploration:</p>
<p><code>for (var ii in this)<br />
  console.info(" ii = " + ii);</code></p>
<p>I explore this way because I don&#8217;t know any better.  After much debugging with the .bind() on my <a href="http://www.tablesorter.com">TableSorter</a> table, I cobbled together references to the row and cell so I could update a single value in the table cache when a form element is changed as a performance boost for large tables.  This assumes a SELECT box but it works for any element inside of a TD:</p>
<p><code>&lt;table&gt;<br />
...<br />
&lt;tbody&gt;<br />
...<br />
&lt;tr&gt;<br />
	&lt;td&gt;...&lt;/td&gt;<br />
	&lt;td&gt;<br />
		&lt;select name="foo"&gt;<br />
			&lt;option value="100"&gt;Blow, Joe&lt;/option&gt;<br />
			&lt;option value="200"&gt;Mack, Jane&lt;/option&gt;<br />
			&lt;option value="300"&gt;Zanker, John&lt;/option&gt;<br />
		&lt;/select&gt;<br />
	&lt;/td&gt;<br />
&lt;/tr&gt;<br />
...<br />
&lt;/tbody&gt;<br />
&lt;/table&gt;</code></p>
<p>And the corresponding Javascript event handler:</p>
<p><code>$("table#tblNumbers select").change(<br />
	function()<br />
	{<br />
		// get row, cell, value<br />
		var cell = $(this).parent("td");<br />
		var row = $(cell).parent("tr");<br />
		var cellValue = [[row[0].sectionRowIndex, cell[0].cellIndex, $(this).find("option:selected").text()]];</p>
<p>		// update table cache<br />
		$(this).parents("table").trigger("updateCell", cellValue);<br />
	}<br />
);</code></p>
<p>The trick is that jQuery&#8217;s .parent() returns a single-item array that you must access through the [0] identifier.  If you drop into the [0] item, you have full access to the DOM node including the properties for rowIndex and cellIndex.</p>
<p>In addition to sectionRowIndex, you can also use rowIndex.  It depends on whether or not you want the position absolutely in the table or relative to the TBODY you&#8217;re inside.  I wanted to exclude the THEAD from the row count so  I used sectionRowIndex.</p>
<p>Hope that helps someone&#8230; or more likely, helps me when I forget how to do this again next week. <img src='http://www.ghidinelli.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2008/03/27/finding-the-row-and-cell-index-of-a-clicked-table-cell-with-jquery/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>TableSorter 2.0.3++ Universal Sorting plus cool Grouping Widget</title>
		<link>http://www.ghidinelli.com/2008/03/25/tablesorter-203-universal-sorting-plus-cool-grouping-widget</link>
		<comments>http://www.ghidinelli.com/2008/03/25/tablesorter-203-universal-sorting-plus-cool-grouping-widget#comments</comments>
		<pubDate>Wed, 26 Mar 2008 01:10:12 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/2008/03/25/tablesorter-203-universal-sorting-plus-cool-grouping-widget/</guid>
		<description><![CDATA[Christian and I collaborated the other day on a new feature for the excellent jQuery plugin, TableSorter.  I can only take credit for the idea as Christian made the magic happen.  This addition makes it now possible to sort any content, whether it be a form field, inside markup, etc.
The Situation
For simple data [...]]]></description>
			<content:encoded><![CDATA[<p>Christian and I collaborated the other day on a new feature for the excellent jQuery plugin, <a href="http://www.tablesorter.com">TableSorter</a>.  I can only take credit for the idea as Christian made the magic happen.  This addition makes it now possible to sort <em>any</em> content, whether it be a form field, inside markup, etc.</p>
<h2>The Situation</h2>
<p>For simple data or markup, TableSorter can normally just grab the data and sort but there are cases where that won&#8217;t work.  Take for example a table with a form field in it. Tables in forms???  Yes, validator-weenies, I have no problem putting a form into a table for tabular editing.  The problem is that TableSorter doesn&#8217;t know the value of the form element so sorting fails.  Furthermore, in my case, I wanted to sort on the display value of a select box since the value was a 35-character UUID.</p>
<p>My &#8220;tableform&#8221; looks like this:</p>
<div style="overflow: auto;"><img src='http://www.ghidinelli.com/wp-content/uploads/2008/03/tablesorter_form.gif' alt='Shot of tablesorter with a form in it' /></div>
<p>I wanted to be able to sort on the select boxes, make changes, and sort again.</p>
<h2>The Change</h2>
<p>I am a relatively clueless Javascript hacker so I asked Christian if he thought a custom extractor or parser was the best way to go about getting at the value and he suggested parsers, because they&#8217;re more powerful.  Then I asked how you get a reference to the content of the cell and he said, &#8220;Oh, hold on&#8230;&#8221;  A few minutes later, he had a new revision checked into subversion that changed the API from:</p>
<p><code>	is: function(s) {<br />
		// returning false prevents auto-detection; we manually assign this<br />
		return false;<br />
	}</p>
<p>	format: function(s) {<br />
		s += ', ' + new Date().getYear();<br />
		return $.tablesorter.formatFloat((new Date(s)).getTime());<br />
	}<br />
});</code></p>
<p>where the is() and format() functions just return the HTML content of the node to accepting multiple arguments that include a reference to the table and the table cell like so:</p>
<p><code>	is: function(s, table, node) {<br />
		// returning false prevents auto-detection; we manually assign this<br />
		return false;<br />
	}</p>
<p>	format: function(s, table, node) {<br />
		s += ', ' + new Date().getYear();<br />
		return $.tablesorter.formatFloat((new Date(s)).getTime());<br />
	}</code></p>
<p>With this API change, I could now write a parser to pull out the display value from the select box with just a little jQuery sugar:</p>
<p><code>$.tablesorter.addParser({<br />
	id: 'selectBox',<br />
	is: function(s, table, node) {<br />
		if (!node.childNodes[0].tagName) return false;<br />
		return (node.childNodes[0].tagName == 'SELECT') ? true : false;<br />
	},<br />
	format: function(s, table, node) {<br />
		// use new node argument to get the display value of the select box<br />
		return $(node).find("option:selected").text();<br />
	},<br />
	type: 'text'<br />
});</p>
<p>$("#tblAssignments").tablesorter({<br />
	,headers: { 3: { sorter: 'selectBox' }<br />
			,4: { sorter: 'selectBox' }<br />
	}<br />
}); </code></p>
<p>As you can imagine, with a jQuery object available, there isn&#8217;t anything you can&#8217;t sort in a table.  Very cool!</p>
<h2>Update</h2>
<p>For efficiency, TableSorter caches the formatted data to make sorting quick.  But when value of a form field changes, TableSorter needs to be told about it with the update() function:</p>
<p><code>$("table#tblAssignments select").change(<br />
	function()<br />
	{<br />
		$(this).parents("table").trigger("update");<br />
	}<br />
);</code></p>
<p>Now every time you change a select box, the data is refreshed.  In a smallish table, this only takes 10-30ms.  I haven&#8217;t tested yet on a large dataset but it&#8217;s sufficiently fast.  If performance becomes a problem, we could find a way to update a single item in the cache.</p>
<h2>Grouping/Collapsing</h2>
<p>I also wanted to be able to add grouping and running tallies for groups using TableSorter and came across a <a href="http://code.google.com/p/grouping/">groups widget</a> on Google code.  The comments and variable names are all in some Slavic language meaning I can&#8217;t make head nor tail of it, but the good news is that this plugin does work!  I&#8217;ve updated it a bit to always show a running tally and so forth so contact me if you&#8217;d like my more-hacky version.  The project description <a href="http://code.google.com/p/grouping/wiki/Description">is pretty clear</a>.</p>
<div style="overflow: auto"><img src='http://www.ghidinelli.com/wp-content/uploads/2008/03/tablesorter_grouped.gif' alt='Shot of tablesorter with grouping plugin collapsed' class='aligncenter' /></div>
<p>This screenshot shows several of the groups collapsed into a thin bar with a tally of how many items are in each group.   Thanks goes out to Christian for the new feature and for revving the version number against his will! <img src='http://www.ghidinelli.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2008/03/25/tablesorter-203-universal-sorting-plus-cool-grouping-widget/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

