<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CkEARHs5cSp7ImA9WhRbEUw.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638</id><updated>2012-02-01T21:07:25.529+05:30</updated><category term="IMAP" /><category term="CFBuilder" /><category term="Flex" /><category term="Misc" /><category term="JavaScript/jQuery" /><category term="Events" /><category term="Kiss My App" /><category term="ColdFusion" /><category term="Server Monitor" /><category term="HTML5" /><category term="Photoshop" /><title>Fusioned with ColdFusion</title><subtitle type="html">&lt;br&gt;
&lt;b&gt;
A blog on ColdFusion and other web technologies.
&lt;/b&gt;</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.sagarganatra.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>43</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/FusionedWithColdfusion" /><feedburner:info uri="fusionedwithcoldfusion" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>FusionedWithColdfusion</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;DkYNQHYycSp7ImA9WhRUE08.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-2289455752001676525</id><published>2012-01-23T18:39:00.002+05:30</published><updated>2012-01-23T18:39:51.899+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-23T18:39:51.899+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ColdFusion" /><title>ColdFusion Tip: How to tell if path is file or directory</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PHkbN5_25_zPzHqXHv8W7dVCW6M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PHkbN5_25_zPzHqXHv8W7dVCW6M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PHkbN5_25_zPzHqXHv8W7dVCW6M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PHkbN5_25_zPzHqXHv8W7dVCW6M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Today, one of the ColdFusion users asked me a question "Is there anyway I can find out whether a path is a directory or a file? There is no isDirectory() function available in ColdFusion and I don't want to write Java code to do this. Any help?"
&lt;br /&gt;
For a moment I thought really! is there no way that ColdFusion can tell you whether a given path is of a directory or file? But sooner, I came across the function 'getFileInfo' which takes the path as an argument and returns a struct data that contains various metadata properties of the file. The struct includes a key - 'type' whose value can either be a directory or file. The below code shows how you can determine whether the given path is of a directory or file:
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class="divCF"&gt;&lt;span class="sc2"&gt;&amp;lt;cfset&lt;/span&gt;&lt;span class="sc0"&gt; fileInfo &lt;/span&gt;&lt;span class="sc8"&gt;=&lt;/span&gt;&lt;span class="sc0"&gt; &lt;/span&gt;&lt;span class="sc14"&gt;getFileInfo&lt;/span&gt;&lt;span class="sc8"&gt;(&lt;/span&gt;&lt;span class="sc14"&gt;expandPath&lt;/span&gt;&lt;span class="sc8"&gt;(&lt;/span&gt;&lt;span class="sc6"&gt;"./myDir"&lt;/span&gt;&lt;span class="sc8"&gt;))&lt;/span&gt;&lt;span class="sc0"&gt; &lt;/span&gt;&lt;span class="sc2"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sc0"&gt;
&lt;/span&gt;&lt;span class="sc2"&gt;&amp;lt;cfif&lt;/span&gt;&lt;span class="sc0"&gt; fileInfo&lt;/span&gt;&lt;span class="sc8"&gt;.&lt;/span&gt;&lt;span class="sc0"&gt;type &lt;/span&gt;&lt;span class="sc8"&gt;EQ&lt;/span&gt;&lt;span class="sc0"&gt; &lt;/span&gt;&lt;span class="sc6"&gt;"directory"&lt;/span&gt;&lt;span class="sc2"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sc0"&gt;
    &lt;/span&gt;&lt;span class="sc12"&gt;&amp;lt;!--- is a directory ---&amp;gt;&lt;/span&gt;&lt;span class="sc0"&gt;
&lt;/span&gt;&lt;span class="sc2"&gt;&amp;lt;cfelseif&lt;/span&gt;&lt;span class="sc0"&gt; fileInfo&lt;/span&gt;&lt;span class="sc8"&gt;.&lt;/span&gt;&lt;span class="sc0"&gt;type &lt;/span&gt;&lt;span class="sc8"&gt;EQ&lt;/span&gt;&lt;span class="sc0"&gt; &lt;/span&gt;&lt;span class="sc6"&gt;"file"&lt;/span&gt;&lt;span class="sc2"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sc0"&gt;
    &lt;/span&gt;&lt;span class="sc12"&gt;&amp;lt;!--- is a file ---&amp;gt;&lt;/span&gt;&lt;span class="sc0"&gt;  
&lt;/span&gt;&lt;span class="sc2"&gt;&amp;lt;/cfif&amp;gt;&lt;/span&gt;&lt;span class="sc0"&gt;
&lt;/span&gt;&lt;span class="sc2"&gt;&amp;lt;cfdump&lt;/span&gt;&lt;span class="sc15"&gt; var&lt;/span&gt;&lt;span class="sc2"&gt;=&lt;/span&gt;&lt;span class="sc6"&gt;"&lt;/span&gt;&lt;span class="sc13"&gt;#fileInfo#&lt;/span&gt;&lt;span class="sc6"&gt;"&lt;/span&gt;&lt;span class="sc2"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sc0"&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;br/&gt;
The other metadata properties such as canRead, canWrite, isHidden, lastModified, parent, size included in the resultant struct can also come handy.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-iWG2rSpwutU/Tx1UGCUwOiI/AAAAAAAADxs/_znKGKrS53I/s1600/getFileInfo_Output.PNG" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="212" width="282" src="http://4.bp.blogspot.com/-iWG2rSpwutU/Tx1UGCUwOiI/AAAAAAAADxs/_znKGKrS53I/s400/getFileInfo_Output.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-2289455752001676525?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/ScxY5auJkDE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/2289455752001676525/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2012/01/coldfusion-tip-how-to-tell-if-path-is.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/2289455752001676525?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/2289455752001676525?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/ScxY5auJkDE/coldfusion-tip-how-to-tell-if-path-is.html" title="ColdFusion Tip: How to tell if path is file or directory" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-iWG2rSpwutU/Tx1UGCUwOiI/AAAAAAAADxs/_znKGKrS53I/s72-c/getFileInfo_Output.PNG" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://www.sagarganatra.com/2012/01/coldfusion-tip-how-to-tell-if-path-is.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUDR3g-eip7ImA9WhRVF04.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-3643230025104206809</id><published>2012-01-16T22:26:00.000+05:30</published><updated>2012-01-16T22:31:16.652+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-16T22:31:16.652+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Misc" /><title>2011 - A year full of surprises</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/IEjeutKxfHsWe9lS2u2tPDE8nW8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IEjeutKxfHsWe9lS2u2tPDE8nW8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/IEjeutKxfHsWe9lS2u2tPDE8nW8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IEjeutKxfHsWe9lS2u2tPDE8nW8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I know it's been more than 15 days since the world celebrated new year and every one made some big and small resolutions which they hope they will live up to in this year. I had a fair 2011; there were a few ups and downs but in the end its gone and 2012 is here. Last year I presented ColdFusion Builder 2 at SOTR on the very day it was released to the public (how exciting!!). I was very much excited and nervous at the same time since this was my first talk at a conference. Nevertheless it went well, I have said this before and will say it again, 'Edinburgh is beautiful'.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;
Last year I started to look at HTML5 features and had shared them on my blog. I thank the community for appreciating my work and findings. A few things that didn't really work out was making money through facebook applications. I had created a couple of facebook apps (you can call them silly, well all facebook apps are silly) and unfortunately I didn't get anything from it. But sooner, I realized that I didn't enjoy it and shifted my focus to something that I liked - blogging. I started blogging about HTML5, ColdFusion and CFBuilder often which made me feel happy about myself. I became a 'DZone Most Valuable Blogger' and that made me say 'I am wow'. During that time, I bought a domain with my name and got rid of the blogspot from my blog address.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-Iz6PstQkuoY/TxMZo_--_XI/AAAAAAAADxQ/OKXdRFvbViw/s1600/img-1458.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-Iz6PstQkuoY/TxMZo_--_XI/AAAAAAAADxQ/OKXdRFvbViw/s200/img-1458.jpg" width="127" /&gt;&lt;/a&gt;&lt;/div&gt;
I read quite a few books, but the one that really stood out was the 'Voice of Silence' by Osho. It's a book on meditation and it shares several aspects of life that one should know. I felt really happy after reading this book. Every page of this book has something that one should know. Several teachings of Buddha and Mahavira have been shared. It took a lot of frustration out of me and made me love myself.&lt;br /&gt;
&lt;br /&gt;
When everything was going just fine, I met with a road accident that shook my life and more than that my right leg. Was that my fault? No. Hell No. A street dog came out of nowhere giving me no chance but to ride my bike over it. I fell on my right and broke my left hand wrist and my right leg knee. The doctors had put screws and asked me to take rest for the next two months. I can say 'I'm screwed; literally'. After two months, I walked into the office and it was a joy. Now, I'm almost back on my feet and feeling good. Oh by the way, someone gifted me a book titled 'Corporate Chanakya' from my &lt;a href="http://www.flipkart.com/wishlist/Sagar_Ganatra" target="_blank"&gt;wishlist&lt;/a&gt;. Like I said, last year was full of surprises.&lt;br /&gt;
&lt;br /&gt;
This year, I hope there'll be good surprises and no accidents at all. My first resolution this year is to get fit. I have put on a few kilos and will have to shed them asap. This year will also see the release of the next version of ColdFusion and I plan to blog about the features once the public beta is released (very very soon). My next resolution is to dedicate more time to my family. At the end of the day, it's my family that makes me feel special than anyone else. And lastly, I hope this year is not the end of the world and I'll live up to see a beautiful sunny day in 2013.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-3643230025104206809?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/1z9pKrVP3sc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/3643230025104206809/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2012/01/2011-year-full-of-surprises.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3643230025104206809?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3643230025104206809?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/1z9pKrVP3sc/2011-year-full-of-surprises.html" title="2011 - A year full of surprises" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-Iz6PstQkuoY/TxMZo_--_XI/AAAAAAAADxQ/OKXdRFvbViw/s72-c/img-1458.jpg" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://www.sagarganatra.com/2012/01/2011-year-full-of-surprises.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYHRXk4fCp7ImA9WhRTE08.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-6373863516238981471</id><published>2011-11-03T19:02:00.000+05:30</published><updated>2011-11-03T19:02:14.734+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T19:02:14.734+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript/jQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><title>Using HTML5's Navigation Timing API to measure Page Load speed</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/90i1btfnBr-KdQN-snzGlexBRdc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/90i1btfnBr-KdQN-snzGlexBRdc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/90i1btfnBr-KdQN-snzGlexBRdc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/90i1btfnBr-KdQN-snzGlexBRdc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;To measure the time taken for a page to load one can use the Date object in the head section and calculate the time taken for the page to load in &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;window.onload&lt;/span&gt; function. However, it calculates the time taken for the page to load after the first bit of JavaScript in the head is executed. This doesn't indicate the time taken by the web server to serve the requested page. The Navigation Timing API introduced in HTML5 provides data that can be used to measure the performance of a website. The API provides a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PerformanceTiming &lt;/span&gt;interface which contains several attributes that can be used to get end-to-end latency data.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;b&gt;Measuring Page load performance using the Date object:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned above, when you try to calculate the time taken for the page to load using the Date object, it doesn't indicate the time taken by the web server to server the page:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; var startTime = new Date().getTime();  
 function onLoadEventHandler() {  
      var latency = new Date().getTime() - startTime;  
      console.log('Latency = ' + latency + 'ms');  
 }  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
This would output:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"&gt;Latency = 2ms&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Measuring Page load performance using the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;performance.timing&lt;/span&gt; object:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The PerformanceTiming interface includes several attributes and one of them is the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;navigationStart&lt;/span&gt; attribute. This attribute returns the time when the browser attempts to fetch a new resource from the server. If there is a document from which the user is navigating to a new document (by clicking a link), then it returns time when the browser finishes unloading the previous document:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; var startTime = new Date().getTime();  
 function onLoadEventHandler() {  
      var latency = startTime - performance.timing.navigationStart;  
      console.log('Latency = ' + latency + 'ms');  
 }  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
This would output:&lt;br /&gt;
&lt;br /&gt;
Latency = 104ms&lt;br /&gt;
&lt;br /&gt;
As you can see from the two examples, there is a difference of more than 100ms when using the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;performance.timing&lt;/span&gt; object.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;PerformanceTiming&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&lt;/span&gt;interface:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PerformanceTiming &lt;/span&gt;interface includes several attributes:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-_1yrgJFLH1A/TrKVHb-AJoI/AAAAAAAADvs/t3YXA8KmbB4/s1600/PerformanceTiming_Attributes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="590" src="http://1.bp.blogspot.com/-_1yrgJFLH1A/TrKVHb-AJoI/AAAAAAAADvs/t3YXA8KmbB4/s640/PerformanceTiming_Attributes.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
You can refer to more detailed explanation of attributes &lt;a href="https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Browser support:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Navigation Timing API is available on Chrome, Firefox 7 and on IE 9.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-6373863516238981471?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/36dYYOGpgHo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/6373863516238981471/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/11/using-html5s-navigation-timing-api-to.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6373863516238981471?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6373863516238981471?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/36dYYOGpgHo/using-html5s-navigation-timing-api-to.html" title="Using HTML5's Navigation Timing API to measure Page Load speed" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-_1yrgJFLH1A/TrKVHb-AJoI/AAAAAAAADvs/t3YXA8KmbB4/s72-c/PerformanceTiming_Attributes.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/11/using-html5s-navigation-timing-api-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQXY-eSp7ImA9WhRTEkQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-3371387348277785473</id><published>2011-11-01T02:05:00.001+05:30</published><updated>2011-11-03T09:26:40.851+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T09:26:40.851+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript/jQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><title>Using HTML5's PageVisibility API</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9DbzYPtrONIj1nBi2BshVqaTWwk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9DbzYPtrONIj1nBi2BshVqaTWwk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9DbzYPtrONIj1nBi2BshVqaTWwk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9DbzYPtrONIj1nBi2BshVqaTWwk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Today I stumbled upon the &lt;a href="http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html"&gt;PageVisibility API&lt;/a&gt; introduced in HTML5, which gives developers an opportunity to improve the performance of a web page and to better the user experience. Whenever a user opens a new tab or navigates to another tab, the behavior of the current page from which user navigated can be controlled using this API. Consider a webmail client that is trying to look for new mails every two seconds, if a user opens a new tab or minimizes the browser window then retrieving mails every two seconds would expend resources, whilst the user is not actively viewing the page. Here the PageVisibilty API would come handy and would allow developers to alter the behavior of the web page.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;a name='more'&gt;&lt;/a&gt;The specification introduces the interface - DocumentVisibility. It includes the attributes 'hidden' and 'visibilityState'. The hidden attribute of the document object (document.hidden) returns true if the user selects another tab or when the browser window is minimized. It returns false when the same document is selected by the user. The visibilityState attribute is used to indicate the state of the page - hidden, visible and preview (marked as optional in the spec).&lt;br /&gt;
&lt;br /&gt;
To be notified when the document becomes hidden or when it becomes visible again one can listen to the 'visibilitychange' event. The example below calculates the number of seconds the user was not active on the page:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;!DOCTYPE HTML&amp;gt;  
 &amp;lt;html&amp;gt;  
 &amp;lt;head&amp;gt;  
      &amp;lt;script type="text/javascript"&amp;gt;  
           timer = 0;  
           function onLoad(){  
                document.addEventListener("visibilitychange",stateChanged);  
                document.addEventListener("webkitvisibilitychange", stateChanged);  
                document.addEventListener("msvisibilitychange", stateChanged);  
           }  
           function stateChanged(){  
                console.log(document.webkitVisibilityState);  
                if(document.hidden || document.webkitHidden || document.msHidden){  
                     //new tab or window minimized
                     timer = new Date().getTime();  
                }  
                else {  
                     alert('You were away for ' + (new Date().getTime()-timer)/1000+ ' seconds.')  
                }  
           }  
      &amp;lt;/script&amp;gt;  
 &amp;lt;/head&amp;gt;  
 &amp;lt;body onLoad="onLoad()"&amp;gt;  
 &amp;lt;/body&amp;gt;  
 &amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Browser support:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Chrome and IE-10 (surprisingly) have implemented this specification. However, as observed in the above code, they have provided their own prefixes to the attributes and the event listener. On Chrome, the attributes are named&amp;nbsp;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;&lt;i&gt;webkitHidden&lt;/i&gt;&lt;/span&gt; and &lt;span class="Apple-style-span" style="white-space: pre;"&gt;&lt;nobr&gt;&lt;i&gt;webkitVisibilityState&lt;/i&gt;&lt;/nobr&gt;&lt;/span&gt;. On IE, it is &lt;span class="Apple-style-span" style="white-space: pre;"&gt;&lt;i&gt;msHidden&lt;/i&gt;&lt;/span&gt; and &lt;span class="Apple-style-span" style="white-space: pre;"&gt;&lt;i&gt;msVisibilityState&lt;/i&gt;&lt;/span&gt;. Similarly the event is named&lt;span class="Apple-style-span" style="white-space: pre;"&gt; &lt;nobr&gt;&lt;i&gt;webkitvisibilitychange&lt;/i&gt;&lt;/nobr&gt; &lt;/span&gt;and&lt;span class="Apple-style-span" style="white-space: pre;"&gt; &lt;i&gt;msvisibilitychange&lt;/i&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Uses:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The PageVisiblity API can be used to notify the page when the user is not interacting with it. On receiving this notification, the client can stop polling for new data. Also, when the user selects the page, a notification can be sent to indicate that the user is active and new data can be fetched from the server. This API would also come handy where the web page is rendering some animation effects. It would make sense to stop the animation when the user is not viewing the page. When the user selects the page, a welcome back message can be displayed and the animation effect can be started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-3371387348277785473?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/LTHnYMP4xkc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/3371387348277785473/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/11/using-html5s-pagevisibility-api.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3371387348277785473?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3371387348277785473?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/LTHnYMP4xkc/using-html5s-pagevisibility-api.html" title="Using HTML5's PageVisibility API" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/11/using-html5s-pagevisibility-api.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMASHk9cCp7ImA9WhRVEko.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-2062056258391021126</id><published>2011-10-10T19:10:00.002+05:30</published><updated>2012-01-11T14:47:29.768+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-11T14:47:29.768+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ColdFusion" /><title>PubSubHubBub and ColdFusion</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5nAt5s6r32lOWI266F4LejyXDcs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5nAt5s6r32lOWI266F4LejyXDcs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5nAt5s6r32lOWI266F4LejyXDcs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5nAt5s6r32lOWI266F4LejyXDcs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I came across a publisher\subscriber protocol called PubSubHubBub. It is a server-to-server web-hook-based pubsub (publish/subscribe) protocol - an extension to Atom and RSS. Here the parties (servers) get an instant notification when a feed URL, that &amp;nbsp;they are interested in is updated.&lt;br /&gt;
