<?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>Fri, 27 Jan 2017 17:45:50 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Selectively applying Hubspot (or other) tracking code</title>
		<link>http://www.ghidinelli.com/2014/01/27/selectively-applying-hubspot-tracking-code</link>
		<comments>http://www.ghidinelli.com/2014/01/27/selectively-applying-hubspot-tracking-code#comments</comments>
		<pubDate>Tue, 28 Jan 2014 06:02:29 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1566</guid>
		<description><![CDATA[Using jQuery to selectively apply Hubspot or other Javascript tracking codes to users]]></description>
			<content:encoded><![CDATA[<p>My company uses <a href="http://www.hubspot.com">Hubspot</a> to help support our marketing efforts.  One thing Hubspot provides is great tracking that shows all of the touch points you have with a potential customer as they read your blog, download your content and fill out your forms.  This helps form a cohesive picture of where someone is in the sales funnel and their interests and needs.</p>
<p>As a Software-as-a-Service for <a href="http://www.motorsportreg.com">online event registration</a>, however, we face the dilemma of separating out potential customers of our SaaS app and <em>their</em> customers who come to our site to also participate in the marketplace.  For every event organizer who visits our site and might be interested in using our system, hundreds of event attendees come to get registered.  Including the <a href="http://knowledge.hubspot.com/getting-started-with-hubspot/how-to-install-the-tracking-code-on-a-generic-website">Hubspot tracking code</a> on our home page makes our traffic numbers look great but has the negative side effect of dropping our lead and conversion ratios well under 1%.  Ignore for a moment that this is demoralizing, it also makes reports difficult to use.  Picture comparing the success of a landing page with 0.05% conversions and another with 0.07%.  They both look effectively equivalent because of the scale but if those numbers instead read 50% and 70%, you would not only be impressed but recognize the latter is performing 40% better!</p>
<p>One option here would be to simply remove the tracking code from the home page and that would fix the statistic and volume issues.  But we would lose important referring data.  While Google is no longer giving us much in the way of search keywords, we still can see referring URLs when people surf to MotorsportReg.com.  If we removed the tracking code from the home page and cookie&#8217;d them when they hit the About Us page, we would lose that original traffic source.</p>
<p>So, the challenge began to find a way to cookie the people who were potential leads and do it on the home page so we could capture referrer data.  I asked our sales guy, our onboarding rep and customer support.  Nobody had any idea how to segment the traffic to weed out the event attendees from skewing our data.  </p>
<p>But I had an idea, and it turns out it works pretty well.</p>
<p>What I want to know, specifically, is when someone views our &#8220;<a href="www.motorsportreg.com/index.cfm/event/event-management">How it works</a>&#8221; or another marketing/sales page as that indicates interest in our SaaS product.  I started by tagging all links in the top and bottom navigation that link to our marketing and sales pages with a CSS class like:</p>
<p><code>&lt; a href="/about" class="hs"&gt;How it Works&lt; /a&gt;</code></p>
<p>On those marketing pages, we include the Hubspot tracking code on every view.  But for the home page, I wrapped it inside of a jQuery click handler:</p>
<p><code>$(document).ready(function()<br />
{<br />
  // dynamically load hubspot code only if someone clicks a marketing-related link on the home page<br />
  $('.hs').click(function(e)<br />
  {<br />
    var anchor = $(this), h;<br />
    h = anchor.attr('href');<br />
    if (typeof _hsq === "undefined")<br />
    {<br />
      e.preventDefault();<br />
      $.getScript('//js.hubspot.com/analytics/'+(Math.ceil(new Date()/300000)*300000)+'/{your-hubspot-id}.js', function(){<br />
        setTimeout(function(){window.location = h},1000);<br />
      });<br />
    }<br />
  });<br />
});</code></p>
<p>The code basically says: if someone clicks a link with the class &#8220;hs&#8221;, grab the link they clicked, load the Javascript file from Hubspot&#8217;s servers, wait 1 second, and then continue to the original link.  In the 1 second while we sleep, the code should load from Hubspot&#8217;s servers which results in the user getting cookie&#8217;d appropriately and Hubspot can still access the referring URLs, search keywords, etc.</p>
<p>This approach is not only limited to Hubspot.  It would work equally well with any Javascript-based tracking code like Google Analytics or others if you had some reason to exclude certain users from participating under certain circumstances.</p>
<p>It&#8217;s not perfect &#8211; the one second pause is too long in some cases, not long enough in others, and adds a delay in all cases which <a href="http://blog.kissmetrics.com/loading-time/">can increase page abandonment</a>.   However, we&#8217;ve been using this in production now for about 3 months and it&#8217;s been working well.  Lead volume is slightly up despite the brief delay and we see the full browsing history for contacts in Hubspot.  Our lead and traffic numbers are now properly scaled so we can make sense of the data we&#8217;re seeing.  </p>
<p>If you have multiple audiences viewing your site and only want to apply tracking to some of them, this technique is worth taking a look at.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2014/01/27/selectively-applying-hubspot-tracking-code/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery TableSorter finds new life</title>
		<link>http://www.ghidinelli.com/2013/03/30/jquery-tablesorter-finds-new-life</link>
		<comments>http://www.ghidinelli.com/2013/03/30/jquery-tablesorter-finds-new-life#comments</comments>
		<pubDate>Sat, 30 Mar 2013 18:22:54 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1545</guid>
		<description><![CDATA[jQuery TableSorter plugin finds new life thanks to Rob Garrison and brings an updated Grouping plugin to create collapsible groups of like items from HTML tables]]></description>
			<content:encoded><![CDATA[<p>Many moons ago, I helped write the docs for <a href="http://www.tablesorter.com">TableSorter</a>, a jQuery plugin for sorting HTML tables.  It was last updated in 2008 but it&#8217;s as useful today as it was then.  Thankfully, Rob Garrison has been making <a href="https://github.com/Mottie/tablesorter">significant updates</a> to it on GitHub.  Importantly, he&#8217;s also brought in and radically improved one of my favorite widgets for Grouping.  This lets you click a header and see collapsible groups.  While the old widget was pretty limited, Rob has gone wild with this one giving you all kind of formatting capability over how the groups are formed and titled.</p>
<p>Two huge thumbs up: take a look at this <a href="http://mottie.github.com/tablesorter/docs/example-widget-grouping.html">jQuery table grouping demo</a>.  </p>
<p>If you&#8217;re using TableSorter 2.0.3 or 2.0.5 from 2008, take a look at Rob&#8217;s version today.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2013/03/30/jquery-tablesorter-finds-new-life/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<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="https://www.ghidinelli.com/wp-content/uploads/2010/01/batchcange.png"><img src="https://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="https://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 (https://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("https://www.ghidinelli.com");
  		setPluginURL("https://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="https://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 (&#8216;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 {&#8220;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="https://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>
	</channel>
</rss>