&lt;br /&gt;
Traditionally a subscriber would subscribe to a feed and poll for it at regular intervals, to see if there is an updated feed available. In this protocol rather than polling for a feed, the content is pushed out from the publisher. The theory here is that the subscriber can subscribe to a feed via a 'Hub', which then would inform the subscribers when the feed is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;b&gt;How PubSubHubBub works?&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;i&gt;Publisher &lt;/i&gt;instead of sending an update to every subscriber, it includes a &amp;lt;link rel="hub"... &amp;gt; in its feed URL and sends an update to the &lt;i&gt;Hub&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;i&gt;Subscriber&lt;/i&gt; sends a subscription request to the &lt;i&gt;Hub &lt;/i&gt;with the feed URL that it is interested in. The request also contains a callback URL to which the Hub should send an update.&lt;/li&gt;
&lt;li&gt;To verify the subscription request, the &lt;i&gt;Hub &lt;/i&gt;sends a GET request to subscribers' callback URL. The &lt;br /&gt;&lt;i&gt;Subscriber &lt;/i&gt;then verifies itself by responding to the request.&lt;/li&gt;
&lt;li&gt;When the &lt;i&gt;Publisher &lt;/i&gt;posts new content, it notifies the &lt;i&gt;Hub &lt;/i&gt;of the updates by sending a ping notification (POST request).&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Hub &lt;/i&gt;on receiving a notification from the &lt;i&gt;Publisher&lt;/i&gt;, fetches the new content and then POSTs an update to the &lt;i&gt;Subscribers &lt;/i&gt;callback URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
If the feed has multiple subscribers, then the Hub would send an update to each of these subscribers. The Subscription flow posted on the &lt;a href="http://code.google.com/apis/pubsubhubbub/"&gt;PubSubHubBub &lt;/a&gt;site is here:&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;iframe frameborder="0" height="451" src="https://docs.google.com/present/embed?id=ajd8t6gk4mh2_34dvbpchfs&amp;amp;size=m" width="555"&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Where is the Hub?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Anybody can run a hub, it is not owned by any company. The protocol is decentralized and free. A couple of implementations include &lt;a href="http://pubsubhubbub.appspot.com/"&gt;pubsubhubbub.appspot.com&lt;/a&gt;&amp;nbsp;and &lt;a href="http://superfeedr.com/"&gt;superfeedr.com&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Publishing&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Whenever a publisher adds new content (a new blog post), the subscribers are to be notified of the updated feed. A notification (POST request) is sent to the Hub by the Publisher. The Content-Type header must be set to &lt;i&gt;application/x-www-form-urlencoded&lt;/i&gt;&amp;nbsp;and the request should contain the parameters 'hub.mode' and 'hub.url' in the request body. The parameter hub.mode is set to 'publish' and the hub.url is set to topic URL that is updated.&lt;br /&gt;
&lt;br /&gt;
The Hub then accepts the POST request and fetches the new content by sending a GET request to the topic URL. After fetching the content the Hub determines whether the feed has changed. The Hub would then send this information about the changes to each subscriber.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Subscribing&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The Subscriber initiates its subscription by sending a POST request to the Hub URL.&amp;nbsp;The Content-Type header must be set to&amp;nbsp;&lt;i&gt;application/x-www-form-urlencoded&lt;/i&gt;&amp;nbsp;and it should contain the following parameters in the request body:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;hub.mode - set to 'subscribe'&lt;/li&gt;
&lt;li&gt;hub.callback - subscribers callback URL where the notifications should be delivered by the Hub.&lt;/li&gt;
&lt;li&gt;hub.topic - the topic URL to which the subscriber wishes to subscribe&lt;/li&gt;
&lt;li&gt;hub.verify - it can be either sync/async.&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;sync when the verification request must occur before the subscription request's HTTP response&amp;nbsp;is returned.&lt;/li&gt;
&lt;li&gt;async when the verification request may occur at a later point after the subscription request has returned.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;b&gt;Verifying the subscription:&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The Hub on receiving a subscription request verifies the same by sending a GET request to the subscriber's callback URL. The request contains the following query strings:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;hub.mode - subscribe or unsubscribe depending on what was set in the original request.&lt;/li&gt;
&lt;li&gt;hub.topic - the topic URL given in the subscription request.&lt;/li&gt;
&lt;li&gt;hub.challenge - a random string.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
The subscriber's callback URL should respond to this request by echoing the hub.challenge string in response.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Code:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Registering the Publisher with the Hub:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The Publisher and Subscriber can be registered at &lt;a href="http://pubsubhubbub.appspot.com/"&gt;pubsubhubbub.appspot.com&lt;/a&gt;&amp;nbsp;and it is a one time activity. However, one can do the same&amp;nbsp;programmatically:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt;&amp;lt;cfhttp method="POST"  
        url="http://pubsubhubbub.appspot.com"  
        result="pub_result"&amp;gt;  

      &amp;lt;cfhttpparam type="header"  
                   name="Content-Type"  
                   value="application/x-www-form-urlencoded"&amp;gt;  
      &amp;lt;cfhttpparam type="url" 
                   name="hub.mode"  
                   value="publish"&amp;gt;  
      &amp;lt;cfhttpparam type="url"
                   name="hub.url"  
                   value="http://#machineIP#/pubsubhubbub/Publisher.cfc?method=getFeed"&amp;gt;  
 &amp;lt;/cfhttp&amp;gt;  

 &amp;lt;cfif #pub_result.Responseheader.Status_Code# eq 204&amp;gt;  
      Publisher registered successfully  
      &amp;lt;cfelse&amp;gt;  
      Publisher failed to register. Returned &amp;lt;cfoutput&amp;gt;#pub_result.Responseheader.Status_Code#&amp;lt;/cfoutput&amp;gt;
 &amp;lt;/cfif&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The Hub responds with a '204 No content' if the publishers feed is successfully registered.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Publishing content:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
A form accepting the post title and description:&lt;br /&gt;
publisher_form.cfm:&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfparam name="FORM.feedTitle" default="" &amp;gt;  
 &amp;lt;cfparam name="FORM.feedDescription" default="" &amp;gt;
  
 &amp;lt;cfif FORM.feedTitle NEQ "" AND FORM.feedDescription NEQ ""&amp;gt;       
      &amp;lt;cfset publisherObject = createObject("component","Publisher") &amp;gt;  
      &amp;lt;cfset publisherObject.publish_update(FORM.feedTitle,FORM.feedDescription) &amp;gt;  
 &amp;lt;/cfif&amp;gt;
  
 &amp;lt;form action="publisher_form.cfm" method="post"&amp;gt;  
      Add a new post here:&amp;lt;br&amp;gt;  
      Title: &amp;lt;input name="feedTitle" type="text" style="width:300px" &amp;gt;&amp;lt;br&amp;gt;   
      Description: &amp;lt;br&amp;gt;  
      &amp;lt;textarea name="feedDescription" rows="5" cols="50" &amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br&amp;gt;  
      &amp;lt;input type="submit" value="Submit"&amp;gt;  
 &amp;lt;/form&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
A ping notification is sent to the Hub, to notify of the new content. The function publish_update does that:&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cffunction name="publish_update"  
             access="remote"&amp;gt;  

             &amp;lt;cfargument name="feedTitle"  
                         required="true"/&amp;gt;  
             &amp;lt;cfargument name="feedDescription"  
                         required="true"/&amp;gt; 

             &amp;lt;!--- Insert feed data, one can also use a DB to store feed data ---&amp;gt;  
             &amp;lt;cfscript&amp;gt;  
                   if(!isDefined("application.feedQuery")) {  
                         application.feedQuery = queryNew("title,description,pubdate");  
                   }  
                  queryAddRow(application.feedQuery,1);  
                  querySetCell(application.feedQuery,"title",'#arguments.feedTitle#');           
                  querySetCell(application.feedQuery,"description",'#arguments.feedDescription#');  
                  querySetCell(application.feedQuery,"pubdate",'#DATEFORMAT(now(), "mm/dd/yyyy")#');  
             &amp;lt;/cfscript&amp;gt;  
    
             &amp;lt;!--- Send a ping notification to the Hub ---&amp;gt;  
             &amp;lt;cfhttp method="POST"  
                     url="http://pubsubhubbub.appspot.com"  
                     result="new_content"&amp;gt;  
                     &amp;lt;cfhttpparam type="header"   
                                  name="Content-Type"  
                                  value="application/x-www-form-urlencoded" &amp;gt;  
                     &amp;lt;cfhttpparam type="url"   
                                  name="hub.mode"  
                                  value="publish"&amp;gt;  
                     &amp;lt;cfhttpparam type="url"   
                                  name="hub.url"  
                                  value="http://#machineIP#/pubsubhubbub//Publisher.cfc?method=getFeed"&amp;gt;  
              &amp;lt;/cfhttp&amp;gt;  
 &amp;lt;/cffunction&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The Hub then fetches the feed from the mentioned URL (hub.url). Here it is the getFeed method in Publisher.cfc:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cffunction name="getFeed"  
             access="remote"&amp;gt;
  
             &amp;lt;cfscript&amp;gt;  
                  /* Feed metadata structure */  
                  feedMetaData = structNew();  
                  feedMetaData.author = arrayNew(1);  
                  arrayAppend(feedMetaData.author,{name:'Sagar Ganatra',email:'sagar@sagarganatra.com'});  
                  feedMetaData.encoding = "UTF-8";  
                  feedMetaData.link = arrayNew(1);  
                  arrayAppend(feedMetaData.link,{href:'http://pubsubhubbub.appspot.com',rel:'hub'});  
                  feedMetaData.title = structNew();  
                  feedMetaData.title.type = "text";  
                  feedMetaData.title.value = "Sagar's Kitchen";  
                  feedMetaData.updated = "#now()#";  
             &amp;lt;/cfscript&amp;gt;  

             &amp;lt;cfset colMap = {publishedDate="pubdate", title="title", content="description"}&amp;gt;  
             &amp;lt;cffeed action="create"  
                     query="#application.feedQuery#"  
                     properties="#feedMetaData#"  
                     columnmap="#colMap#"  
                     xmlvar="xmlResult"&amp;gt;  

             &amp;lt;cfcontent type="text/xml"  
                        reset="true"&amp;gt;  

             &amp;lt;cfoutput&amp;gt;#xmlResult#&amp;lt;/cfoutput&amp;gt;  
 &amp;lt;/cffunction&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Registering a Subscriber with the Hub:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The Subscriber can subscribe to the feed by specifying the topic URL in the request body:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfhttp method="POST"  
         url="http://pubsubhubbub.appspot.com"  
         result="sub_result"&amp;gt;
  
      &amp;lt;cfhttpparam type="header"  
             name="Content-Type"  
             value="application/x-www-form-urlencoded"&amp;gt;  
      &amp;lt;cfhttpparam type="url"  
             name="hub.mode"  
             value="subscribe"&amp;gt;  
      &amp;lt;cfhttpparam type="url"  
             name="hub.verify"  
             value="sync"&amp;gt;  
      &amp;lt;cfhttpparam type="url"  
             name="hub.topic"              
             value="http://#machineIP#/pubsubhubbub/Publisher.cfc?method=getFeed"&amp;gt;  
      &amp;lt;cfhttpparam type="url"  
             name="hub.callback"              
             value="http://#machineIP#/pubsubhubbub/subscriber.cfc?method=receiveFeed"&amp;gt;  
 &amp;lt;/cfhttp&amp;gt;  

 &amp;lt;cfif #sub_result.Responseheader.Status_Code# eq 204&amp;gt;  
      Subscriber registered successfully  
 &amp;lt;cfelse&amp;gt;  
      Subscriber failed to register. Returned &amp;lt;cfoutput&amp;gt;#sub_result.Responseheader.Status_Code#&amp;lt;/cfoutput&amp;gt;  
 &amp;lt;/cfif&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Subscribing&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, Hub checks the Subscribers' intent by sending a GET request to the callback URL. The Subscriber is then required to respond, by echoing back the 'hub.challenge' parameter present in the URL:&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cffunction name="receiveFeed"  
             access="remote"  
             returnformat="plain"  
             returntype="string"  
             output="false" &amp;gt;  

         &amp;lt;cfheader name="Content-Type"  
                   value="text/plain"&amp;gt;
  
         &amp;lt;!--- To verify the subscription ---&amp;gt;  
           &amp;lt;cfif structKeyExists(URL, "hub.challenge")&amp;gt;  
                  &amp;lt;cflog text="#url['hub.challenge']#" &amp;gt;  
                  &amp;lt;cfreturn #url['hub.challenge']#&amp;gt;  
           &amp;lt;cfelse&amp;gt;  
                 &amp;lt;!--- Receive feed data ---&amp;gt;  
                 &amp;lt;cfset feedData = getHTTPRequestData().content &amp;gt;  
                 &amp;lt;cfset fileWrite("ram:///feedSource.xml",trim(feedData)) &amp;gt;  

                 &amp;lt;cffeed action="read" source="ram:///feedSource.xml" query="feedReceived" &amp;gt;  
      
                 &amp;lt;cfdump var = #feedReceived# output="console"&amp;gt;  
                 &amp;lt;cfheader statuscode="200"&amp;gt;  
                 &amp;lt;cfreturn&amp;gt;  
           &amp;lt;/cfif&amp;gt;  
&amp;lt;/cffunction&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
As seen in the above code the feed is read in else part. One can store the read content in a database for later retrieval or send the same over a websocket to the clients so that it can be read live.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Who is using PubSubHubBub?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Google products - Google Alerts, FeedBurner, Blogger and Google Reader are using PubSubHubBub.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Reference:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Project Home -&amp;nbsp;&lt;a href="http://code.google.com/p/pubsubhubbub/"&gt;http://code.google.com/p/pubsubhubbub/&lt;/a&gt;&lt;br /&gt;
Protocol Basics -&amp;nbsp;&lt;a href="http://pubsubhubbub.googlecode.com/svn/trunk/pubsubhubbub-core-0.3.html"&gt;http://pubsubhubbub.googlecode.com/svn/trunk/pubsubhubbub-core-0.3.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-2062056258391021126?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/hB146-OHxuQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/2062056258391021126/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/10/pubsubhubbub-and-coldfusion.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/2062056258391021126?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/2062056258391021126?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/hB146-OHxuQ/pubsubhubbub-and-coldfusion.html" title="PubSubHubBub and ColdFusion" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/10/pubsubhubbub-and-coldfusion.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YAR388fyp7ImA9WhdUGEQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-1288002162234715919</id><published>2011-10-06T14:22:00.000+05:30</published><updated>2011-10-06T14:22:26.177+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-06T14:22:26.177+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Misc" /><title>Steve Jobs - An insanely brilliant man passes away</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/j-xXDPTMQCHc8i3VDkcyQQ6O1Bo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/j-xXDPTMQCHc8i3VDkcyQQ6O1Bo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/j-xXDPTMQCHc8i3VDkcyQQ6O1Bo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/j-xXDPTMQCHc8i3VDkcyQQ6O1Bo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Today when I woke up and switched on the Television to see what's making the news; I heard about Steve Jobs death. For the first time in my life, I'm feeling very sorry for a tech giant who passed away. Steve was an extraordinary human being. He kissed success not just once but many times. He changed the way we experience technology. His charisma, passion and more importantly desperation to do something great is matchless.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div&gt;
&lt;br /&gt;
He gave the world the Macintosh, iPod, iPhone, iPad and many other products. Sometimes people say 'Why to reinvent the wheel?'; this man did reinvent the wheel and revolutionized the way we perceive technology. With Macintosh, he changed the way we compute. When I work on a Mac machine at office, I can feel its simplicity and power at the same time. It feels awesome when I hit the keys of a Mac keyboard or when I scroll using the mouse. And of course the monitor, what you experience on it is amazing.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
iPhone defined what a smartphone should be like. It was introduced when everyone was talking about smart phones and few thought that they really owned one. Everyone went gaga once the iPhone was introduced in the market and it became the hottest product on the planet. Competitors like Nokia, HTC, Samsung followed soon and produced their own range of smart phones. Apple reinvented the wheel and others followed.&amp;nbsp;Not to forget the iPad, the tablet PC. Though it was Microsoft that popularized the tablet PC in earlier days, it was Apple that reinvented the wheel again and introduced this amazing product. Again competitors followed soon and produced their own range of tablet PCs.&amp;nbsp;I don't think someone has manufactured a product that comes close to an Apple iPod.&amp;nbsp;The first gift that I gave my wife was a third generation iPod nano. Its size and sound quality is breathtaking.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Apple grew not just because of the great products that it gave to its consumers, but it was this mans' charisma on stage that made Apple so insanely successful. His presentation skills were&amp;nbsp;exemplary. Today it's not just a great loss to Apple, but to this entire nation. I salute him for what he did in his life. May his soul rest in peace.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style="text-align: center;"&gt;
&lt;object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" height="374" id="ep" width="416"&gt;&lt;param name="allowfullscreen" value="true" /&gt;
&lt;param name="allowscriptaccess" value="always" /&gt;
&lt;param name="wmode" value="transparent" /&gt;
&lt;param name="movie" value="http://i.cdn.turner.com/cnn/.element/apps/cvp/3.0/swf/cnn_416x234_embed.swf?context=embed_edition&amp;videoId=us/2011/08/24/bts.steve.jobs.apple.timeline.cnn" /&gt;
&lt;param name="bgcolor" value="#000000" /&gt;
&lt;embed src="http://i.cdn.turner.com/cnn/.element/apps/cvp/3.0/swf/cnn_416x234_embed.swf?context=embed_edition&amp;videoId=us/2011/08/24/bts.steve.jobs.apple.timeline.cnn" type="application/x-shockwave-flash" bgcolor="#000000" allowfullscreen="true" allowscriptaccess="always" width="416" wmode="transparent" height="374"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-1288002162234715919?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/2KdJh7KqyAo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/1288002162234715919/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/10/steve-jobs-insanely-brilliant-man.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/1288002162234715919?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/1288002162234715919?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/2KdJh7KqyAo/steve-jobs-insanely-brilliant-man.html" title="Steve Jobs - An insanely brilliant man passes away" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/10/steve-jobs-insanely-brilliant-man.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQXY9cSp7ImA9WhRTEkQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-6843989214080458050</id><published>2011-10-03T18:36:00.000+05:30</published><updated>2011-11-03T09:26:40.869+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T09:26:40.869+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript/jQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><title>Building resposive Web applications with HTML5 Web Workers</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/T9qwYw6sGmg3VhvGAdLkAr4UbxE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T9qwYw6sGmg3VhvGAdLkAr4UbxE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/T9qwYw6sGmg3VhvGAdLkAr4UbxE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T9qwYw6sGmg3VhvGAdLkAr4UbxE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;One of the key aspects of building web applications that deliver great user experience is to build applications that are highly responsive. Browser vendors are trying to improve the speed of their JavaScript engines&amp;nbsp;and are&amp;nbsp;enabling the web applications to perform well. Since JavaScript was introduced, there has been no way to execute the code outside of the browser UI thread&amp;nbsp;i.e. it has remained single threaded. The&amp;nbsp;Web Workers API introduced in HTML5 enables web applications to run scripts in the background, independent of the UI thread.&lt;br /&gt;
&lt;br /&gt;
The performance of a web application can be greatly improved by using Web Workers since each worker would spawn its own thread. These threads can be used to perform computationally intensive tasks in the background without affecting the performance of the entire application.&lt;br /&gt;

&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Spawning a Worker:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The Worker() constructor is used to spawn a new worker thread. Since workers run in an isolated thread, a separate file containing the code(.js file) is created. The URI of the file is then passed as an argument to the Worker() constructor:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; var worker = new Worker('myWorker.js');  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
If the file 'myWorker.js' is found, then the same would be downloaded asynchronously and a Worker thread would be spawned. To receive notifications from the Worker, the onmessage event handler can be defined:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; worker.onmessage = function(event){  
      alert(event.data);  
 }  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The Worker thread can be started using the &lt;i&gt;postMessage&lt;/i&gt;() method:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; worker.postMessage('Data');  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The worker would handle the message received from the main page by defining a &lt;i&gt;onmessage&lt;/i&gt;() method:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; onmessage = function(event) {  
   postMessage('Received message ' + event.data);  
 }  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The message events &lt;i&gt;data &lt;/i&gt;attribute would contain the data passed to it from the main page. The worker can send data back to its calling thread by using the &lt;i&gt;postMessage&lt;/i&gt;() method.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Worker Example:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, Workers can be used to perform computationally intensive tasks independently. Say if the server returns a JSON string to the client and parsing the same would take say 500ms, then performing this operation inside a Worker would make the application more responsive. I was working on an algorithm for finding the first non repeated character in a paragraph or in the user provided text (a good interview question right?). In this algorithm one has to build a hash table and insert entries for each character scanned. If the character is already present in the hash table then update its value to indicate that it appears more than once. Here is the worker code:&lt;br /&gt;
&lt;br /&gt;
NonRepeatedChar.js&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; onmessage = function(event){  
   //event.data contains the text in which the non-repeated character is to be found       
   var postData = event.data;
  
   //array to insert the scanned character  
   var array = {};  
   var key = {};  
   var j = 0; 
 
   //set the found flag to false  
   var found = false; 
 
   //for each character see if it is already present in the array  
   for (i = 0; i &amp;lt; postData.length; i++) {  
     if (postData[i] != ' ') {  
       //if the character is not present in the array, insert it into the array       
       if (!array[postData[i]]) {  
         array[postData[i]] = "Seen Once";  
         key[j++] = postData[i];  
       }  
       else {  
         //if the character appears more than once update it here  
         array[postData[i]] = "More than once";  
       }  
     }  
   }
  
   //find the first character that contains the text 'Seen Once'       
   for (i = 0; i &amp;lt; j; i++) {  
     if (array[key[i]] == "Seen Once") {  
       //post the result to the caller thread and break from the loop  
       postMessage("First non repeated character is " + key[i]);  
       found = true;  
       break;  
     }  
   }
  
   //if there are no non repeated characters then send a message 'Not found'  
   if (!found) {  
     postMessage("Not found");  
   }  
 }  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The main page that invokes the worker:&lt;br /&gt;
&lt;br /&gt;
index.html&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;!DOCTYPE HTML&amp;gt;  
 &amp;lt;html&amp;gt;  
   &amp;lt;head&amp;gt;  
     &amp;lt;script type="text/javascript"&amp;gt;  
       var worker = new Worker('NonRepeatedChar.js');  
                worker.onmessage = function(event){  
                     alert(event.data);  
       }  
       function findNonRepeatedChar(){  
                  worker.postMessage(document.getElementById('myText').value);  
       }        
     &amp;lt;/script&amp;gt;  
   &amp;lt;/head&amp;gt;  
   &amp;lt;body&amp;gt;  
     &amp;lt;textarea id="myText" rows="10" cols="50"&amp;gt;  
     &amp;lt;/textarea&amp;gt;  
     &amp;lt;input type="button" value="Click" onclick="findNonRepeatedChar()"&amp;gt;  
   &amp;lt;/body&amp;gt;  
 &amp;lt;/html&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;A few limitations:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Since Workers are not bound to the UI thread, they do not have access to the DOM elements defined in the calling page. Each worker thread has its own global environment and access to a limited set of JavaScript features:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;i&gt;navigator &lt;/i&gt;object.&lt;/li&gt;
&lt;li&gt;The &lt;i&gt;location &lt;/i&gt;object.&lt;/li&gt;
&lt;li&gt;The &lt;i&gt;XmlHttpRequest &lt;/i&gt;object.&lt;/li&gt;
&lt;li&gt;Methods - &lt;i&gt;setTimeOut&lt;/i&gt;(), &lt;i&gt;setInterval&lt;/i&gt;() and &lt;i&gt;clearTimeOut&lt;/i&gt;(), &lt;i&gt;clearInterval&lt;/i&gt;().&lt;/li&gt;
&lt;li&gt;importing scripts using the method &lt;i&gt;importScripts&lt;/i&gt;()&lt;/li&gt;
&lt;li&gt;Spawning other worker threads.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;b&gt;Reference:&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://dev.w3.org/html5/workers/"&gt;http://dev.w3.org/html5/workers/&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-6843989214080458050?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/kW3adiB2Nus" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/6843989214080458050/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/10/building-resposive-web-applications.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6843989214080458050?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6843989214080458050?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/kW3adiB2Nus/building-resposive-web-applications.html" title="Building resposive Web applications with HTML5 Web Workers" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/10/building-resposive-web-applications.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUINSH4-eyp7ImA9WhdVF0k.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-450334571318851288</id><published>2011-09-22T22:12:00.001+05:30</published><updated>2011-09-23T08:43:19.053+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-23T08:43:19.053+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ColdFusion" /><title>Merging password protected PDF files in ColdFusion</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Jut5upXLYopr44ksunrqzo7X0O8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jut5upXLYopr44ksunrqzo7X0O8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Jut5upXLYopr44ksunrqzo7X0O8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jut5upXLYopr44ksunrqzo7X0O8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;In ColdFusion, CFPDF tag can be used to perform several PDF related operations such as adding a watermark, generating thumbnails, deleting pages, merging documents and securing a PDF with password. Today I wanted to merge all my bank statements into a single PDF document, such that only the first page from each document containing the summary of the statement is present in the merged document.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;To merge these documents, one can use CFPDF tag with the action attribute set to '&lt;i&gt;merge&lt;/i&gt;'. However, the PDF files that I was trying to merge were password protected. To merge password protected files one can use the CFPDFPARAM tag within a CFPDF tag and provide password there:&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfpdf action="merge"  
     destination="merged.pdf"  
     overwrite="yes"&amp;gt;  
      &amp;lt;cfpdfparam source="pdf1.pdf"  
            password="#password#"  
            pages="1"&amp;gt;  
      &amp;lt;cfpdfparam source="pdf2.pdf"  
            password="#password#"  
            pages="1"&amp;gt;  
      .
      .
      .
      .
 &amp;lt;/cfpdf&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
As mentioned earlier, the merged document should have only the first page from each document. The CFPDFPARAM tag with the &lt;i&gt;pages &lt;/i&gt;attribute set to '1' would consider only the first page while merging. One can also specify a range of pages with "1-5" or a list of pages&amp;nbsp;separated&amp;nbsp;with&amp;nbsp;a comma "1,5,7".&lt;br /&gt;
&lt;br /&gt;
The resultant merged document was not password protected. To secure a PDF file with a password, one can use the CFPDF tag with the action attribute set to '&lt;i&gt;protect&lt;/i&gt;':&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfpdf action="protect"  
     source="merged.pdf"  
     newuserpassword="test"&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-450334571318851288?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/vN7p2y__0TY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/450334571318851288/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/09/merging-password-protected-pdf-files-in.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/450334571318851288?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/450334571318851288?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/vN7p2y__0TY/merging-password-protected-pdf-files-in.html" title="Merging password protected PDF files in ColdFusion" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/09/merging-password-protected-pdf-files-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8ARno6eip7ImA9WhdVFEg.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-6498508028325552018</id><published>2011-09-20T00:12:00.000+05:30</published><updated>2011-09-20T00:14:07.412+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-20T00:14:07.412+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><title>An odd behavior with localStorage events in HTML5</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cdAmARz3nXKQuuIxmHhkKPFDZ3A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cdAmARz3nXKQuuIxmHhkKPFDZ3A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cdAmARz3nXKQuuIxmHhkKPFDZ3A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cdAmARz3nXKQuuIxmHhkKPFDZ3A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Today I was looking into web storage (localStorage) feature introduced in HTML5. Most of the modern browsers provide means through which key/value pairs can be securely stored and retrieved for later use. Browser cookies can indeed be used for the storage of persistent data but are limited in capacity. Also with cookies, the data is transmitted in every HTTP request thereby making the web applications run slow. Unlike cookies, in local storage there is no limit on the size of the data and it is never transmitted to the web server unless an attempt is made to send it manually. Whenever the data in the storage area changes a '&lt;b&gt;storage&lt;/b&gt;' event is fired. This event is fired whenever the methods setItem(), removeItem(), or clear() are called on the localStorage object.&lt;br /&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
However, when I tried to use these methods to update the localStorage area, the storage event never fired:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;!DOCTYPE html&amp;gt;  
 &amp;lt;html&amp;gt;  
  &amp;lt;head&amp;gt;  
   &amp;lt;title&amp;gt;localStorage Test&amp;lt;/title&amp;gt;  
   &amp;lt;script type="text/javascript" &amp;gt;  
   
    var storageHandler = function () {  
     alert('storage event 1');  
    };  
   
    window.addEventListener("storage", storageHandler, false);  
   
   &amp;lt;/script&amp;gt;  
  &amp;lt;/head&amp;gt;  
  &amp;lt;body&amp;gt;  
         
   &amp;lt;button id="addBtn"  
           onclick="localStorage.setItem('key1','value1')"&amp;gt;  
           Add  
   &amp;lt;/button&amp;gt;  
   &amp;lt;button id="clearBtn"  
           onclick="localStorage.clear()"&amp;gt;  
           Clear  
   &amp;lt;/button&amp;gt;  
  &amp;lt;/body&amp;gt;  
 &amp;lt;/html&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The methods setItem and clear did change the storage area and I confirmed this by referring to the resources &amp;nbsp;section in chrome developer tools. This looked very odd, but on referring to the &lt;a href="http://dev.w3.org/html5/webstorage/#dom-localstorage"&gt;w3c specification&lt;/a&gt; I found this:&amp;nbsp;"&lt;i&gt;When the setItem(), removeItem(), and clear() methods are called on a Storage object x that is associated with a local storage area, if the methods did something, then in every Document object whose Window object's localStorage attribute's Storage object is associated with the same storage area, &lt;b&gt;other than x&lt;/b&gt;, a storage event must be fired&lt;/i&gt;". This meant that, the &lt;i&gt;storage&lt;/i&gt; event would be fired in any other window\tab which used the same storage area.&lt;br /&gt;
&lt;br /&gt;
Now on opening another tab and on clicking the Add\Clear button the localStorage area was affected and a storage event was fired in the other tab; not on the one that invoked the setItem or clear method. In a way this makes sense because the invoking window would already know of event and would perform the necessary action. Windows that share the same storage area would then be notified of the event and can update the DOM or perform the required action.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-6498508028325552018?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/bPvAFqLgGlc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/6498508028325552018/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/09/odd-behavior-with-localstorage-events.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6498508028325552018?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6498508028325552018?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/bPvAFqLgGlc/odd-behavior-with-localstorage-events.html" title="An odd behavior with localStorage events in HTML5" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/09/odd-behavior-with-localstorage-events.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIGQnY9eip7ImA9WhdVEEQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-4282006155141240821</id><published>2011-09-15T18:45:00.000+05:30</published><updated>2011-09-15T18:45:23.862+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-15T18:45:23.862+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CFBuilder" /><title>A Cloud of Productivity features in ColdFusion Builder</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LCa-ttwCY-VEocKHtRe3Hh6gXOY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LCa-ttwCY-VEocKHtRe3Hh6gXOY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LCa-ttwCY-VEocKHtRe3Hh6gXOY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LCa-ttwCY-VEocKHtRe3Hh6gXOY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Yesterday at the ColdFusion Developer Week, I had demonstrated the Productivity features in ColdFusion Builder. Here is a cloud of these features:&amp;nbsp;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-dlt59bk1mZM/TnH3Bt7VgkI/AAAAAAAADu8/aDAhMmDDkvY/s1600/Productivity-Features3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-dlt59bk1mZM/TnH3Bt7VgkI/AAAAAAAADu8/aDAhMmDDkvY/s1600/Productivity-Features3.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-4282006155141240821?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/cnl7-Azc6wE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/4282006155141240821/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/09/cloud-of-productivity-features-in.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/4282006155141240821?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/4282006155141240821?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/cnl7-Azc6wE/cloud-of-productivity-features-in.html" title="A Cloud of Productivity features in ColdFusion Builder" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-dlt59bk1mZM/TnH3Bt7VgkI/AAAAAAAADu8/aDAhMmDDkvY/s72-c/Productivity-Features3.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/09/cloud-of-productivity-features-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YBR3szeSp7ImA9WhdXEUQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-1009588854608639325</id><published>2011-08-24T19:42:00.000+05:30</published><updated>2011-08-24T19:42:36.581+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-24T19:42:36.581+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Events" /><title>Speaking at Adobe ColdFusion Developer Week</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WFH-A92n9bxzIrNnKgiTLuP18Us/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WFH-A92n9bxzIrNnKgiTLuP18Us/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WFH-A92n9bxzIrNnKgiTLuP18Us/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WFH-A92n9bxzIrNnKgiTLuP18Us/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;The Adobe ColdFusion Developer Week is here and is scheduled from 12th of September to 16th of September 2011. I'm pleased to announce that I'll be speaking on Wednesday, 14th of September and my session title is &lt;b&gt;'ColdFusion Builder: The Professional IDE to Boost Your Productivity'&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
This session would focus on how you can get started with using ColdFusion Builder and productivity features that would enable you to develop ColdFusion applications in no time. I'll also be demonstrating the new features that have been introduced in ColdFusion Builder 2.0.&lt;br /&gt;
&lt;br /&gt;
You can register for the session here -&amp;nbsp;&lt;a href="http://www.adobe.com/cfusion/event/index.cfm?event=detail&amp;amp;id=1489920&amp;amp;loc=en_us"&gt;http://www.adobe.com/cfusion/event/index.cfm?event=detail&amp;amp;id=1489920&amp;amp;loc=en_us&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-1009588854608639325?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/krYH3Byeonc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/1009588854608639325/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/08/speaking-at-adobe-coldfusion-developer.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/1009588854608639325?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/1009588854608639325?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/krYH3Byeonc/speaking-at-adobe-coldfusion-developer.html" title="Speaking at Adobe ColdFusion Developer Week" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/08/speaking-at-adobe-coldfusion-developer.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQXY9fSp7ImA9WhRTEkQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-6237791911967498833</id><published>2011-08-09T20:41:00.000+05:30</published><updated>2011-11-03T09:26:40.865+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T09:26:40.865+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript/jQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><category scheme="http://www.blogger.com/atom/ns#" term="Kiss My App" /><title>Kiss My App: Collaborating using HTML5 Canvas and WebSockets</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zB5J-59NbZN5gE9SLZTp86hI76M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zB5J-59NbZN5gE9SLZTp86hI76M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zB5J-59NbZN5gE9SLZTp86hI76M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zB5J-59NbZN5gE9SLZTp86hI76M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;The Canvas element introduced in HTML5 is the most talked about feature in HTML5. It allows a developer to draw on a rectangular area and the ability to control each pixel in it. I'm not a very big fan of powerful graphics and animation on the web, however I wanted to try Canvas in conjunction with another popular feature  - Web Sockets. The idea is to use the mouse events to draw on the Canvas and then send the coordinates to remote clients using Web Sockets. I have used the &lt;a href="http://pusher.com/"&gt;pusherapp &lt;/a&gt;Web Socket library in my example and this video shows how two clients can play a Tic-Tac-Toe game:&lt;br /&gt;
&lt;br /&gt;
&lt;object data="http://content.screencast.com/users/SagarGanatra/folders/Default/media/c536a848-9204-4bd1-9536-c12d97648d4b/bootstrap.swf" height="500" id="scPlayer" type="application/x-shockwave-flash" width="700"&gt;  &lt;param name="movie" value="http://content.screencast.com/users/SagarGanatra/folders/Default/media/c536a848-9204-4bd1-9536-c12d97648d4b/bootstrap.swf" /&gt;


&lt;param name="quality" value="high" /&gt;


&lt;param name="bgcolor" value="#FFFFFF" /&gt;


&lt;param name="flashVars" value="thumb=http://content.screencast.com/users/SagarGanatra/folders/Default/media/c536a848-9204-4bd1-9536-c12d97648d4b/FirstFrame.jpg&amp;containerwidth=700&amp;containerheight=500&amp;content=http://content.screencast.com/users/SagarGanatra/folders/Default/media/c536a848-9204-4bd1-9536-c12d97648d4b/TicTacToe.swf&amp;blurover=false" /&gt;


&lt;param name="allowFullScreen" value="true" /&gt;


&lt;param name="scale" value="showall" /&gt;


&lt;param name="allowScriptAccess" value="always" /&gt;


&lt;param name="base" value="http://content.screencast.com/users/SagarGanatra/folders/Default/media/c536a848-9204-4bd1-9536-c12d97648d4b/" /&gt;


Unable to display content. Adobe Flash is required. &lt;/object&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.blogger.com/blogger.g?blogID=8417810603086728638" name="more"&gt;&lt;/a&gt;&lt;br /&gt;
As you can see in this video, the mouse movements made on the canvas will draw lines on it and also cause lines to be drawn on another browser window.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;HOW?:&lt;/b&gt;
&lt;br /&gt;
There are various event handlers that can be used with the Canvas element. The one that I have used in this application are the mousedown and the mousemove events. When the user clicks on the Canvas the mousedown event is invoked. The point at the which the mouse was clicked will be marked as the starting point for the line. Now, when one moves the mouse, the mousemove event is invoked. The movement of mouse will then be used to draw the line on the canvas. The next mouse click is then used to mark the end of drawing and any mouse movement will not cause lines to be drawn on the Canvas. This is particularly useful when you want to draw multiple shapes or letters on the Canvas. To start drawing again click anywhere on the Canvas to mark the start point.&lt;br /&gt;
&lt;br /&gt;
In both the cases i.e. on mouseclick and mousemove events, the X and Y coordinates along with the event type is sent over the Web Socket. On receiving the message on the Web Socket, the corresponding action is performed.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Code:&lt;/b&gt;&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt;
      var canvas, ctx, socket, clicked = true;  
     var oldX = 0, oldY = 0;  
      socket = new Pusher('{api_key}', 'test_channel');  
     /*  
      * Initialize the Canvas   
      * set the line width  
      * and add event listeners - mousedown and mousemove   
      */  
     $(document).ready(function(){  
         canvas = document.getElementById('myCanvas');  
         ctx = canvas.getContext('2d');  
         ctx.lineWidth = "6";  
          canvas.addEventListener('mousedown', drawOnCanvas, false);  
         canvas.addEventListener('mousemove', drawOnCanvas, false);  
     });  
     /*  
      * Function to be invoked when a mousedown or a mousemove event is received  
      */  
     function drawOnCanvas(evt){  
     /*  
      * Post a HTTP request to the server on mousedown and mousemove events.  
      * Post a HTTP request for mousemove only when the mouse is clicked.  
      */  
     if (evt.type == 'mousedown' || !(clicked)) {  
           $.post('send.cfm', {  
                x: evt.x,  
                y: evt.y,  
                eventType: evt.type  
           });  
        }  
     }  
     /*  
      * Bind the socket to an event  
      */  
     socket.bind('test_event', function(data){  
          if (data.eventType == 'mousedown') {  
          /*  
           * Change the start position to the coordinate where the mouse was clicked  
           * Set clicked to false, so that the next mousemove event can send the request to Pusher. See below.  
           */  
          if(clicked) {  
                ctx.moveTo(oldX, oldY);  
                clicked = false;  
          }  
          /*  
           * On second click, stop drawing any more lines on the Canvas until the next mousedown event is received.  
           * This is used to mark an end of a character or a diagram on the Canvas. Allows user to draw multiple characters or diagrams  
           */  
           else {  
                clicked = true;  
           }  
      }  
      /*  
       * In case of a mousemove event draw the line  
       */  
      else if(!clicked){  
           ctx.beginPath();  
           ctx.moveTo(oldX, oldY);  
           ctx.lineTo(data.x, data.y);  
           ctx.stroke();  
           clicked=false;  
      }  
      /*  
       * Update the next start position  
       */  
      oldX = data.x;  
      oldY = data.y;          
 });  
 
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The performance of this application depends on the network speed. If you do see the application running slow, you can change the behavior such that the line is drawn if the difference between the new and the old coordinates is greater than some value.&lt;br /&gt;
&lt;br /&gt;
Download code -&amp;nbsp;&lt;a href="http://goo.gl/tDDkY"&gt;http://goo.gl/tDDkY&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-6237791911967498833?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/-kn373M431s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/6237791911967498833/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/08/kiss-my-app-collaborating-using-html5.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6237791911967498833?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6237791911967498833?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/-kn373M431s/kiss-my-app-collaborating-using-html5.html" title="Kiss My App: Collaborating using HTML5 Canvas and WebSockets" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/08/kiss-my-app-collaborating-using-html5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYDQX4ycSp7ImA9WhdSEU0.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-4413119932419405171</id><published>2011-07-19T23:59:00.000+05:30</published><updated>2011-07-19T23:59:30.099+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-19T23:59:30.099+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ColdFusion" /><title>Using Google Maps Places API and ColdFusion's CFMAP to render places of interests</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UMVnjt1litbEkhi5ZqIf9C5RfGo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UMVnjt1litbEkhi5ZqIf9C5RfGo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UMVnjt1litbEkhi5ZqIf9C5RfGo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UMVnjt1litbEkhi5ZqIf9C5RfGo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Google announced the Places API recently at Google I/O (2011) and I was looking into this, to see how this API can be used in conjunction with ColdFusion maps created with CFMAP. The Places API can be used to retrieve place information which includes:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Places of interests such as parks, restaurants, hospitals which are nearby to the users location.&lt;/li&gt;
&lt;li&gt;More detailed information on the place, such as the address, phone number etc,.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
The API can also be used to perform check-in at a particular place and to add\delete a place. These check-ins can then be used to evaluate&amp;nbsp;the popularity of the place. In this post I'll explain how to retrieve the places of interests and displaying the same on a ColdFusion map using CFMAP.&lt;/div&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Place Search Requests - retrieving the places of interests near a user's location:&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
You can send a HTTP request to the URL of the form:&lt;/div&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="color: blue;"&gt;https://maps.googleapis.com/maps/api/place/search/&lt;i&gt;output&lt;/i&gt;?&lt;i&gt;parameters&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here the user has an option of specifying the &lt;i&gt;output &lt;/i&gt;format as either &lt;i&gt;json &lt;/i&gt;or &lt;i&gt;xml &lt;/i&gt;and is required to pass a few parameters:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;key &lt;/i&gt;(required): The application's API key. The Places API uses this information to identify your application.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;location &lt;/i&gt;(required): This will be the latitude and longitude information of a particular place around which the places of interests are to be found.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;radius&lt;/i&gt;&amp;nbsp;(required): to specify the radius within which the places of interests are to be found. The value specified will be considered in meters.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;sensor&lt;/i&gt;&amp;nbsp;(required): to indicate whether the place request is from a device using the location sensor. It can be either true or false.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;types &lt;/i&gt;(optional): the user might be interested in various types of businesses such as library, park, gym etc,. You can also specify multiple types which are separated by a '|' (type1|type2|type3).&lt;/li&gt;
&lt;li&gt;&lt;i&gt;name &lt;/i&gt;(optional): A term to be matched against the names of places. This will restrict the results to contain only those with the specified name.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;language&lt;/i&gt;&amp;nbsp;(optional): The language code to indicate the language in which the results are to be returned.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
With the above information, you can issue a HTTP request using ColdFusion's&amp;nbsp;&lt;i&gt;cfhttp &lt;/i&gt;tag:&lt;/div&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfhttp url="https://maps.googleapis.com/maps/api/place/search/json"  
         method="get"  
         result="gmapData"&amp;gt;  

      &amp;lt;cfhttpparam type="url"  
                   name="location"  
                   value="-33.8670522,151.1957362"&amp;gt;  
      &amp;lt;cfhttpparam type="url"  
                   name="types"  
                   value="doctor|book_store"&amp;gt;  
      &amp;lt;cfhttpparam type="url"  
                   name="radius"  
                   value="2000"&amp;gt;  
      &amp;lt;cfhttpparam type="url"  
                   name="sensor"  
                   value="false"&amp;gt;  
      &amp;lt;cfhttpparam type="url"  
                   name="key"  
                   value="{API_Key}"&amp;gt;  
 &amp;lt;/cfhttp&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
For the purpose of this example, I have specified the latitude and longitude values for 'Sydney, Australia' (I've lived here!!) and have specified the type of business as doctor and book_store. The radius is specified as 2000 meters (2 Kms) and the sensor is set to false. The output format is specified as &lt;i&gt;json&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
The &lt;i&gt;json &lt;/i&gt;response would contain three root elements: status, results and html_attributions. If there were no errors in performing the request operation and the response contained at least one result then the response status is set to "OK". The result element is an array of places sent in response to a request, this would include the place &lt;i&gt;name&lt;/i&gt;, its &lt;i&gt;geometry &lt;/i&gt;(latitude and longitude information), place &lt;i&gt;id&lt;/i&gt;, &lt;i&gt;reference&lt;/i&gt;, &lt;i&gt;icon&lt;/i&gt;, &lt;i&gt;types&lt;/i&gt;, &lt;i&gt;vicinity&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
The results array in the response can then be used to add places to the ColdFusion's map. However, on a Google Map when a user clicks on a location a popup is shown which includes the Address and the Phone number of the selected location. To get more details on a particular location, another request should be made to retrieve the place details such as address, phone number, rating.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Place Detail requests - retrieve place details:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Similar to the previous one, the HTTP request to retrieve the place details is:&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="color: blue;"&gt;https://maps.googleapis.com/maps/api/place/details/output?parameters&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, &lt;i&gt;output&lt;/i&gt; can be either &lt;i&gt;json&lt;/i&gt; or &lt;i&gt;xml&lt;/i&gt;. The &lt;i&gt;reference&lt;/i&gt; value obtained from the previous HTTP call (Place Search request) is then passed as a parameter to retrieve the place details. Other required parameters include the &lt;i&gt;sensor&lt;/i&gt; and the &lt;i&gt;key&lt;/i&gt;. The &lt;i&gt;cfhttp &lt;/i&gt;request to get the details is of the form:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfloop array="#arrayResults#"  
         index="placesObject"&amp;gt;  
      &amp;lt;cfhttp url="https://maps.googleapis.com/maps/api/place/details/json"  
              method="get"  
              result="placeDetails"&amp;gt;  
           &amp;lt;cfhttpparam type="url"  
                        name="reference"  
                        value="#placesObject.reference#"&amp;gt;  
           &amp;lt;cfhttpparam type="url"  
                        name="sensor"  
                        value="false"&amp;gt;  
           &amp;lt;cfhttpparam type="url"  
                        name="key"  
                        value="{API_Key}"&amp;gt;  
      &amp;lt;/cfhttp&amp;gt;  
      &amp;lt;cfset placeDetails = #deserializeJSON(placeDetails.fileContent).result#&amp;gt;  
      &amp;lt;cfset arrayAppend(windowContent,   
                "&amp;lt;h3&amp;gt;" &amp;amp; placeDetails.name &amp;amp; "&amp;lt;/h3&amp;gt;&amp;lt;br&amp;gt;&amp;lt;h5&amp;gt;" &amp;amp; placeDetails.formatted_address &amp;amp;   
 "&amp;lt;br&amp;gt;Phone: " &amp;amp; placeDetails.formatted_phone_number &amp;amp; "&amp;lt;/h5&amp;gt;")/&amp;gt;  
 &amp;lt;/cfloop&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
As seen in the above code, the &lt;i&gt;arrayResults &lt;/i&gt;containing the results of the place search request is iterated in the cfloop tag. The &lt;i&gt;reference &lt;/i&gt;value in the &lt;i&gt;arrayResults &lt;/i&gt;is then used in each iteration to get the place details. The place details are then used populate the &lt;i&gt;windowContent&lt;/i&gt;&amp;nbsp;array, which contains the html markup to show when the user clicks on any of the map item.&lt;br /&gt;
&lt;br /&gt;
The CFMAP and CFMAPITEM tag can then be used to render a Google map and add places of interests to the map:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfmap name="myMap"  
        centerlatitude="-33.8670522"  
        centerlongitude="151.1957362"  
        tip="Sydney"  
        width="800"  
        height="700"  
        zoomlevel="16"&amp;gt;  
      &amp;lt;cfloop array="#arrayResults#"  
             index="mapObject"&amp;gt;  
           &amp;lt;cfmapitem name="#mapObject.name#"  
                      latitude="#mapObject.geometry.location.lat#"  
                      longitude="#mapObject.geometry.location.lng#"  
                      tip="#mapObject.name#"  
                      markerwindowcontent="#windowContent[count++]#"  
                      markericon="#mapObject.icon#"&amp;gt;  
      &amp;lt;/cfloop&amp;gt;  
 &amp;lt;/cfmap&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The CFMAPITEM tag is used to add places of interests on the map using the latitude and longitude information obtained from the place search request. The &lt;i&gt;markerwindowcontent &lt;/i&gt;attribute would contain the address and the phone number information obtained from place detail request. The map rendered would look similar to the one shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-q2PcRPsUsnY/TiXLfok3WCI/AAAAAAAADtQ/OuqfG0Kre2c/s1600/CFMAP_Places.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-q2PcRPsUsnY/TiXLfok3WCI/AAAAAAAADtQ/OuqfG0Kre2c/s1600/CFMAP_Places.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-4413119932419405171?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/snSLsPs96TA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/4413119932419405171/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/07/using-google-maps-places-api-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/4413119932419405171?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/4413119932419405171?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/snSLsPs96TA/using-google-maps-places-api-and.html" title="Using Google Maps Places API and ColdFusion's CFMAP to render places of interests" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-q2PcRPsUsnY/TiXLfok3WCI/AAAAAAAADtQ/OuqfG0Kre2c/s72-c/CFMAP_Places.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/07/using-google-maps-places-api-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUHQXYyeyp7ImA9WhRWEUU.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-1905005697671340573</id><published>2011-07-08T20:41:00.030+05:30</published><updated>2011-12-29T23:07:10.893+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-29T23:07:10.893+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><title>Custom validation messages for HTML5 Input elements using the constraint validation API</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cF_MDEBRdDh2SIip8TuwQHUBGF8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cF_MDEBRdDh2SIip8TuwQHUBGF8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cF_MDEBRdDh2SIip8TuwQHUBGF8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cF_MDEBRdDh2SIip8TuwQHUBGF8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;HTML5 has introduced several input types such as EMAIL, URL, RANGE, SEARCH, DATE, TIME, etc,. Most of the modern browsers have implemented them and are ready to be used in a HTML document. Another exciting feature introduced in HTML5 is the form validation. Instead of writing JavaScript to validate users input, browsers can now validate it and show an appropriate message if the validation fails. The validation message is shown in line with the field for which the validation has failed. The default error message is shown when the validation fails. In this post I'll explain how these error messages can be changed.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Take an example of a form that has an input element with type="email" and a submit button:&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt;
&amp;lt;form id="myForm"&amp;gt;
&amp;lt;input id="eid" name="email_field" type="email" /&amp;gt;
&amp;lt;input type="submit" /&amp;gt;
&amp;lt;/form&amp;gt;


&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
After entering some text in the input field and on clicking the submit button, the default validation message is shown:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/-HK_Ieu_k8nw/Thb_uMzuTwI/AAAAAAAADqM/w9FbALopUqk/s1600/default_email.png" imageanchor="1" style="clear: left; display: inline !important; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-HK_Ieu_k8nw/Thb_uMzuTwI/AAAAAAAADqM/w9FbALopUqk/s1600/default_email.png" /&gt;&lt;/a&gt;The message style varies from browser to browser and the one shown in this picture is taken from Google's Chrome browser.&lt;br /&gt;
&lt;br /&gt;
As you can see, message "Please enter an email address." is shown when the user enters an invalid email address and clicks the submit button. This message is shown inline with the input field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To show a custom message, instead of default one the &lt;a href="http://dev.w3.org/html5/spec/association-of-controls-and-forms.html#the-constraint-validation-api"&gt;constraint validation API&lt;/a&gt; is used. Here the user can set the custom validation message using &lt;i&gt;element.setCustomValidity(message)&lt;/i&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt;function check(input) {  
    if(&lt;b&gt;input.validity.typeMismatch&lt;/b&gt;){  
        &lt;b&gt;input.setCustomValidity("Dude '" + input.value + "' is not a valid email. Enter something nice!!");&lt;/b&gt;  
    }  
    else {  
        input.setCustomValidity("");  
    }                 
}  &lt;/code&gt;&lt;/pre&gt;From the code, the function &lt;i&gt;check &lt;/i&gt;accepts a HTMLInputElement (&lt;i&gt;input&lt;/i&gt;) as a parameter and checks for the validity of the input text entered against its type using &lt;b style="font-style: italic;"&gt;input.validity.typeMismatch&lt;/b&gt;. It is set to true if the entered text doesn't match the specified input type. The &lt;i&gt;&lt;b&gt;input.setCustomValidity(message)&lt;/b&gt;&lt;/i&gt; is then used to set the validation message. Now whenever the validation fails the custom message will be shown:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-USt77uExikI/ThcHNdvADTI/AAAAAAAADqQ/DQbtkivl1gA/s1600/custom_email.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-USt77uExikI/ThcHNdvADTI/AAAAAAAADqQ/DQbtkivl1gA/s1600/custom_email.png" /&gt;&lt;/a&gt;&lt;/div&gt;Similarly the &lt;a href="http://www.custompc.ie"&gt;custom&lt;/a&gt; validation message can be set in various conditions, such as required filed not entered - &lt;i&gt;&lt;b&gt;element.validity.valueMissing&lt;/b&gt;&lt;/i&gt;, element value doesn't match the pattern - &lt;b style="font-style: italic;"&gt;element.validity.patternMismatch&lt;/b&gt;, value is lower than the provided minimum - &lt;b style="font-style: italic;"&gt;element.validity.rangeUnderflow&lt;/b&gt;, value is higher than the maximum - &lt;b style="font-style: italic;"&gt;element.validity.rangeOverflow&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
One can set such validation messages in various use cases as well. Say, when the entered text is not one of the expected values or when the confirmation email address doesn't match with the original email address. In such cases showing a &lt;a href="http://www.custompc.ie"&gt;custom&lt;/a&gt; validation message comes very handy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-1905005697671340573?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/Tvzx2I4cBo8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/1905005697671340573/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/07/custom-validation-messages-for-html5.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/1905005697671340573?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/1905005697671340573?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/Tvzx2I4cBo8/custom-validation-messages-for-html5.html" title="Custom validation messages for HTML5 Input elements using the constraint validation API" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-HK_Ieu_k8nw/Thb_uMzuTwI/AAAAAAAADqM/w9FbALopUqk/s72-c/default_email.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/07/custom-validation-messages-for-html5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAAQ3c8eSp7ImA9WhdTEU8.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-8590834861360528381</id><published>2011-07-07T23:05:00.002+05:30</published><updated>2011-07-08T16:45:42.971+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-08T16:45:42.971+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><title>Submitting Form using FormData object in HTML5 using XmlHttpRequest Level 2</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SpDoBrO2UxGoxl3batoUV_Xn0KM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SpDoBrO2UxGoxl3batoUV_Xn0KM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SpDoBrO2UxGoxl3batoUV_Xn0KM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SpDoBrO2UxGoxl3batoUV_Xn0KM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The other day I had posted on &lt;a href="http://www.sagarganatra.com/2011/04/file-upload-and-progress-events-with.html"&gt;uploading a file using XmlHttpRequest 2&lt;/a&gt; and tracking the progress of the file upload process using the progress event on XHR2 object and the progress tag. Another enhancement added to the XHR2 specification is the introduction of FormData object. Using the FormData object, one can create a set of key-value pairs and send them as form data in a XHR request. The FormData object is passed in the send() method of the XHR object:&lt;/span&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; var formObject = new FormData();  
 formObject.append("element_1","Sagar");  
 formObject.append("element_2","Ganatra");  
   
 var xhrObject = new XMLHttpRequest();  
 xhrObject.open("POST","postform.cfm");  
 xhrObject.send(formObject);  
&lt;/code&gt;&lt;/pre&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;This means that, one need not add the form element to the document and can avoid using hidden input element (type="hidden") to send the additional key-value data to the server for processing.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;It is also possible to add additional data to an already existing form in the document and send the form data to the server:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; var docFormElement = document.getElementById('myForm');  
 var docFormData = new FormData(docFormElement);  
 &lt;b&gt;docFormData.append("product_license","Enterprise");&lt;/b&gt;
 var xhrObject = new XMLHttpRequest();  
 xhrObject.open("POST","postform.cfm");  
 xhrObject.send(docFormData);

 &amp;lt;form id="myForm"&amp;gt;  
   &amp;lt;input name="product_name" type="text" value="ColdFusion" /&amp;gt;  
   &amp;lt;input name="product_codename" type="text" value="Zeus" /&amp;gt;  
 &amp;lt;/form&amp;gt;  

&lt;/code&gt;&lt;/pre&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The FormData constructor takes the form element as an argument and then the append function is used to add another key-value data to the FormData object.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-8590834861360528381?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/CdcnkNKqPKE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/8590834861360528381/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/07/submitting-form-using-formdata-object.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/8590834861360528381?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/8590834861360528381?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/CdcnkNKqPKE/submitting-form-using-formdata-object.html" title="Submitting Form using FormData object in HTML5 using XmlHttpRequest Level 2" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/07/submitting-form-using-formdata-object.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MDRn85eSp7ImA9WhdRGU0.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-6268137311228688384</id><published>2011-06-20T20:41:00.007+05:30</published><updated>2011-08-09T22:34:37.121+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-09T22:34:37.121+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CFBuilder" /><title>Auto Insertion of Tag attributes and Function arguments in ColdFusion Builder 2</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vEg9AKE82LVhjFMuvqHjxBtpB18/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vEg9AKE82LVhjFMuvqHjxBtpB18/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vEg9AKE82LVhjFMuvqHjxBtpB18/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vEg9AKE82LVhjFMuvqHjxBtpB18/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;The Editor is the most important feature in an IDE and the code assist features in the Editor helps in developing applications quickly and hence help in increasing the productivity. One of features is the 'auto insertion of tag attributes'. Most of the tags in ColdFusion have a mandatory attribute, for example the attribute 'name' is mandatory when using the &lt;i&gt;cffunction &lt;/i&gt;tag. In ColdFusion Builder 2, these attributes are auto inserted i.e. when a user types in the &lt;i&gt;cffunction &lt;/i&gt;tag and invokes code assist (using CTRL + SPACE) the &lt;i&gt;name &lt;/i&gt;attribute is auto inserted.&lt;br /&gt;
&lt;br /&gt;
Auto insertion also works for function arguments wherein the required arguments are auto inserted.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;&lt;b&gt;Auto Insertion of Tag attributes&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;As explained above, the mandatory attributes are auto inserted whenever the code assist is invoked for tags such as &lt;i&gt;cffunction&lt;/i&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-mNRDFgo5_tE/Tf8gKmGCYXI/AAAAAAAADpQ/ohTJouWkS-8/s1600/CodeAssist_cffunction.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-mNRDFgo5_tE/Tf8gKmGCYXI/AAAAAAAADpQ/ohTJouWkS-8/s1600/CodeAssist_cffunction.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;In the above picture, code assist for &lt;i&gt;cffunction &lt;/i&gt;is invoked and the tag is selected from the list. This would auto insert the required attribute 'name':&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-zqvShkHlTh0/Tf8hsISzWII/AAAAAAAADpU/wJ6XUi5mzjI/s1600/CodeAssist_cffunction_inserted.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-zqvShkHlTh0/Tf8hsISzWII/AAAAAAAADpU/wJ6XUi5mzjI/s1600/CodeAssist_cffunction_inserted.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;There are some tags such as cfpdf, cfimage wherein a few attributes become mandatory when one of the attributes' value is specified. For example, in case of &lt;i&gt;cfimage &lt;/i&gt;when the &lt;i&gt;action &lt;/i&gt;attribute is specified as 'convert', the attributes &lt;i&gt;destination &lt;/i&gt;and &lt;i&gt;source &lt;/i&gt;become mandatory and are auto inserted:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-g5rhgM7Cp3w/Tf8j4gSdhRI/AAAAAAAADpY/00rnjP2_LXw/s1600/CodeAssist_cfimage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-g5rhgM7Cp3w/Tf8j4gSdhRI/AAAAAAAADpY/00rnjP2_LXw/s1600/CodeAssist_cfimage.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Now on selecting the action attributes' value as &lt;i&gt;convert&lt;/i&gt;,&lt;i&gt; &lt;/i&gt;the attributes &lt;i&gt;destination &lt;/i&gt;and &lt;i&gt;source&lt;/i&gt; are auto inserted:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ybB-3UCTsxU/Tf8kfJ7hLZI/AAAAAAAADpc/bvG7mpmaTfw/s1600/CodeAssist_cfimage_convert.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-ybB-3UCTsxU/Tf8kfJ7hLZI/AAAAAAAADpc/bvG7mpmaTfw/s1600/CodeAssist_cfimage_convert.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;If the user selects action attributes' value as &lt;i&gt;rotate&lt;/i&gt;,&lt;i&gt; &lt;/i&gt;then the attributes &lt;i&gt;angle &lt;/i&gt;and &lt;i&gt;source&lt;/i&gt; are auto inserted:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-5ji8dTEtFx8/Tf8lYOPGPqI/AAAAAAAADpg/mdmAdIrHINs/s1600/CodeAssist_cfimage_rotate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-5ji8dTEtFx8/Tf8lYOPGPqI/AAAAAAAADpg/mdmAdIrHINs/s1600/CodeAssist_cfimage_rotate.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Another thing to note here is that, after inserting the required attributes the cursor is positioned such that one can go about specifying the next attributes' value.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;auto Insertion of required function arguments&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Whenever one tries to invoke a built-in function or a user defined function the required arguments are auto inserted. For example, consider a function &lt;i&gt;foo &lt;/i&gt;which takes three arguments, of which the first two arguments are mandatory:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-WNQVwkuwzIo/Tf8q5B4eidI/AAAAAAAADpk/SbMn8d_Zauc/s1600/CodeAssist_function_arguments.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-WNQVwkuwzIo/Tf8q5B4eidI/AAAAAAAADpk/SbMn8d_Zauc/s1600/CodeAssist_function_arguments.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;When this function is invoked using code assist, the required arguments are auto inserted. As seen above, arguments arg1 and arg2 are marked as required and are auto inserted when the function is invoked. After inserting the required arguments the first argument is selected so that the user can go about specifying a value for the argument. The tooltip here shows the list of arguments that the function accepts along with the argument type. The last argument - arg3 is marked optional and is surrounded by square brackets indicating that it is optional. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-6268137311228688384?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/oDXLkyv-IZY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/6268137311228688384/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/06/auto-insertion-of-tag-attributes-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6268137311228688384?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/6268137311228688384?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/oDXLkyv-IZY/auto-insertion-of-tag-attributes-and.html" title="Auto Insertion of Tag attributes and Function arguments in ColdFusion Builder 2" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-mNRDFgo5_tE/Tf8gKmGCYXI/AAAAAAAADpQ/ohTJouWkS-8/s72-c/CodeAssist_cffunction.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/06/auto-insertion-of-tag-attributes-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQXY8eip7ImA9WhRTEkQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-7545404197331211926</id><published>2011-06-17T18:03:00.000+05:30</published><updated>2011-11-03T09:26:40.872+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T09:26:40.872+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript/jQuery" /><title>De-obfuscating javascript code in Chrome Developer Tools</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0VvnCs5W63iLkWnzaid8k2eaxHI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0VvnCs5W63iLkWnzaid8k2eaxHI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0VvnCs5W63iLkWnzaid8k2eaxHI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0VvnCs5W63iLkWnzaid8k2eaxHI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I had blogged about &lt;a href="http://fusioned.blogspot.com/2011/05/javascript-debugging-with-chrome.html"&gt;JavaScript debugging with Chrome Developer Tools&lt;/a&gt;&amp;nbsp;some time back, wherein I have explained how these developer tools can help in debugging javascript code.&amp;nbsp;Today Google Chrome 12 was released and my Chrome browser was updated to this version. As with every release, there have been some improvements made on performance, usability etc,. One feature that stood out for me is the ability to De-obfuscate the javascript code.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;b&gt;What is Minification?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Minification is the process of removing unnecessary characters such as white spaces, comments, new lines from the source code. These otherwise would be added to make the code more readable. Minifying the source code helps in reducing the file size and thereby reducing the time taken to download the file. This is the reason why most of the popular javascript libraries such as &lt;i&gt;jQuery&lt;/i&gt; are minified. A minified jQuery file is of 31 KB in size where as an uncompressed one is about 229 KB. Unfortunately, debugging minified javascript files is an impossible task.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
With the latest version of Google Chrome one can choose to de-obfuscate the javascript code right with in the developer tools. This is how the jquery.js file would look before de-obfuscation:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-rjLzbeg4u6o/Tfs-8EJmfxI/AAAAAAAADoU/h9KWZTS20dQ/s1600/jquery_before_deobfuscation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-rjLzbeg4u6o/Tfs-8EJmfxI/AAAAAAAADoU/h9KWZTS20dQ/s1600/jquery_before_deobfuscation.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now, to de-obfuscate the code one can right click on the file and select the 'De-obfuscate Source' option. This would de-obfuscate the javascript code and present the code which is readable and ready to debug:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-pMjneep1Ni8/Tfs_DbxsbgI/AAAAAAAADoY/Ee4vxfQXbfQ/s1600/jquery_after_deobfuscation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-pMjneep1Ni8/Tfs_DbxsbgI/AAAAAAAADoY/Ee4vxfQXbfQ/s1600/jquery_after_deobfuscation.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
Update:&lt;br /&gt;
&lt;br /&gt;
This post was written when Chrome 12 was released. In recent versions, this option is available as a button - 'pretty print', at the bottom left corner of the screen. Look for the button with the icon '{ }'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-7545404197331211926?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/nk43A2oZ95E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/7545404197331211926/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/06/de-obfuscating-javascript-code-in.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/7545404197331211926?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/7545404197331211926?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/nk43A2oZ95E/de-obfuscating-javascript-code-in.html" title="De-obfuscating javascript code in Chrome Developer Tools" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-rjLzbeg4u6o/Tfs-8EJmfxI/AAAAAAAADoU/h9KWZTS20dQ/s72-c/jquery_before_deobfuscation.png" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/06/de-obfuscating-javascript-code-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQXY_fip7ImA9WhRTEkQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-3299840608664193859</id><published>2011-06-08T23:39:00.000+05:30</published><updated>2011-11-03T09:26:40.846+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T09:26:40.846+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript/jQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><title>Getting notifications of Network Status changes using online and offline events introduced in HTML5</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/EL11oxjLT2mf76VP86B_6RN6HoI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EL11oxjLT2mf76VP86B_6RN6HoI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/EL11oxjLT2mf76VP86B_6RN6HoI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EL11oxjLT2mf76VP86B_6RN6HoI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I was working on an online\offline application, wherein I wanted to display a set of records stored in the local database to the user when he goes offline. The only way to determine the network status is to send a XHR request to the server at particular time intervals (polling). If the server responds back with some data it is understood that the user is online. However, I came across two event listeners 'ononline' and 'onoffline' which are triggered when the network status changes.&lt;br /&gt;
&lt;div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Sample Code:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;These event listeners are not supported in every browser, I have tested this on Chrome 11 and it works great. Here is the code snippet that I have used in my application:&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;script&amp;gt;  
           function showOnlineStatus(){  
           var status = document.getElementById('userStatus');  
           if(navigator.onLine)  
                status.innerHTML = status.className = 'online';  
           else  
                status.innerHTML = status.className = 'offline';  
           }  
   
           window.onload = window.ononline = window.onoffline = showOnlineStatus;  
 &amp;lt;/script&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
As seen in the above code, the navigator object has an attribute onLine which is used to determine network status. It is set to true if the user is online and false otherwise. To test this, unplug the network cable and see that the offline event gets triggered. On connecting the network cable the online event would be triggered.&lt;br /&gt;
&lt;div id="userStatus"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-3299840608664193859?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/hAVWnbEJW68" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/3299840608664193859/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/06/getting-notifications-of-network-status.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3299840608664193859?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3299840608664193859?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/hAVWnbEJW68/getting-notifications-of-network-status.html" title="Getting notifications of Network Status changes using online and offline events introduced in HTML5" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>3</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/06/getting-notifications-of-network-status.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEAQHk6fSp7ImA9WhZUEE8.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-4775346482402357991</id><published>2011-06-02T19:20:00.000+05:30</published><updated>2011-06-02T19:20:41.715+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-02T19:20:41.715+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><category scheme="http://www.blogger.com/atom/ns#" term="ColdFusion" /><title>ColdFusion's CFDIV tag can be used to output HTML5's semantic tags</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WkhUd8cM5VBS9wVZX43fO-7jPKM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WkhUd8cM5VBS9wVZX43fO-7jPKM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WkhUd8cM5VBS9wVZX43fO-7jPKM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WkhUd8cM5VBS9wVZX43fO-7jPKM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;HTML5 has introduced several semantic tags such as HEADER, FOOTER, SECTION, ARTICLE, ASIDE, NAV etc,. The rationale behind creating these structural tags is to divide the web pages into logical parts with tags that are descriptive of the type of content they contain. Before HTML5 the &lt;i&gt;div &lt;/i&gt;tags were used in creating blocks of content in a HTML document.&lt;br /&gt;
&lt;br /&gt;
Recently, I was having a conversation with one of my team members from whom I learnt that the CFDIV tag can be used to output these semantic tags.&lt;br /&gt;
&lt;br /&gt;
The CFDIV tag has an attribute&amp;nbsp;&lt;i&gt;'tagname'&lt;/i&gt;. This attribute can be used to specify the HTML container tag i.e. one can specify &lt;i&gt;tagname="header" &lt;/i&gt;to output the header tag. Similarly the &lt;i&gt;tagname &lt;/i&gt;attribute can be used to specify other HTML5 semantic tags.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Why should I use CFDIV tag to output the semantic tags?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Well, this is an obvious question you are likely to ask yourself before you write the CFDIV tag. It is not so obvious to one who uses CFDIV tag in their day to day development because CFDIV tag comes with an attribute &lt;i&gt;bind&lt;/i&gt;, which is used to specify a bind expression that returns the container contents. One can dynamically populate the tag contents by specifying the bind expression which can be a CFC function, a URL or even a javascript function. You can refer to the CFDIV tag documentation &lt;a href="http://goo.gl/SnpMr"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-4775346482402357991?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/JHJG42QKoC4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/4775346482402357991/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/06/coldfusions-cfdiv-tag-can-be-used-to.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/4775346482402357991?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/4775346482402357991?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/JHJG42QKoC4/coldfusions-cfdiv-tag-can-be-used-to.html" title="ColdFusion's CFDIV tag can be used to output HTML5's semantic tags" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/06/coldfusions-cfdiv-tag-can-be-used-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQXY9eSp7ImA9WhRTEkQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-483235720052757863</id><published>2011-05-13T23:24:00.001+05:30</published><updated>2011-11-03T09:26:40.861+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T09:26:40.861+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript/jQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><category scheme="http://www.blogger.com/atom/ns#" term="Kiss My App" /><title>Drawing paths on Google Maps, the Indiana Jones way</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/q6B_ok_1CNZQ03AOZtOoalE6HL0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q6B_ok_1CNZQ03AOZtOoalE6HL0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/q6B_ok_1CNZQ03AOZtOoalE6HL0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q6B_ok_1CNZQ03AOZtOoalE6HL0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;I was looking into the Google Maps API the other day and came across some APIs which are really cool. I came up with a use case to show path from the current location to a particular destination entered by the user. I was also trying to achieve that Indiana Jones like effect on the map i.e. to show an animation of the path being drawn on the map.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The idea here is to show the moving path until the destination is reached and also to pan the map accordingly.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;object data="http://content.screencast.com/users/SagarGanatra/folders/Default/media/83278ed5-3d3b-42f3-8c7d-d6c65bedd30d/bootstrap.swf" height="511" id="scPlayer" type="application/x-shockwave-flash" width="600"&gt;  &lt;param name="movie" value="http://content.screencast.com/users/SagarGanatra/folders/Default/media/83278ed5-3d3b-42f3-8c7d-d6c65bedd30d/bootstrap.swf" /&gt;&lt;param name="quality" value="high" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;param name="flashVars" value="thumb=http://content.screencast.com/users/SagarGanatra/folders/Default/media/83278ed5-3d3b-42f3-8c7d-d6c65bedd30d/FirstFrame.jpg&amp;containerwidth=600&amp;containerheight=511&amp;content=http://content.screencast.com/users/SagarGanatra/folders/Default/media/83278ed5-3d3b-42f3-8c7d-d6c65bedd30d/Bangalore_To_NewYork.swf&amp;blurover=false" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="scale" value="showall" /&gt;&lt;param name="allowScriptAccess" value="always" /&gt;&lt;param name="base" value="http://content.screencast.com/users/SagarGanatra/folders/Default/media/83278ed5-3d3b-42f3-8c7d-d6c65bedd30d/" /&gt;Unable to display content. Adobe Flash is required. &lt;/object&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;As seen in the video, a marker is added to the map specifying my current location (Bangalore, India). The current location data is retrieved using the HTML5’s Geolocation API. Once the latitude and longitude information are available, a marker can be added to the map. You can now enter one of your favorite destinations in the text box provided and click the Submit button to see a path drawn from your current location to the destination. The path is drawn using the Google maps ‘Polyline’ API. &lt;/span&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Getting the current location data using HTML5’s Geolocation API:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The Geolocation API allows users share their current location information with trusted sites. You can examine the property navigator.geolocation to see whether the browser supports the Geolocation API. Alternatively, Modernizr can be used to determine the same. All modern browsers support the Geolocation API; however users are required to provide permission to the websites. Once the user has provided the permission, the method getCurrentPosition can be invoked on the navigator.geolocation object:&lt;/span&gt;&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; navigator.geolocation.getCurrentPosition(function(position){  
     var mapElement = document.getElementById('mapelement');  
     startLatitude = position.coords.latitude;  
     startLongitude = position.coords.longitude;  
     mapObj = new google.maps.Map(mapElement,  
     {  
         disableDefaultUI:true,  
         zoom: 3,  
         center: new google.maps.LatLng(startLatitude,startLongitude),  
         mapTypeId: google.maps.MapTypeId.TERRAIN  
     });  
     var markerPosition = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);  
     var startPosition = markerPosition;                                     
     var marker = new google.maps.Marker({position:markerPosition,map:mapObj,title:'You are here'});       
});  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Once the latitude and longitude information is available, they can be used to specify the center address and to add a marker on the map.&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Drawing the path using the Polyline API:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;A polyline is a linear overlay of connected line segments on the map. To draw a line on the map using the Polyline API, you have to pass the map object along with the coordinates specifying the end points as arguments. However, to get the Indiana Jones like effect, you must get as many points between the start and the end location. The latitude and longitude information of these points are then stored in an array and will later be used to achieve the desired effect.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;For the purpose of this example, I’ve assumed 30 animation frames and have calculated the increment:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; function getPathData(destLatitude,destLongitude){  
    var xInc,yInc;  
    xInc = (destLatitude - startLatitude)/30;  
    yInc = (destLongitude - startLongitude)/30;  
    for(var i=0;i&amp;lt;30;i++){  
      path[i] = new google.maps.LatLng(startLatitude += xInc,startLongitude += yInc);       
    }  
 }  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The path array would then contain the latitude and longitude information for the points between the start and the end location. This information can then be used to draw the path and get the desired effect:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; function drawPath(){  
    var polyLine = new google.maps.Polyline({  
                       path: [startPosition,path[positionIndex]],  
                       strokeColor:'#FF0000',  
                       strokeOpacity:2,  
                       strokeWeight:8,  
                   });  
    polyLine.setMap(mapObj);  
    mapObj.panTo(path[positionIndex]);  
    positionIndex = positionIndex + 1;  
    if(positionIndex &amp;lt; 30){  
      setTimeout(drawPath,200);  
    }                            
 }  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;As seen in the above code snippet, the Polyline API is invoked with the arguments path, strokeColor, strokeOpacity, and strokeWeight. Also, the map is panned to the current position while the path is being drawn on the map.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;b&gt;Can I use ColdFusion’s CFMAP tag to get this effect?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;This was the initial idea and I did attempt to get this effect using the CFMAP tag. However, I found that the map object retrieved using the &lt;i&gt;ColdFusion.map.getMapObject&lt;/i&gt; was not compatible with the Polyline API and hence decided to use the Google maps API to get that effect. &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-483235720052757863?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/tBBDpYFTfpU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/483235720052757863/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/05/drawing-paths-on-google-maps-indiana.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/483235720052757863?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/483235720052757863?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/tBBDpYFTfpU/drawing-paths-on-google-maps-indiana.html" title="Drawing paths on Google Maps, the Indiana Jones way" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/05/drawing-paths-on-google-maps-indiana.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQXY-fip7ImA9WhRTEkQ.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-3452643990627451526</id><published>2011-05-09T17:22:00.005+05:30</published><updated>2011-11-03T09:26:40.856+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T09:26:40.856+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript/jQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><category scheme="http://www.blogger.com/atom/ns#" term="ColdFusion" /><title>JavaScript debugging with Chrome Developer Tools and some tips\tricks</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tCFm8gOZkLSACoAWyq-vIhrS6kU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tCFm8gOZkLSACoAWyq-vIhrS6kU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tCFm8gOZkLSACoAWyq-vIhrS6kU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tCFm8gOZkLSACoAWyq-vIhrS6kU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;Last Friday I was having a conversation with &lt;a href="http://www.bennadel.com/"&gt;Ben Nadel &lt;/a&gt;and &lt;span id="goog_1516302617"&gt;&lt;/span&gt;&lt;a href="http://twitter.com/#%21/CFJonJoyce"&gt;Jonothan Joyce&lt;span id="goog_1516302618"&gt;&lt;/span&gt;&lt;/a&gt; on Twitter about examining the content of a JavaScript object. While the firebug add-on for Firefox comes in very handy in examining the request\response header and for various other internals, I can’t really debug the JavaScript code by adding breakpoints. I use Google’s Chrome browser for my day to day web application development. Both Chrome and Safari provide ‘Developer tools’ which help the user not only in debugging the JavaScript code but also in examining the content of an object at any point in time by providing watch expressions. What I like about debugging in Chrome is that it is very much similar to how I debug my server-side code using ColdFusion Builder or Eclipse. This certainly reduces the learning curve to understand debugging in a browser. However, Chrome has more to give when it comes to debugging web applications.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;In this post I’ll explain how Google Chrome can help you debug web applications and several other internals.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;JavaScript debugging with Chrome Developer tools:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
I have taken an example of a CFAJAXPROXY tag, which is used to create a JavaScript proxy for a ColdFusion component. The proxy class can then be used to invoke any method defined in the CFC (methods with access attribute set to remote):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfajaxproxy jsclassname="myCFCProxy" cfc="TestCFC" &amp;gt;  
 &amp;lt;script type="text/javascript"&amp;gt;  
      var myObj = new myCFCProxy();  
 &amp;lt;/script&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;Now to see the methods that I can invoke using the proxy object (myObj in the code); I can make use of the developer tools in Chrome. After launching the page in the browser, you can invoke the developer tools by selecting the same under settings &amp;gt; Tools. Alternatively, you can use the shortcut key CTRL + SHIFT + I (CMD + OPTION + I on Mac):&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-X5iFaM5m0i0/Tce37pywOpI/AAAAAAAADi8/4M5HICgpVqY/s1600/Chrome_DevTools.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="430" src="http://4.bp.blogspot.com/-X5iFaM5m0i0/Tce37pywOpI/AAAAAAAADi8/4M5HICgpVqY/s640/Chrome_DevTools.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;As shown in the above screen shot, you can click the line numbers to add a breakpoint. This would turn the background color of that particular line number to blue. Once a break point has been added, the same would get listed in the ‘Breakpoints’ section. To inspect the content of a JS object, expand the watch expressions column and click ‘Add’ button (myObj added to the Watch Expressions list). The button bar just above the Watch Expressions column is used in debugging JavaScript code. Once the page is refreshed, the breakpoint is hit and you can inspect the object content:&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-5Eh5duCKLvs/Tce44QannAI/AAAAAAAADjA/8qrn60C5Si8/s1600/Chrome_breakpoint.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-5Eh5duCKLvs/Tce44QannAI/AAAAAAAADjA/8qrn60C5Si8/s1600/Chrome_breakpoint.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;As shown in the above screenshot, the line at which the break-point is hit would be highlighted and an arrow mark at that line would also be shown. The button bar to debug the JS code can now be used:&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Mnuf4V3ql2M/Tce5XJNsdpI/AAAAAAAADjE/i3_9bZPH6bI/s1600/Chrome_debugView.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-Mnuf4V3ql2M/Tce5XJNsdpI/AAAAAAAADjE/i3_9bZPH6bI/s1600/Chrome_debugView.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;There are five buttons provided to debug the JS code:&lt;/span&gt;&lt;/div&gt;&lt;ul style="font-family: inherit;"&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;Pause\Resume&lt;/i&gt;: Use to run the code until it comes across any other break-point. &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul style="font-family: inherit;"&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;Step over&lt;/i&gt;: Used to step over the highlighted code and move to the next line.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul style="font-family: inherit;"&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;Step Into&lt;/i&gt;: Similar to Step over, except that when one clicks Step Into at a function call, the debugger moves its execution to the first line in the function definition. If the user clicks Step over button, then the function is executed and the debugger moves to the next line.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul style="font-family: inherit;"&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;Step out&lt;/i&gt;:  Say if you have stepped into a function definition by clicking Step Into button, on clicking the Step out button the remainder of the function definition is executed and the debugger moves its execution to its parent function and highlight the next line in place.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul style="font-family: inherit;"&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;Deactivate\Activate all breakpoints&lt;/i&gt;: The last button is used to deactivate\activate all the breakpoints added. &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;Once the line at which the break-point was set is executed (by clicking Step Over\Step Into), the JavaScript object (myObj in the code) is populated and the watch expression indicates that. As shown in the above screenshot, the object contains several methods including the one that is defined in the CFC – retrieveAuthorDetails.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Tips and Tricks:&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;There are times when one would get JavaScript errors in the console and to debug the entire web application at that time can seem daunting. To resolve this, click the button ‘Pause on all exceptions’ which is available at the bottom left corner of the window, to pause at the line wherever the exception occurs. The debugger would then highlight the line where the exception occurred, just like how it would highlight when the user sets a breakpoint at a particular line.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;With the advent of HTML5, you can leverage the offline database to store some records offline. Chrome has added support for WebSQL database; with Developer tools, you can examine the database records by switching to the Resources panel. This lists all the resources\files and various entities: &lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-yPWcWnzRoNc/Tce7i1CKWDI/AAAAAAAADjI/EEUvgfQ4jN4/s1600/Chrome_resources.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-yPWcWnzRoNc/Tce7i1CKWDI/AAAAAAAADjI/EEUvgfQ4jN4/s1600/Chrome_resources.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;As seen from the above screenshot, the resources are shown which also includes Databases, Local Storage, Session storage, Cookies, and Application Cache.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt; If you run a script that creates an offline database and stores some records offline, then the same is listed in Resources panel under databases. What is cool is that, you can see all the tables and query the same. That is, you can click the database and a console would be shown to the users wherein they can query the offline database using SQL statements.&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-3452643990627451526?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/pZsBwc-WEtE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/3452643990627451526/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/05/javascript-debugging-with-chrome.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3452643990627451526?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3452643990627451526?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/pZsBwc-WEtE/javascript-debugging-with-chrome.html" title="JavaScript debugging with Chrome Developer Tools and some tips\tricks" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-X5iFaM5m0i0/Tce37pywOpI/AAAAAAAADi8/4M5HICgpVqY/s72-c/Chrome_DevTools.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/05/javascript-debugging-with-chrome.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08AQ346eyp7ImA9WhRQFUo.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-5886666068343852220</id><published>2011-04-27T21:49:00.001+05:30</published><updated>2011-12-11T10:34:02.013+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-11T10:34:02.013+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><category scheme="http://www.blogger.com/atom/ns#" term="ColdFusion" /><title>File upload and Progress events with HTML5 XmlHttpRequest Level 2</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mayXXnwOTLEP-VYp5opGWd9Fh_o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mayXXnwOTLEP-VYp5opGWd9Fh_o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mayXXnwOTLEP-VYp5opGWd9Fh_o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mayXXnwOTLEP-VYp5opGWd9Fh_o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;The XmlHttpRequest Level 2 specification adds several enhancements to the XmlHttpRequest object. Last week I had blogged about &lt;a href="http://fusioned.blogspot.com/2011/04/html5-xmlhttprequest-2-cross-origin.html"&gt;cross-origin-requests&lt;/a&gt; and how it is different from &lt;a href="http://fusioned.blogspot.com/2011/04/html5-xmlhttprequest-2-vs.html"&gt;Flash\Silverlight's approach&lt;/a&gt;. &amp;nbsp;With Level 2 specification one can upload the file to the server by passing the file object to the send method.&amp;nbsp;In this post I'll try to explore&amp;nbsp;uploading file using XmlHttpRequest 2 in conjunction with&amp;nbsp;the progress events.&amp;nbsp;I'll also provide a description on the new HTML5 tag -&amp;nbsp;&lt;i&gt;progress &lt;/i&gt;which can be updated while the file is being uploaded to the server. And of course, some ColdFusion code that will show how the file is accepted and stored on the server directory.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Progress Tag:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
HTML5 has introduced several new elements to the language and one of them the &lt;i&gt;progress&lt;/i&gt;&amp;nbsp;element. This element is used to show a progress bar on the web page. This tag comes handy for describing any work in progress. It can be used to describe the progress of a time consuming task.The &lt;i&gt;progress&lt;/i&gt;&amp;nbsp;element comes with two attributes: &lt;i&gt;value&lt;/i&gt; and &lt;i&gt;max&lt;/i&gt;. The &lt;i&gt;value&lt;/i&gt; attribute is used to indicate the current value of progress and the &lt;i&gt;max&lt;/i&gt; attribute is used to describe completion value.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;progress id="progressBar" value="0" max="100"&amp;gt;  
 &amp;lt;/progress&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;XmlHttpRequest Progress Events:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The only event listener that was available with &lt;i&gt;XmlHttpRequest&lt;/i&gt; was the &lt;i&gt;readystatechange&lt;/i&gt; event listener. Now with the advent of HTML5, several event listeners have been added to the&amp;nbsp;&lt;i&gt;XmlHttpRequest&lt;/i&gt; Interface -&amp;nbsp;&lt;i&gt;loadstart&lt;/i&gt;, &lt;i&gt;progress&lt;/i&gt;, &lt;i&gt;load&lt;/i&gt;, &lt;i&gt;abort&lt;/i&gt;, &lt;i&gt;error&lt;/i&gt;, &lt;i&gt;timeout&lt;/i&gt; and &lt;i&gt;loadend&lt;/i&gt;. The &lt;i&gt;loadstart&lt;/i&gt; event is triggered when the request is initiated by the client. The&amp;nbsp;&lt;i&gt;progress&amp;nbsp;&lt;/i&gt;event is triggered once the &lt;i&gt;loadstart&lt;/i&gt; event has been dispatched.&lt;br /&gt;
&lt;br /&gt;
In this example, I'll try to upload a file (text, image, mp3) using &lt;i&gt;XmlHttpRequest &lt;/i&gt;and show the progress for the same by updating the&amp;nbsp;&lt;i&gt;progressbar&lt;/i&gt;&amp;nbsp;(progress tag)&amp;nbsp;using the &lt;i&gt;progress &lt;/i&gt;event handler. With Level 2 specification one can now pass&amp;nbsp;&lt;i&gt;ArrayBuffer&lt;/i&gt;, &lt;i&gt;Blob&lt;/i&gt;, &lt;i&gt;File&lt;/i&gt; and &lt;i&gt;FormData&lt;/i&gt; objects to the send method.&lt;br /&gt;
&lt;br /&gt;
The &lt;i&gt;input &lt;/i&gt;tag with the type &lt;i&gt;file&lt;/i&gt; can be used to select a file that needs to be uploaded to the server (&amp;lt;input type="file" id="fileUpload"&amp;gt;). Once the file is selected, a POST request can then be made to the server and the file object can be passed as an argument to the send method:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; function uploadFile(){  
         var filesToBeUploaded = document.getElementById("fileControl");  
         var file = filesToBeUploaded.files[0];  
         var xhrObj = new XMLHttpRequest();  
         xhrObj.upload.addEventListener("loadstart", loadStartFunction, false);  
         xhrObj.upload.addEventListener("progress", progressFunction, false);  
         xhrObj.upload.addEventListener("load", transferCompleteFunction, false);  
         xhrObj.open("POST", "upload.cfm", true);  
         xhrObj.setRequestHeader("Content-type", file.type);  
         xhrObj.setRequestHeader("X_FILE_NAME", file.name);  
         xhrObj.send(file);  
 }  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
As observed in the above code, event listeners are added for &lt;i&gt;loadstart&lt;/i&gt;, &lt;i&gt;progress&lt;/i&gt; and &lt;i&gt;load &lt;/i&gt;events. These events are added for the upload attribute of &lt;i&gt;XmlHttpRequest &lt;/i&gt;object.&amp;nbsp;The &lt;i&gt;Content-type &lt;/i&gt;header is set to the value of &lt;i&gt;file.type&lt;/i&gt;. This is required to let the server know the mime type of file being transferred. Also, the header X_FILE_NAME with the value of &lt;i&gt;file.name&lt;/i&gt; is specified. The &lt;i&gt;file &lt;/i&gt;object is then passed to the &lt;i&gt;send&lt;/i&gt; method of the &lt;i&gt;XmlHttpRequest&lt;/i&gt; object.&lt;br /&gt;
&lt;br /&gt;
The &lt;i&gt;loadstart &lt;/i&gt;event is triggered once a request to send a file to the server is initiated. Once this function has been dispatched the &lt;i&gt;progress&lt;/i&gt; event is triggered indicating that the file is being uploaded to the server:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt;  function progressFunction(evt){  
         var progressBar = document.getElementById("progressBar");  
         var percentageDiv = document.getElementById("percentageCalc");  
         if (evt.lengthComputable) {  
           progressBar.max = evt.total;  
           progressBar.value = evt.loaded;  
           percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";  
         }  
 }  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The &lt;i&gt;progress &lt;/i&gt;event is triggered as and when some data is uploaded to the server. This depends on the size of file that is being transmitted. The progressFunction defined above, takes an argument of type &lt;i&gt;ProgressEvent&lt;/i&gt;. The &lt;i&gt;ProgressEvent &lt;/i&gt;Interface defines the attributes - &lt;i&gt;lengthcomputable&lt;/i&gt;, &lt;i&gt;loaded &lt;/i&gt;and &lt;i&gt;total&lt;/i&gt;. The &lt;i&gt;lengthcomputable &lt;/i&gt;attribute is used to find whether the progress is an indeterministic or deterministic one. In this case the size of the file being uploaded is known and hence the &lt;i&gt;lengthcomputable &lt;/i&gt;attribute will be set to true. The other attributes &lt;i&gt;loaded &lt;/i&gt;and &lt;i&gt;total&lt;/i&gt; are used to indicate the number of bytes uploaded of the total number of bytes. This data is then used to update the &lt;i&gt;progress &lt;/i&gt;tag attributes &lt;i&gt;value&lt;/i&gt; and &lt;i&gt;max&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Server side code:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The server-side code is as simple as it can get:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfset headerData = getHTTPRequestData().headers&amp;gt;  
 &amp;lt;cfset content = getHTTPRequestData().content&amp;gt;  
 &amp;lt;cfset filePath = expandPath(".") &amp;amp; "/Uploaded/" &amp;amp; headerData.X_FILE_NAME &amp;gt;  
 &amp;lt;cfset fileWrite(filePath,content)&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The header X_FILE_NAME would contain the name of the file that is being sent from the client. The file content is available in the request data and the same is accessed using &lt;i&gt;getHTTPRequestData().content&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
You can download the source code from -&amp;nbsp;&lt;a href="http://www.box.com/s/8py25tahymooe8pabo9z"&gt;http://www.box.com/s/8py25tahymooe8pabo9z&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-5886666068343852220?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/s5poc0mRY24" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/5886666068343852220/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/04/file-upload-and-progress-events-with.html#comment-form" title="14 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/5886666068343852220?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/5886666068343852220?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/s5poc0mRY24/file-upload-and-progress-events-with.html" title="File upload and Progress events with HTML5 XmlHttpRequest Level 2" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>14</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/04/file-upload-and-progress-events-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYFRHk7fCp7ImA9WhZQE0Q.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-7364288127683849355</id><published>2011-04-21T18:44:00.002+05:30</published><updated>2011-04-21T18:51:55.704+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-21T18:51:55.704+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><title>HTML5 XmlHttpRequest 2 v/s Flash\Silverlight approach to cross-origin requests</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/_R483DmmTqnJDxVZ8WFRPz7gNLA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_R483DmmTqnJDxVZ8WFRPz7gNLA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/_R483DmmTqnJDxVZ8WFRPz7gNLA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_R483DmmTqnJDxVZ8WFRPz7gNLA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;A few days back I had posted on &lt;a href="http://fusioned.blogspot.com/2011/04/html5-xmlhttprequest-2-cross-origin.html"&gt;XmlHttpRequest Level 2&lt;/a&gt;, describing how cross-origin requests can be achieved. A few folks on my team asked me how different it is from Flash\Silverlight's approach to achieve cross domain request\response with &lt;i&gt;crossdomain.xml&lt;/i&gt;. The approach that these plugins take to send a request and receive a response is completely different from that of XmlHttpRequest's approach.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
In case of Flash\Silverlight a policy file &lt;i&gt;crossdomain.xml&lt;/i&gt; is created for the site. This file would contain a list of all sites that can make a cross domain request to this site. For example, if &lt;i&gt;http://yoursite.com&lt;/i&gt; lists&amp;nbsp;&lt;i&gt;http://friendssite.com&lt;/i&gt;&amp;nbsp;in crossdomain.xml file, then &lt;i&gt;http://friendssite.com&lt;/i&gt; is allowed to access all the resources of &lt;i&gt;http://yoursite.com&lt;/i&gt;. Here the access control mode is set to per site. XHR 2 on the other hand, follows a different approach altogether. It works on the per page access control model. In this case, every page has to respond with a 'Access-Control-Allow-Origin' header to the foreign site. With this approach only a part of a website can be accessed by a foreign site, keeping the rest of the website inaccessible.&lt;br /&gt;
&lt;br /&gt;
Another difference to note is that, in case of Flash\Silverlight the browser fetches the &lt;i&gt;crossdomain.xml&lt;/i&gt; defined for the website and analyzes it. If a foreign site is not allowed to make cross domain calls then the browser restricts the call being made. In case of XHR 2, a request is sent first and then a check is performed to see whether the response header contains 'Access-Control-Allow-Origin' header. If this header allows the foreign site then it can read the response, otherwise the response is inaccessible to javascript.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-7364288127683849355?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/rOr08PWA4jg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/7364288127683849355/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/04/html5-xmlhttprequest-2-vs.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/7364288127683849355?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/7364288127683849355?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/rOr08PWA4jg/html5-xmlhttprequest-2-vs.html" title="HTML5 XmlHttpRequest 2 v/s Flash\Silverlight approach to cross-origin requests" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/04/html5-xmlhttprequest-2-vs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04NR38_cCp7ImA9WhdREUo.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-3239453486896830054</id><published>2011-04-18T18:48:00.003+05:30</published><updated>2011-08-01T11:56:36.148+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-01T11:56:36.148+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><category scheme="http://www.blogger.com/atom/ns#" term="ColdFusion" /><title>HTML5 XmlHttpRequest 2 - Cross origin request</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/z6uoKlXHEBM_MdDKX4fFK3XtOlg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/z6uoKlXHEBM_MdDKX4fFK3XtOlg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/z6uoKlXHEBM_MdDKX4fFK3XtOlg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/z6uoKlXHEBM_MdDKX4fFK3XtOlg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;HTML5 specification has introduced a few enhancements for XmlHttpRequest object and one of them is the ability to make cross-origin request. That is, a host can send a XmlHttpRequest request to another host and receive a response in return. On the server-side, a check can be made to see whether the request can be accepted from the given origin.&amp;nbsp;In this post I'll try to explain how this can be done using ColdFusion.&lt;br /&gt;
&lt;a href="" name="more"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Client side:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
On the client side, a XmlHttpRequest object is created and then a GET request is made to the remote server.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt; var client = new XMLHttpRequest();  
client.onreadystatechange = readyStateChangeHandler;  
client.open("GET","http://{remote-address}/{path-to-file}.cfm",true);  
client.send();       
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
For example, say &lt;i&gt;example.com&lt;/i&gt; wants to get a response from another domain say &lt;i&gt;abc.com&lt;/i&gt;, then as observed from the above code the request would look like:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter"&gt;&lt;code class="CICodeFormatter"&gt;
client.open("GET","http://abc.com/dir1/foo.cfm",true);  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Server side:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
When a request is sent to the server, the request header would contain a key ORIGIN whose value will be the domain name from which the request was made. In this case the value would be &lt;i&gt;example.com&lt;/i&gt;&lt;i&gt;.&lt;/i&gt;&amp;nbsp;The server side code can then perform a check to see whether the request origin belongs to the list of origins from which the request can be accepted.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="CICodeFormatter" &gt;&lt;code class="CICodeFormatter"&gt; &amp;lt;cfif structKeyExists(getHTTPRequestData().headers,"origin") &amp;gt;   
    &amp;lt;cfset origin = getHTTPRequestData().headers.origin /&amp;gt;   
    &amp;lt;cfif origin eq "http://example.com"&amp;gt;   
      &amp;lt;cfheader name="Access-Control-Allow-Origin"   
         value="http://example.com"&amp;gt;   
      &amp;lt;cfoutput&amp;gt;#timeFormat(now(),"medium")#&amp;lt;/cfoutput&amp;gt;   
    &amp;lt;/cfif&amp;gt;   
 &amp;lt;/cfif&amp;gt;   
&lt;/code&gt;&lt;/pre&gt;As seen from the above code, the response header ACCESS-CONTROL-ALLOW-ORIGIN is set to allow cross-origin requests from &lt;i&gt;example.com.&lt;/i&gt;&amp;nbsp;This now enables requests from &lt;i&gt;example.com &lt;/i&gt;to be served from &lt;i&gt;abc.com.&amp;nbsp;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;
&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;
&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-3239453486896830054?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/1ouhFPRq58o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/3239453486896830054/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/04/html5-xmlhttprequest-2-cross-origin.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3239453486896830054?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/3239453486896830054?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/1ouhFPRq58o/html5-xmlhttprequest-2-cross-origin.html" title="HTML5 XmlHttpRequest 2 - Cross origin request" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>4</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/04/html5-xmlhttprequest-2-cross-origin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUHR3wyfip7ImA9WhZbF0k.&quot;"><id>tag:blogger.com,1999:blog-8417810603086728638.post-1772619252140666440</id><published>2011-04-07T17:11:00.001+05:30</published><updated>2011-06-22T17:17:16.296+05:30</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-22T17:17:16.296+05:30</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CFBuilder" /><title>Navigation enhancements in ColdFusion Builder 2.0</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/snIH7gTq0l5ZGV50y2TD90JR0JU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/snIH7gTq0l5ZGV50y2TD90JR0JU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/snIH7gTq0l5ZGV50y2TD90JR0JU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/snIH7gTq0l5ZGV50y2TD90JR0JU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Do you spend a lot of &amp;nbsp;time scrolling large files, just to find out the next function definition in place or to figure out the end\start of a tag? If your answer is YES, then why don’t you try the Navigation enhancements in ColdFusion Builder 2.0?&lt;/span&gt;&lt;br /&gt;
&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"&gt;&lt;span style="color: black; font-family: inherit;"&gt;ColdFusion Builder comes to you with three types of Navigation enhancements:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpFirst" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; margin-left: 21.75pt; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo1; text-indent: -.25in;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;-&lt;span style="font: normal normal normal 7pt/normal 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;Code Navigation&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpMiddle" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; margin-left: 21.75pt; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo1; text-indent: -.25in;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;-&lt;span style="font: normal normal normal 7pt/normal 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;Smart Tab Navigation&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpLast" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; margin-left: 21.75pt; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo1; text-indent: -.25in;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;-&lt;span style="font: normal normal normal 7pt/normal 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;Jumping to matching tag.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;a href="" name="more"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;b&gt;Code Navigation&lt;/b&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="color: black;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Code Navigation is all about navigating to the next function definition in place. Imagine a CFC containing various cffunction tags. It is a time-consuming task to keep scrolling and keep an eye on the file to get to the next cffunction tag. ColdFusion Builder 2.0 provides a shortcut key CTRL + SHIFT + DOWN to navigate to the next function definition. And to navigate to the previous function definition, you can use the shortcut CTRL + SHIFT + UP.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;Code Navigation works in conditional statements as well.&amp;nbsp;&lt;/span&gt;Consider an example of a cfif-cfelseif-cfelse conditional statement. If the cursor is placed, say at the start tag and if this particular conditional statement has several conditions in it, then on pressing the shortcut key, the next condition in place is highlighted. That is, on placing the cursor at the start of the cfif tag and pressing the shortcut CTRL + SHIFT + DOWN, the next cfelseif condition is highlighted.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;b&gt;Smart Tab Navigation&lt;/b&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;Smart Tab navigation is about navigating to the next attribute value.&amp;nbsp;&lt;/span&gt;The shortcut key for this is CTRL + ]. On pressing the shortcut key, the next attribute value is highlighted. This works in script style code as well, wherein the function arguments are also highlighted.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;b&gt;Jump to matching tag&lt;/b&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span style="color: black;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;If you have several nested cfif tags, it becomes very difficult to find out the end of a particular cfif tag. ColdFusion Builder 2.0 provides the shortcut CTRL + ALT + M, which shifts the cursor position to end of the tag. If the cursor is placed at the end tag, then on pressing the same shortcut key the cursor position shifts to the start tag.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;b&gt;Summary:&lt;/b&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;ul type="disc"&gt;&lt;li class="MsoNormal" style="color: black; line-height: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;i&gt;Code Navigation&lt;/i&gt;&amp;nbsp;- Navigate to the next function definition or the next      condition. Shortcut- CTRL + SHIFT + DOWN \ UP.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li class="MsoNormal" style="color: black; line-height: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;i&gt;Smart Tab Navigation&lt;/i&gt;&amp;nbsp;- Navigate to the next attribute value or arguments      (cfscript). Shortcut- CTRL + ] \ [.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li class="MsoNormal" style="color: black; line-height: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;i&gt;Jump to matching tag&lt;/i&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;-&amp;nbsp;Jump to the start or end tag. Shortcut- CTRL +      ALT + M.&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman', serif; font-size: 13.5pt; font-weight: bold;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8417810603086728638-1772619252140666440?l=www.sagarganatra.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FusionedWithColdfusion/~4/M11JYy4Tl_M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.sagarganatra.com/feeds/1772619252140666440/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.sagarganatra.com/2011/04/navigation-enhancements-in-coldfusion.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/1772619252140666440?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8417810603086728638/posts/default/1772619252140666440?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FusionedWithColdfusion/~3/M11JYy4Tl_M/navigation-enhancements-in-coldfusion.html" title="Navigation enhancements in ColdFusion Builder 2.0" /><author><name>Sagar Ganatra</name><uri>http://www.blogger.com/profile/15129859862786257527</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="29" height="32" src="http://3.bp.blogspot.com/_kDEiWzETcpY/Sdg8Y7b51XI/AAAAAAAAB8A/WHb29eNdzJY/S220/mypic.JPG" /></author><thr:total>4</thr:total><feedburner:origLink>http://www.sagarganatra.com/2011/04/navigation-enhancements-in-coldfusion.html</feedburner:origLink></entry></feed>

