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

<channel>
	<title>The CSS Ninja &#187; javascript</title>
	<atom:link href="http://www.thecssninja.com/category/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://www.thecssninja.com</link>
	<description>All things CSS, Javascript &#38; xhtml</description>
	<lastBuildDate>Mon, 30 Aug 2010 10:21:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Drag out files like Gmail</title>
		<link>http://www.thecssninja.com/javascript/gmail-dragout</link>
		<comments>http://www.thecssninja.com/javascript/gmail-dragout#comments</comments>
		<pubDate>Mon, 16 Aug 2010 12:53:42 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=703</guid>
		<description><![CDATA[Google in their quest to keep me busy in trying to figure out how they do their innovative features in Gmail are at it again. First it was drag and drop uploading which used a clever trick to make it work in Chrome which currently doesn&#8217;t support the FileReader in their stable release. Now they&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Google in their quest to keep me busy in trying to figure out how they do their innovative features in Gmail are at it again. First it was <a href="http://www.thecssninja.com/javascript/gmail-upload ">drag and drop uploading</a> which used a clever trick to make it work in Chrome which currently doesn&#8217;t support the FileReader in their stable release. Now they&#8217;ve added the ability to drag out attachments to your file system, allowing you to bypass the usual method of the save dialog.<span id="more-703"></span></p>
<p>While the first feature of drag and drop uploading I figured out quite easily, this drag out feature was a doozy.</p>
<h2 class="subtitle02">How did I figure it out?</h2>
<p>There were two clues which got me started. One it only works in Chrome so it had to be an extension to the current Drag and Drop API. Two, after some poking around in gmail, there was a custom attribute on the attachment link called download_url which colon separated the attachments mime type, file name and download link.</p>
<p>Since Gmails JavaScript is obfuscated to within in an inch of its life there was no easy way to attach the built in debugger to anything that might give it away. So I tried downloading the script and running it through various unobfuscaters which made it format nicely but I still had to work with function names like vHG etc.</p>
<p>My last hope was <a href="http://code.google.com/p/chromium/issues/list">chromiums bug tracker</a> and searching to see if any bugs or feature requests were filed that could help give it away. I knew the download_url attribute played a role and it would be set using setData method on the dataTransfer object. So I searched high and low on Chromiums bug tracker for matches to &#8220;download_url&#8221;, &#8220;downloadurl&#8221; &#038; &#8220;downloadurl setData&#8221; nothing nada, zip. So I turned to the <a href="https://bugs.webkit.org/">webkit bug tracker</a>, still nothing! So I thought maybe Mozilla had discussed it on their bug tracker, a long shot but worth a try. Bingo! This <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=570164">bug</a> led me to this <a href="https://bugs.webkit.org/show_bug.cgi?id=31090">bug</a>, on webkits bug tracker don&#8217;t ask why the search didn&#8217;t bring this up, and then onto this <a href="http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-August/022118.html">proposal</a>. We&#8217;re in business!</p>
<h2 class="subtitle02">How does it work?</h2>
<p>So we&#8217;ve found the details let&#8217;s play with it.</p>
<div class="resources01"><a target="_blank" class="demo" title="How to drag out files like gmail" href="http://www.thecssninja.com/demo/gmail_dragout/">View a live demo</a> <a target="_blank" class="demo source" title="Download the source of the Gmail drag out demo" href="http://www.thecssninja.com/demo/gmail_dragout/gmail_dragout.zip">Download the source files</a></div>
<p>Update: I&#8217;ve rolled out drag to desktop across my site for all my demo source files. If you&#8217;re using Chrome 5+ just drag the &#8220;Download the source files&#8221; link to your desktop!</p>
<p>The above demo will, in Chrome 5+, allow you to drag any of the items to your desktop and save them without having to go through the usual save dialog process.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> file <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;dragout&quot;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
file.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;dragstart&quot;</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>evt<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    evt.<span style="color: #660066;">dataTransfer</span>.<span style="color: #660066;">setData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;DownloadURL&quot;</span><span style="color: #339933;">,</span>fileDetails<span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>From the code above you attach an ondragstart event listener to something you want to &#8220;drag out&#8221; and save to your file system. On the dragstart event you set the data using the new &#8220;DownloadURL&#8221; type and pass file information to it.</p>
<p>In order to pass the correct information to the event we access the download_url attribute and use that for our setData call. I&#8217;ve made one change that is slightly different to how Gmail sets and gets the attribute.</p>

<div class="wp_syntax"><div class="code"><pre class="htrml4strict" style="font-family:monospace;">&lt;a href=&quot;Eadui.ttf&quot; id=&quot;dragout&quot; draggable=&quot;true&quot; data-downloadurl=&quot;
    application/octet-stream
    :Eadui.ttf
    :http://thecssninja.com/gmail_dragout/Eadui.ttf&quot;&gt;Font file&lt;/a&gt;</pre></div></div>

<p>Instead of creating a new attribute I have instead used the new <a href="http://www.w3.org/TR/html5/common-dom-interfaces.html#domstringmap-0">custom data attributes</a> specified in the HTML5 spec. While not officially supported by Chrome yet we can still use it and add a simple test for support and fork the code either way.</p>
<p>The custom attribute needs three things specified that are separated by colons in order for it to work. The files mime type, the name you wish it to be saved as (this can be anything) and the url to where the file can be downloaded from.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> fileDetails;
&nbsp;
<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> file.<span style="color: #660066;">dataset</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;undefined&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// Grab it the old way</span>
    fileDetails <span style="color: #339933;">=</span> file.<span style="color: #660066;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;data-downloadurl&quot;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
    fileDetails <span style="color: #339933;">=</span> file.<span style="color: #660066;">dataset</span>.<span style="color: #660066;">downloadurl</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Above I do a check to see if the element supports the dataset attribute if not use getAttribute to grab the value.</p>
<h2 class="subtitle02">A cool finding</h2>
<p>Playing around with this new functionality I did find a cool side effect that if I drag a file that&#8217;s set the DownloadURL type on the setData method into a page using Firefox 3.6+ that will capture a drop event the dataTransfer file attribute will act as though it&#8217;s captured a local file and can be manipulated with the FileAPI e.g. In my <a href="http://labs.thecssninja.com/font_dragr/">font dragr</a> web app if I drag a font file that&#8217;s been attached to an email it will render the font as though I&#8217;ve dragged it from my local file system! Doing the same with Chrome 6, which also supports file attribute on the dataTransfer property, will ignore the drop.</p>
<h2 class="subtitle02">Predicting the next challenge from Google</h2>
<p>So what do I think the Gmail team will do next? Since they announced, and are now starting, their 6 week release cycle of chrome. I foresee the ability to upload folders not just individual files, being able to capture a photo from your web cam straight into an embedded picture using the proposed <a href="http://www.w3.org/TR/html-media-capture/">media capture proposal</a>. Whatever it is I&#8217;m sure it&#8217;ll knock everyone&#8217;s socks off and make me rack my brain in trying to figure it out.</p>
<p class="shorty01">Short URL: <a href="http://cssn.in/ja/028">http://cssn.in/ja/028</a></p>
<div class="clear">&nbsp;</div>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/gmail-dragout/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>How Gmail&#8217;s drag and drop works and why it&#8217;s not supported in Safari</title>
		<link>http://www.thecssninja.com/javascript/gmail-upload</link>
		<comments>http://www.thecssninja.com/javascript/gmail-upload#comments</comments>
		<pubDate>Wed, 21 Apr 2010 12:42:51 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=682</guid>
		<description><![CDATA[Recently Gmail pushed out an update that allowed users to drag and drop files from desktop to Gmail and have them automatically uploaded. Being the web geek I am I had to figure out how it functioned. Firefox was easy and I have covered drag and drop uploading already. They also mentioned in their post [...]]]></description>
			<content:encoded><![CDATA[<p>Recently Gmail pushed out an update that allowed users to drag and drop files from desktop to Gmail and have them automatically uploaded. Being the web geek I am I had to figure out how it functioned. Firefox was easy and I have covered <a href="http://www.thecssninja.com/javascript/fileapi">drag and drop uploading</a> already. They also mentioned in their post that Chrome was supported but I know Chrome is yet to implement the File API. Most intriguing was that it doesn&#8217;t work in Safari?<span id="more-682"></span></p>
<div class="resources01"><a href="http://www.thecssninja.com/demo/gmail_upload/" title="How Gmail's drag and drop works and why it's not supported in Safari " class="demo" target="_blank">View a live demo</a> <a href="http://www.thecssninja.com/demo/gmail_upload/gmail_upload.zip" title="Download the source of the Gmail drag and drop upload demo" class="demo source" target="_blank">Download the source files</a></div>
<p>In the above demo I&#8217;ve recreated a mock Gmail UI that works the same as the actual Gmail with drag drop uploading. It feature detects the browsers capabilities and depending on it will use the File API or another method, which I will delve into. The beauty of feature detection is once Chrome and other browsers add support for the File API the alternative method will become defunct and would require no maintenance for the code.</p>
<p>I have intentionally left out the File API code that would allow Firefox to function as I wanted to focus on Chrome’s implementation.</p>
<h2 class="subtitle02">So how does Chrome do it?</h2>
<p>Using a bit of CSS trickery we can create the illusion of having File API support and still allow users to drag and drop files from the desktop into Gmail. I accomplish this by having the drop zone, which becomes visible on a <code>dragenter</code> event, contain an invisible file input with a 100% width and height of the drop zone area. The file input also has the attribute multiple on it allowing a user to drop multiple files.</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;drop&quot;</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>Drop files here<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;</span>To add them as attachments<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;file&quot;</span> <span style="color: #000066;">multiple</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;filesUpload&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></pre></div></div>

<p>The drop zone is hidden by default and only appears when the body detects the <code>dragenter</code> event.</p>

<div class="wp_syntax"><div class="code"><pre class="css css" style="font-family:monospace;"><span style="color: #cc00cc;">#drop</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">relative</span>;
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#drop</span> input <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">absolute</span>;
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;"><span style="color: #cc66cc;">100</span>%</span>;
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;"><span style="color: #cc66cc;">100</span>%</span>;
    <span style="color: #000000; font-weight: bold;">top</span><span style="color: #00AA00;">:</span> 0;
    <span style="color: #000000; font-weight: bold;">left</span><span style="color: #00AA00;">:</span> 0;
    opacity<span style="color: #00AA00;">:</span> 0;
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>The file input inside the drop zone has position absolute, width and height of 100% and its opacity set to 0 so it can still be interacted with but not seen.</p>
<h2 class="subtitle02">Handling the drop</h2>
<p>Unlike Firefox 3.6 we don&#8217;t bother listening for the drop event in the drop zone as Chrome is using the file input. We instead attach a change event to the file input which will trigger when a file is selected through the browse screen or in our case when a file is dropped on the input, and since we added the multiple attribute we can drop more than one file at a time.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">dropArea.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;change&quot;</span><span style="color: #339933;">,</span> TCNDDU.<span style="color: #660066;">handleDrop</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;
&nbsp;
TCNDDU.<span style="color: #660066;">handleDrop</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>evt<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> files <span style="color: #339933;">=</span> evt.<span style="color: #660066;">target</span>.<span style="color: #660066;">files</span>;
    dropArea.<span style="color: #660066;">style</span>.<span style="color: #660066;">display</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;none&quot;</span>;
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> 0<span style="color: #339933;">,</span> len <span style="color: #339933;">=</span> files.<span style="color: #660066;">length</span>; i <span style="color: #339933;">&lt;</span> len; i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// iterate over file(s) and process them for uploading</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>;</pre></div></div>

<p>The function that handles the change event looks at the javascript event target to access the files array which contains the dropped file(s) name, size and type. From there we can iterate over the files and queue them to be uploaded.</p>
<h2 class="subtitle02">Uploading the file</h2>
<p>I&#8217;ve updated the demo to now upload the file. Using XHR2 and the <a href="http://www.w3.org/TR/2009/WD-XMLHttpRequest2-20090820/#the-upload-attribute">upload attribute</a> to attach progress events so we can do a real progress bar that indicates to the user how much the file has uploaded.</p>
<p>Drop the file or files into the drop zone in Chrome or Safari and the files will be uploaded.</p>
<p>Have a read of Andrea Giammarchi <a href="http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html">Safari 4 Multiple Upload With Progress Bar</a> article. I used the PHP from that article to handle the upload.</p>
<h2 class="subtitle02">Why doesn&#8217;t it work in Safari?</h2>
<p>Technically it does work in Safari but only if you drop one file at a time which isn&#8217;t what users would expect. Dropping multiple files will populate the files array in the file input, but selecting say 3 files and dragging them into Safari will register 3 files have been dragged but if you iterate over the files array those 3 files will all be the same file&#8230;</p>
<p>To explain it better let&#8217;s say you have 3 files each one called a.jpg, b.jpg and c.jpg selecting those 3 files and then clicking and dragging on the b.jpg file will add 3 files to the input. The file you did the drag operation on will be added 3 times to the input and it will ignore the other files, iterating over the files array will have b.jpg 3 times?!</p>
<p>To add to the strangeness if I have an input that is visible and I click the choose file/browse button and select multiple files in the dialog box upon clicking open the files array will correctly be populated with all the files selected and won&#8217;t have the duplication issue.</p>
<p>That folks is why I believe Safari isn&#8217;t supported in the new drag and drop upload feature in Gmail. I&#8217;m sure Google has tapped Apple on the shoulder to get that fixed.</p>
<p><strong>Update:</strong> <a href="#comment-1480">Paul</a> has filed a <a href="https://bugs.webkit.org/show_bug.cgi?id=37957">ticket</a> in webkits bug tracker.</p>
<h2 class="subtitle02">A work around?</h2>
<p>The only work around that Google could do is to break out of the loop if they detect multiple instances of the same file being referenced. This work around would limit Safari to only 1 file per drag and drop operation.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">TCNDDU.<span style="color: #660066;">handleDrop</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>evt<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> files <span style="color: #339933;">=</span> evt.<span style="color: #660066;">target</span>.<span style="color: #660066;">files</span>;
&nbsp;
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> 0<span style="color: #339933;">,</span> len <span style="color: #339933;">=</span> files.<span style="color: #660066;">length</span>; i <span style="color: #339933;">&lt;</span> len; i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">!=</span> 0 <span style="color: #339933;">&amp;&amp;</span> files<span style="color: #009900;">&#91;</span>0<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">fileName</span> <span style="color: #339933;">===</span> files<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">fileName</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">continue</span>;
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>;</pre></div></div>

<p>Checking the first file name against other file names and making sure they don&#8217;t match, if they do skip that iteration and go to the next. If the file names are all the same only the first will be processed but you still get the benefit of drag and drop action in Safari. Not ideal and an error message could be shown to the user letting them know why only 1 file appears.</p>
<h2 class="subtitle02">Still sometime to go</h2>
<p>From my investigation it seems Safari isn&#8217;t far off from getting some drag and drop love, they just need to push out a fix for the bug mentioned above or Google could limit drag and drop to first file only for Safari.</p>
<p>I don&#8217;t expect to see this functionality in any version of IE until they support the File API. Dragging and dropping a file into a file input doesn&#8217;t work nor does IE have a files array for the file input.</p>
<p>Opera is a long way from having this functionality they have yet to implement the Drag and Drop API and their file inputs work the same as IE.</p>
<p>Our best bet of getting cross browser drag and drop uploading is with the Drag and Drop and File API. Let&#8217;s hope we see some other browser vendors add this soon.</p>
<p class="shorty01">Short URL: <a href="http://cssn.in/ja/027">http://cssn.in/ja/027</a></p>
<div class="clear">&nbsp;</div>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/gmail-upload/feed</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Is that a Speedo in your pocket?</title>
		<link>http://www.thecssninja.com/javascript/pocket-speedo</link>
		<comments>http://www.thecssninja.com/javascript/pocket-speedo#comments</comments>
		<pubDate>Sat, 13 Mar 2010 04:11:25 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[css]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=623</guid>
		<description><![CDATA[Why yes it is&#8230; I&#8217;ve been sitting on this little idea for a while and as a bit of fun I finally got around to putting it together and properly testing it. Basically on an iPhone with geolocation support (3.0+), I have set up a little web app that will get the speed from the [...]]]></description>
			<content:encoded><![CDATA[<p>Why yes it is&#8230;</p>
<p>I&#8217;ve been sitting on this little idea for a while and as a bit of fun I finally got around to putting it together and properly testing it. Basically on an iPhone with geolocation support (3.0+), I have set up a little web app that will get the speed from the GPS and move the speedometer needle according to your current speed in kilometres.<span id="more-623"></span></p>
<h2 class="subtitle02">But speed returns null?</h2>
<p>When I originally played around with the <a href="http://www.thecssninja.com/javascript/geolocation-iphone">geolocation API on the iPhone</a> checking the speed attribute always returned null, what I failed to actually do was test this value while actually moving. The speed attribute is capable of getting speeds as low as 2km/h so walking with the phone will start to register speeds.</p>
<div class="resources01"><a target="_blank" class="demo" title="Pocket speedo web app" href="http://labs.thecssninja.com/pocket_speedo/">View a live demo</a> <a target="_blank" class="demo source" title="Download the source of the Pocket speedo web app demo" href="http://labs.thecssninja.com/pocket_speedo/pocket_speedo.zip">Download the source files</a></div>
<h2 class="subtitle02">So we can get the speed let&#8217;s use it</h2>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>navigator.<span style="color: #660066;">geolocation</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">getCurrentPosition</span><span style="color: #009900;">&#40;</span>getSpeed<span style="color: #339933;">,</span> handleError<span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span>
<span style="color: #003366; font-weight: bold;">function</span> getSpeed<span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    updateStats<span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span>;
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> coordsListener <span style="color: #339933;">=</span> navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">watchPosition</span><span style="color: #009900;">&#40;</span>updateStats<span style="color: #339933;">,</span> handleError<span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Here we get the current position and upon success tell it to execute the <code>getSpeed</code> function. Inside that function I call another function which does all the hard work which I&#8217;ll explain below, next I call the watchPosition method and pass it the same updateStats function so we can get constant updates from the GPS about our speed and adjust our speedometer needle.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> updateStats<span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> speed <span style="color: #339933;">=</span> pos.<span style="color: #660066;">coords</span>.<span style="color: #660066;">speed</span><span style="color: #339933;">,</span>
         speedVariation <span style="color: #339933;">=</span> <span style="color: #CC0000;">3.6</span><span style="color: #339933;">,</span>
         currentSpeed <span style="color: #339933;">=</span> Math.<span style="color: #660066;">round</span><span style="color: #009900;">&#40;</span>speed<span style="color: #339933;">*</span>speedVariation<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
         angleVariation <span style="color: #339933;">=</span> <span style="color: #CC0000;">0.8</span><span style="color: #339933;">,</span>
         initSpeedAngle <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">105</span><span style="color: #339933;">,</span>
         speedAngle <span style="color: #339933;">=</span> initSpeedAngle <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>currentSpeed <span style="color: #339933;">*</span> angleVariation<span style="color: #009900;">&#41;</span>;
&nbsp;
    needle.<span style="color: #660066;">style</span>.<span style="color: #660066;">webkitTransitionDuration</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'500ms'</span>;
    needle.<span style="color: #660066;">style</span>.<span style="color: #660066;">webkitTransform</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;rotate(&quot;</span> <span style="color: #339933;">+</span> speedAngle <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;deg)&quot;</span>;
    speedVal.<span style="color: #660066;">textContent</span> <span style="color: #339933;">=</span> currentSpeed <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;km/h&quot;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> speed <span style="color: #339933;">=</span> pos.<span style="color: #660066;">coords</span>.<span style="color: #660066;">speed</span><span style="color: #339933;">,</span>
     speedVariation <span style="color: #339933;">=</span> <span style="color: #CC0000;">3.6</span><span style="color: #339933;">,</span>
     currentSpeed <span style="color: #339933;">=</span> Math.<span style="color: #660066;">round</span><span style="color: #009900;">&#40;</span>speed<span style="color: #339933;">*</span>speedVariation<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>When I get my initial position and my subsequent position updates through the watchPosition method, I access the current speed, in metres, through the coords attribute. To work out the rough speed I times the speed by the speedVariation var which is 3.6 which will give me the speed in km/h, for miles/hour the variation is 2.237. I do this calculation inside the Math.round function so I get a whole rounded number with no decimal places.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> angleVariation <span style="color: #339933;">=</span> <span style="color: #CC0000;">0.8</span><span style="color: #339933;">,</span>
     initSpeedAngle <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">105</span><span style="color: #339933;">,</span>
     speedAngle <span style="color: #339933;">=</span> initSpeedAngle <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>currentSpeed <span style="color: #339933;">*</span> angleVariation<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>To calculate the corresponding angle to the equivalent speed we are currently getting from the GPS I had to work out the angle variation per kilometre. I knew there was 16&deg; between each 20km/h block. The angle variation then could be worked out to be 0.8&deg; per kilometre, I also needed to have the starting angle of 0km/h and that is exactly -105&deg; from our middle point. With those 2 values plus the currentSpeed I could then work out the angle so the speedometer needle could be correctly rotated to the right spot.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">needle.<span style="color: #660066;">style</span>.<span style="color: #660066;">webkitTransitionDuration</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'500ms'</span>;
needle.<span style="color: #660066;">style</span>.<span style="color: #660066;">webkitTransform</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;rotate(&quot;</span> <span style="color: #339933;">+</span> speedAngle <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;deg)&quot;</span>;
speedVal.<span style="color: #660066;">textContent</span> <span style="color: #339933;">=</span> currentSpeed <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;km/h&quot;</span>;</pre></div></div>

<p>To move the needle when the speed changes and to make that change animate between the two points I use CSS3 transforms and transitions. By setting our <code>-webkit-transition-duration</code> any changes done using the <code>-webkit-transform</code> property will be transitioned smoothly between the current angle and the new angle. The last bit is just to print out the speed so we can compare the needle position to the actual speed being read.</p>
<h2 class="subtitle02">Some CSS3</h2>
<p>I&#8217;ve added some extra CSS3 to the speedo including animations and box-shadow</p>

<div class="wp_syntax"><div class="code"><pre class="css css" style="font-family:monospace;"><span style="color: #cc00cc;">#dial</span> <span style="color: #cc00cc;">#needle</span>
<span style="color: #00AA00;">&#123;</span>
    -moz-box-shadow<span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #933;">1px</span> <span style="color: #933;">3px</span> <span style="color: #cc00cc;">#ffd712</span><span style="color: #00AA00;">,</span> <span style="color: #933;">-1px</span> <span style="color: #933;">-1px</span> <span style="color: #933;">3px</span> <span style="color: #cc00cc;">#feb018</span>;
    -webkit-box-shadow<span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #933;">1px</span> <span style="color: #933;">3px</span> <span style="color: #cc00cc;">#ffd712</span><span style="color: #00AA00;">,</span> <span style="color: #933;">-1px</span> <span style="color: #933;">-1px</span> <span style="color: #933;">3px</span> <span style="color: #cc00cc;">#feb018</span>;
&nbsp;
    -webkit-animation-name<span style="color: #00AA00;">:</span> speedorgo;
    -webkit-animation-duration<span style="color: #00AA00;">:</span> 2s;
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>To add the slight glow around speedo needle by using a dual box-shadow so it appears on both edges. The <a href="http://webkit.org/blog/324/css-animation-2/">-webkit-animation-</a> properties allows me to specify a predefined animation that can be applied to different elements.</p>

<div class="wp_syntax"><div class="code"><pre class="css css" style="font-family:monospace;"><span style="color: #a1a100;">@-webkit-keyframes speedorgo {</span>
    <span style="color: #933;">0%</span>   <span style="color: #00AA00;">&#123;</span> -webkit-transform<span style="color: #00AA00;">:</span> rotate<span style="color: #00AA00;">&#40;</span>-105deg<span style="color: #00AA00;">&#41;</span>; <span style="color: #00AA00;">&#125;</span>
    <span style="color: #933;"><span style="color: #cc66cc;">20</span>%</span>  <span style="color: #00AA00;">&#123;</span> -webkit-transform<span style="color: #00AA00;">:</span> rotate<span style="color: #00AA00;">&#40;</span>41deg<span style="color: #00AA00;">&#41;</span>; <span style="color: #00AA00;">&#125;</span>
    <span style="color: #933;"><span style="color: #cc66cc;">100</span>%</span> <span style="color: #00AA00;">&#123;</span> -webkit-transform<span style="color: #00AA00;">:</span> rotate<span style="color: #00AA00;">&#40;</span>-105deg<span style="color: #00AA00;">&#41;</span>; <span style="color: #00AA00;">&#125;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>By using webkits @-webkit-keyframes rule and giving it a unique name which we applied to our speedo needle in the previous CSS using the -webkit-animation-name property we can do some pretty cool animations. Inside this animation rule I set up the animation to rotate any element it&#8217;s applied to to go from -105&deg; to 41&deg; then back to -105&deg; when you rotate the phone into landscape mode it&#8217;ll trigger the animation and do the animation over a 2 second period.</p>
<h2 class="subtitle02">Pfft! Who needs the internet&#8230;</h2>
<p>Well technically we initially need the internet but after we load the web app for the first time no connection is required for this to work. By taking advantage of the <a href="http://www.thecssninja.com/javascript/how-to-create-offline-webapps-on-the-iphone">application cache</a> we can store all our assets on the phone, and since the GPS can still work without a network connection the speedo will still function fine.</p>
<h2 class="subtitle02">A clear sky</h2>
<p>In order to pick up a consistent speed reading from the GPS you will need to have the phone with a good clear view of the sky. I&#8217;ve found when using it while walking the speed reading will fluctuate quite a lot, going from 0 to the actual speed your doing and back to 0 and back up etc. It becomes more reliable the faster you are moving. I&#8217;m sure with some adjustments to the code getting a more consistent speed reading will be possible.</p>
<h2 class="subtitle02">Go forth and hack</h2>
<p>We have a fun little tech demo that shows what can with some simple JavaScript and CSS3. I don&#8217;t see why this couldn&#8217;t work on an Android, Palm Pre or a Blackberry with the new webkit browser, all of these should or should very soon support the features required for the web app to work. If you get this working in any other smart phone please leave a comment.</p>
<p class="shorty01">Short URL: <a href="http://cssn.in/ja/024">http://cssn.in/ja/024</a></p>
<div class="clear">&nbsp;</div>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/pocket-speedo/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Web Notifications</title>
		<link>http://www.thecssninja.com/javascript/web-notifications</link>
		<comments>http://www.thecssninja.com/javascript/web-notifications#comments</comments>
		<pubDate>Sat, 06 Feb 2010 06:40:58 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[editor draft]]></category>
		<category><![CDATA[web notifications]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=584</guid>
		<description><![CDATA[Google Chrome has recently updated their stable release with some extra goodies; probably most notable is the inclusion of @font-face support which is very welcome. Another not so well know proposal by the Chromium team is to have web notifications which was shipped with the stable release (v4.0.249.78). Web Notifications allows users to get updates [...]]]></description>
			<content:encoded><![CDATA[<p>Google Chrome has recently updated their stable release with some extra goodies; probably most notable is the inclusion of @font-face support which is very welcome. Another not so well know proposal by the Chromium team is to have <a href="http://dev.w3.org/2006/webapi/WebNotifications/publish/">web notifications</a> which was shipped with the stable release (v4.0.249.78).<span id="more-584"></span></p>
<p>Web Notifications allows users to get updates on a webpage even if they&#8217;re not looking at it, shown to them through small notification boxes, think <a href="http://growl.info/screenshots.php">growl</a>. This opens up some great potential for the current web apps out there. When you get a new email it could popup a little notification much like our desktop email clients do now or your twitter page could let you know when new @replies have come in, the possibilities are endless.</p>
<p>Interaction with your web app no longer needs the focus of the user to be informed that something has occurred, I know I would find notifications very useful.</p>
<p>Since this is a proposal and neither a working draft nor an agreed upon API, anything written about in this article is almost guaranteed to change. I will however try to make updates when changes are made. We have our <a href="http://code.google.com/p/chromium/issues/detail?id=34961">first bug</a>. If you&#8217;re using the latest dev version (5.0.317.2) Web Notifications will crash the browser, all previous versions still work fine.</p>
<div id="usermessagea" class="cf_info failure"><strong>Update:</strong> Web notifications spec has been updated <a href="#specchange01">see here for changes</a>.</div>
<h2 class="subtitle02">You&#8217;ve got mail</h2>
<p>I&#8217;ll go through a few examples I have put together on how to setup and start using notifications today.</p>
<p><img src="http://www.thecssninja.com/wp-content/uploads/2010/02/notification01.png" alt="First example of Web Notifications in Chrome" title="First example of Web Notifications in Chrome" width="609" height="353" class="article-img main-img" /><br />
<small style="margin: -30px 0pt 0pt; display: block;">This is what a notification looks like using the <code>createNotification()</code> method</small></p>
<div class="resources01"><a target="_blank" class="demo" title="HTML5 web notifications" href="http://www.thecssninja.com/demo/web_notifications/">View live demos</a> <a target="_blank" class="demo source" title="Download the source of the web notification demo" href="http://www.thecssninja.com/demo/web_notifications/web_notifications.zip">Download the source files</a></div>
<p>Everyone loves the classic &#8220;you&#8217;ve got mail&#8221; voice, so let&#8217;s go through how to do that with Chromes Web Notifications.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">TCNWN.<span style="color: #660066;">myNotifications</span> <span style="color: #339933;">=</span> window.<span style="color: #660066;">webkitNotifications</span>;
&nbsp;
TCNWN.<span style="color: #660066;">setup</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>TCNWN.<span style="color: #660066;">myNotifications</span>.<span style="color: #660066;">checkPermission</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// 1 = Permission is uknown so we request permission</span>
        TCNWN.<span style="color: #660066;">myNotifications</span>.<span style="color: #660066;">requestPermission</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>TCNWN.<span style="color: #660066;">myNotifications</span>.<span style="color: #660066;">checkPermission</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> 0<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// 0 = Permission has been granted to show notifications</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>  
        <span style="color: #006600; font-style: italic;">// 2 = Permission has been denied	</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>;</pre></div></div>

<p>A few things are happening here, for notifications to ever work you need to ask the user for permission. So we use the <code>checkPermission()</code> method to see what status web notifications are in and act on the status accordingly. Once permission has been granted notifications can then be used. <strong id="specchange01">Update:</strong> <code>checkPermission()</code> has been changed to <code>permissionLevel()</code> in the spec, this hasn&#8217;t been pushed out in any release of Chrome so <code>checkPermission()</code> still works.</p>
<p>A bizarre bug with web notifications is asking for permission by calling the <code>requestPermission()</code> method within the page will throw a security exception and won&#8217;t display the permission window where the user can either deny, allow or ignore the notifications request. To get around this I have to run the <code>requestPermission()</code> method as either <del datetime="2010-02-08T00:44:29+00:00">a javascript: URL as this code only works when run in the address bar</del> a <code>javascript:</code> link or by using an <code>onclick</code> function, but still cannot be called programatically (see <a href="http://code.google.com/p/chromium/issues/detail?id=31736">Issue 31736</a>). That&#8217;s why you need to click the first link in the demo. Once permission has been granted we no longer need to resort to that god awful hack, hopefully this is fixed ASAP. You&#8217;ll also notice the notifications object is prefixed with webkit, for similar reason why they prefix new CSS3 properties.</p>
<p>Once permission is allowed the <code>requestPermission()</code> method has a callback parameter where we can setup all our notifications. In this case we pass a function to display our got mail message.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">TCNWN.<span style="color: #660066;">gotMail</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>TCNWN.<span style="color: #660066;">myNotifications</span>.<span style="color: #660066;">checkPermission</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> 0<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		TCNWN.<span style="color: #660066;">notification</span> <span style="color: #339933;">=</span> TCNWN.<span style="color: #660066;">myNotifications</span>.<span style="color: #660066;">createNotification</span><span style="color: #009900;">&#40;</span>
			<span style="color: #3366CC;">&quot;http://www.thecssninja.com/demo/web_notifications/icon.png&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;You've got mail&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;The CSS Ninja has sent you an email&quot;</span>
		<span style="color: #009900;">&#41;</span>;
		TCNWN.<span style="color: #660066;">notification</span>.<span style="color: #660066;">ondisplay</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #003366; font-weight: bold;">var</span> audio <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Audio<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;youvegotmail.mp3&quot;</span><span style="color: #009900;">&#41;</span>;
			audio.<span style="color: #660066;">play</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
			window.<span style="color: #660066;">setTimeout</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;TCNWN.notification.cancel()&quot;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">5000</span><span style="color: #009900;">&#41;</span>;
		<span style="color: #009900;">&#125;</span>
		TCNWN.<span style="color: #660066;">notification</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;You need to allow web notifications for this to work&quot;</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>;</pre></div></div>

<p>In the callback function we create our new notification object using <code>createNotification()</code> method which accepts an icon url, title and body text. To display nothing for any one of these parameters passing in empty quotes (&#8220;&#8221;) will work, otherwise it will display undefined. We then attach an <code>ondisplay</code> event listener so we can run some code when the notification displays. For this demo we load an mp3 to play &#8220;you&#8217;ve got mail&#8221; using HTML5 audio. We then create a <code>setTimeout</code> function to close the notification after 5 seconds. Lastly we execute the <code>show()</code> method so the actual notification displays.</p>
<h2 class="subtitle02">Custom notifications</h2>
<p>Along with the <code>createNotification()</code> we also have the <code>createHTMLNotification()</code> method which allows us to pass an url to a html page to be displayed as the notification. The second example on the demo page will load a notification that fetches a new tweet every 15 seconds and dynamically updates the content.</p>
<p><img src="http://www.thecssninja.com/wp-content/uploads/2010/02/notification02.png" alt="The second example using custom notifications method" title="notification02" width="609" height="353" class="article-img main-img" /><br />
<small style="margin: -30px 0pt 0pt; display: block;">Using <code>createHTMLNotification()</code> method, we can pass a url to be loaded in the notification window</small></p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">TCNWN.<span style="color: #660066;">loadTweet</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>TCNWN.<span style="color: #660066;">myNotifications</span>.<span style="color: #660066;">checkPermission</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> 0<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        TCNWN.<span style="color: #660066;">notification</span> <span style="color: #339933;">=</span> TCNWN.<span style="color: #660066;">myNotifications</span>.<span style="color: #660066;">createHTMLNotification</span><span style="color: #009900;">&#40;</span>url<span style="color: #009900;">&#41;</span>;
        TCNWN.<span style="color: #660066;">notification</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;You need to allow web notifications for this to work&quot;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>;</pre></div></div>

<p>The only difference here is we specify 1 parameter for the <code>createHTMLNotification()</code> method which is the url for the notification we wish to display. I won&#8217;t be going into detail on loading the tweets, to touch on it quickly it uses a JSONP call.</p>
<h2 class="subtitle02">Some observations</h2>
<p>Since playing around with this and trying to figure out how it works I have come across some quirks/bugs. </p>
<p>If you go to the first example that does the &#8220;you&#8217;ve got mail&#8221; notification and click back in the browser before the audio finishes playing, it will stop the audio and the setTimeout function that closes the notification will never fire.</p>
<p>As discussed earlier in the article you can&#8217;t actually request permission to display web notifications from within your code, you have to create a <code>javascript:</code> link that will execute the code. I tried programmatically changing the window.location to a JavaScript url which would fire the <code>requestPermission()</code> method but that wouldn&#8217;t work.</p>
<p>Bringing focus back to the window that called the notification, as stated in the proposal by using <code>window.opener.focus()</code>, doesn&#8217;t currently work.</p>
<p>Finally the last quirk I came across with the twitter demo is that for some tweets with long unbroken strings it will cause the notification window to flicker uncontrollably. Setting <code>white-space: pre-wrap</code> to force long string to be broken can help fix the issue.</p>
<h2 class="subtitle02">Looks promising</h2>
<p>Web notifications do look like a promising addition to the browser land and can create some really useful feedback to a user. With today’s web applications pushing the limits of the current technology available in the browser, I&#8217;m sure many developers will embrace web notifications in clever and exciting new ways.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/web-notifications/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>The File API has changed</title>
		<link>http://www.thecssninja.com/javascript/fileapi</link>
		<comments>http://www.thecssninja.com/javascript/fileapi#comments</comments>
		<pubDate>Thu, 10 Dec 2009 06:53:52 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=530</guid>
		<description><![CDATA[Recently I have been touting how awesome and revolutionary the File API is through a few demo&#8217;s. After some feedback on webapps mailing list there have been some major changes to the API and how it works. I have updated my previous drag and drop upload demo to reflect the API changes, as of Firefox [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I have been touting how awesome and revolutionary the <a href="http://www.w3.org/TR/FileAPI/">File API</a> is through a <a href="http://www.thecssninja.com/javascript/drag-and-drop-upload">few</a> <a href="http://www.thecssninja.com/javascript/font-dragr">demo&#8217;s</a>. After some feedback on webapps mailing list there have been some major changes to the API and how it works.<span id="more-530"></span></p>
<p>I have updated my <a href="http://www.thecssninja.com/demo/drag-drop_upload/">previous drag and drop upload demo</a> to reflect the API changes, as of Firefox 3.6b3 the API supports both the original API and the updated one. The older model will eventually be dropped, it&#8217;s only in there for legacy purposes. To use the demo you will need <a href="http://www.mozilla.com/en-US/firefox/all-beta.html">Firefox 3.6</a> installed. You can also watch the <a href="http://screenr.com/i18">screencast of it in action</a>.</p>
<div class="resources01"><a target="_blank" class="demo" title="Drag and drop files from your computer and they're uploaded using a XMLHttpRequest" href="http://www.thecssninja.com/demo/drag-drop_upload/v2/">View a live demo</a> <a target="_blank" class="demo source" title="Download the source of the Drag and drop upload demo" href="http://www.thecssninja.com/demo/drag-drop_upload/v2/drag-drop_upload.zip">Download the source files</a></div>
<p>The biggest change is with the file handling, it is now processed asynchronously with progress events so we can attach listeners. The advantage of this is if a user drags in many files or a large file the UI won&#8217;t be locked up while it&#8217;s processing the data, much like XmlHttpRequest works.</p>
<h2 class="subtitle02">The File object</h2>
<p>The <a href="https://developer.mozilla.org/en/DOM/File">File object</a> has been updated to reflect the new specs changes and has deprecated all the previous methods we used to get the file in various formats e.g. <em>getAsDataUrl()</em>, <em>getAsText()</em>, <em>getAsBinary()</em>. We now handle these methods in the new <a href="https://developer.mozilla.org/en/DOM/FileReader">FileReader object</a>.</p>
<p>It has also renamed the 2 properties for accessing the files name and size from <em>fileName</em>/<em>fileSize</em> to <em>name</em>/<em>size</em> respectively.</p>
<h2 class="subtitle02">The FileReader object</h2>
<p>This new object allows us to asynchronously read the contents of a file from a drop event.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> reader <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> FileReader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
reader.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;loadend&quot;</span><span style="color: #339933;">,</span> TCNDDU.<span style="color: #660066;">buildImageListItem</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;
reader.<span style="color: #660066;">readAsDataURL</span><span style="color: #009900;">&#40;</span>file<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Instead of locking the UI while we wait for it to loop through all the dropped files and then convert them to a DataUrl. The <em>FileReader</em> does this asynchronously. We attach to the <em>onloadend</em> event handler which will fire once the current file has been read into the <em>result</em> attribute. Upon the event firing we then take the event <em>result</em> and add the DataURL to the source of the image to be displayed to the user while it uploads.</p>
<h2 class="subtitle02">Send the binary data</h2>
<p>Once we have the file we send it to be processed for an XHR call so we can upload it to the server. Same as above we need to create a file reader and attach to the <em>onloadend</em> event which we then pass to the <em>sendAsBinary()</em> method.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> getBinaryDataReader <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> FileReader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
getBinaryDataReader.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;loadend&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>evt<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>xhr.<span style="color: #660066;">sendAsBinary</span><span style="color: #009900;">&#40;</span>evt.<span style="color: #660066;">target</span>.<span style="color: #660066;">result</span><span style="color: #009900;">&#41;</span>;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;
getBinaryDataReader.<span style="color: #660066;">readAsBinaryString</span><span style="color: #009900;">&#40;</span>file<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Similar code we used for the image display handling, but we use the <em>readAsBinaryString()</em> method to return the files binary data for uploading.</p>
<h2 class="subtitle02">Further reading</h2>
<p>As the 3.6 final release date is coming closer Mozilla has been ramping up demos and documentation about the File API. Some good documentation on <a href="https://developer.mozilla.org/en/Using_files_from_web_applications">handling files in web applications</a>.</p>
<p>The <a href="http://hacks.mozilla.org/">hacks blog</a> has recently put up some <a href="http://hacks.mozilla.org/2009/12/w3c-fileapi-in-firefox-3-6/">great information about the File API</a> along with an excellent demo extracting <a href="http://hacks.mozilla.org/2009/12/firefox-36-fileapi-demo-reading-exif-data-from-a-local-jpeg-file/">EXIF data from an image</a>. </p>
<p>Now we just need webkit to push out the File API to their nightly builds.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/fileapi/feed</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Font Dragr: A drag and drop font tester</title>
		<link>http://www.thecssninja.com/javascript/font-dragr</link>
		<comments>http://www.thecssninja.com/javascript/font-dragr#comments</comments>
		<pubDate>Tue, 13 Oct 2009 07:39:27 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[@font-face]]></category>
		<category><![CDATA[Firefox]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=484</guid>
		<description><![CDATA[After playing with the new file API draft spec available in Firefox 3.6 with my drag and drop upload article. I had another idea when I was playing with custom fonts, @font-face, in the browser. What if you could drag an drop a font file (otf, ttf, svg, woff) from your desktop into the browser [...]]]></description>
			<content:encoded><![CDATA[<p>After playing with the new file API draft spec available in Firefox 3.6 with my <a href="http://www.thecssninja.com/javascript/drag-and-drop-upload">drag and drop upload article</a>. I had another idea when I was playing with custom fonts, @font-face, in the browser. What if you could drag an drop a font file (otf, ttf, svg, woff) from your desktop into the browser and have text rendered on the fly using any available valid font.<span id="more-484"></span></p>
<p>In conjunction with Mozilla&#8217;s official announcement for the <a href="http://hacks.mozilla.org/2009/10/woff/">Web Open Font Format (WOFF)</a> and continuing the wanky tradition of removing vowels from web app names, I introduce font dragr.</p>
<div class="resources01"><a href="http://labs.thecssninja.com/font_dragr/" title="HTML5 web app for testing custom font files, drag and drop font testing" class="demo" target="_blank">View the web app</a></div>
<h2 class="subtitle02">What is it?</h2>
<p><a href="http://labs.thecssninja.com/font_dragr/" title="HTML5 web app for testing custom font files, drag and drop font testing" class="demo" target="_blank">Font dragr</a> is an experimental web app that uses HTML5 &#038; CSS3 to create a useful standalone web based application for testing custom fonts, once you visit it for the first time you don&#8217;t need to be online to use it after the initial visit. It allows you, in Firefox 3.6+, to drag and drop font files from your file system into the drop area. The browser will then create a data URL encoded copy to use in the page and render the content in the dropped font.</p>
<h2 class="subtitle02">See it in action</h2>
<p><object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='609' height='366'><param name='movie' value='http://screenr.com/Content/assets/screenr_0817090731.swf' /><param name='flashvars' value='i=20449' /><param name='allowFullScreen' value='true' /><embed src='http://screenr.com/Content/assets/screenr_0817090731.swf' flashvars='i=20449' allowFullScreen='true' width='609' height='366' pluginspage='http://www.macromedia.com/go/getflashplayer'></embed></object></p>
<h2 class="subtitle02">Encoded files</h2>
<p>I went about testing out a few theories on how I could dynamically add a dropped font to be used in the page. I saw this article on embedding <a href="http://robert.accettura.com/blog/2009/07/03/optimizing-font-face-for-performance/">custom fonts using a base64</a> encoded string. In the file API we have the <em>getAsDataURL()</em> method to return a file as a data url for using in a page, I used the same method in my <a href="http://www.thecssninja.com/demo/drag-drop_upload/" class="external-link">drag drop upload demo</a> to display the images.</p>
<h2 class="subtitle02">Inserting into the stylesheet</h2>
<p>The next hurdle was taking that data url and inserting it into the style sheet referenced on the page.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> styleSheet <span style="color: #339933;">=</span> document.<span style="color: #660066;">styleSheets</span><span style="color: #009900;">&#91;</span>0<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
	fontFaceStyle <span style="color: #339933;">=</span> 
	<span style="color: #3366CC;">&quot;@font-face{font-family: CustomFont;src:url(&quot;</span><span style="color: #339933;">+</span>files<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">getAsDataURL</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;);}&quot;</span>;
&nbsp;
styleSheet.<span style="color: #660066;">insertRule</span><span style="color: #009900;">&#40;</span>fontFaceStyle<span style="color: #339933;">,</span> 0<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>In the above code we reference our style sheet using <em>document.styleSheet[0]</em>. We then build our style from the dropped file that we want to insert, notice the <em>files[i].getAsDataURL()</em> is where the magic happens and the current file is converted to a dataURL. We then use the <em>insertRule</em> method to prepend it to the style sheet.</p>
<h2 class="subtitle02">Getting file information and applying the font</h2>
<p>We also get the <em>fileSize</em> of the font and the <em>fileName</em> so we can populate the list item that we create on drop. With the file name I also do some crude validation and I also sanitise the file name in case there is any non alpha numeric characters, it will stop the font from being applied to the container if we have invalid characters.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">acceptedFileExtensions <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^.*\.(ttf|otf|svg|woff)$/i</span>
&nbsp;
droppedFileName <span style="color: #339933;">=</span> droppedFullFileName.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/\..+$/</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;&quot;</span><span style="color: #009900;">&#41;</span>;
droppedFileName <span style="color: #339933;">=</span> droppedFileName.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/\W+/g</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;-&quot;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>For the validation I have a regexp of accepted file extensions so it will only accept font types that work in Firefox. I remove the file extension from the fileName and then replace any non alphanumeric characters, <strong>\W</strong>, with hyphens.</p>
<p>Once we have a semi-friendly name we use that to apply the font family style to the newly created list item and the content container.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">displayContainer.<span style="color: #660066;">style</span>.<span style="color: #660066;">fontFamily</span> <span style="color: #339933;">=</span> droppedFileName;</pre></div></div>

<h2 class="subtitle02">International font friendly</h2>
<p>Dragging in an international based font file will cause the text to render in a default sans serif font. To fix that I have made the main content area editable, you can type some text in your own language which should render in your international based font, this hasn&#8217;t been thoroughly tested. I would appreciate any feedback on using this demo with international fonts.</p>
<h2 class="subtitle02">Work in progress</h2>
<p>I am still very much actively refining and adding more features to this web app. If you have any of your own features/ideas please feel free to suggest/request any improvements or changes. Some I&#8217;m working on now.</p>
<ul>
<li>Using localStorage object to store users dropped fonts and <del datetime="2009-10-28T06:04:17+00:00">save edits to main content area</del>. Main content edits are now stored in localStorage, hit size limit capacity with dropped fonts will look into webDB for font storage.</li>
<li>Better indicating to the user that the content can be edited</li>
<li>Making the drop area highlight on drag</li>
</ul>
<p>I built this to fill a need I had, to quickly test custom fonts, and the idea has grown in to something much bigger and better than I thought it would be. I can see this as not only something cool to show off where HTML5 is heading but something genuinely useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/font-dragr/feed</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Make IE awesome by turning it into Google Chrome</title>
		<link>http://www.thecssninja.com/javascript/make-ie-awesome</link>
		<comments>http://www.thecssninja.com/javascript/make-ie-awesome#comments</comments>
		<pubDate>Wed, 23 Sep 2009 12:15:15 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=455</guid>
		<description><![CDATA[As I&#8217;m sure you all know by now Google made an announcement about their Chrome Frame plugin for IE that turns the Trident rendering engine into the Chrome rendering engine giving IE access to the awesome power that is Chrome. No longer will IE miss out on those awesome new features in CSS3 &#038; HTML5 [...]]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;m sure you all know by now Google made an announcement about their <a href="http://blog.chromium.org/2009/09/introducing-google-chrome-frame.html">Chrome Frame plugin for IE</a> that turns the Trident rendering engine into the Chrome rendering engine giving IE access to the awesome power that is <a href="http://code.google.com/chrome/chromeframe/">Chrome</a>. No longer will IE miss out on those awesome new features in CSS3 &#038; HTML5 the more competent browsers enjoy today such as the soon to be released <a href="http://wave.google.com/">Google Wave</a>.<span id="more-455"></span></p>
<p>I did a post a while back on how <a href="http://www.thecssninja.com/rant/chroming-how-google-is-changing-the-browser">Google Chrome is changing the browser</a>, the landscape is rapidly progressing thanks to Google and the likes of Mozilla, Webkit &#038; Opera. <a href="http://code.google.com/chrome/chromeframe/">This plugin</a> helps push that final frontier into fruition bringing the next set of tools to all major browsers.</p>
<div class="resources01"><a target="_blank" class="demo" title="A demo using canvas that's works in IE with Chrome Frame installed" href="http://www.thecssninja.com/demo/particle_fountain/">View a live demo</a> <a target="_blank" class="demo source" title="Download the source of the canvas demo" href="http://www.thecssninja.com/demo/particle_fountain/particle_fountain.zip">Download the source files</a></div>
<p><small>This demo was slightly modified from the awesome work of http://iterationsix.com/posts/16 particle fountain.</small></p>
<h2 class="subtitle02">How does it work?</h2>
<p>The above demo uses the HTML5 canvas tag to simulate particle effects. If you load this in IE you will be prompted to install Chrome Frame. Setting up a site to make it render using Chrome Frame is a simple meta tag.</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">http-equiv</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;X-UA-Compatible&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;chrome=1&quot;</span>&gt;</span></pre></div></div>

<p>Look familiar? It&#8217;s the same meta tag that IE uses to force IE8 to render in <a href="http://msdn.microsoft.com/en-au/library/cc817574.aspx" target="_blank">compatibility mode</a>. </p>
<p>If IE goes to a site that has this meta tag it will kick-in and render the page using Chrome Frame giving the full power of Google Chrome in IE. Pretty simple and incredibly powerful.</p>
<p><object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='609' height='366'><param name='movie' value='http://screenr.com/Content/assets/screenr_0817090731.swf' /><param name='flashvars' value='i=14065' /><param name='allowFullScreen' value='true' /><embed src='http://screenr.com/Content/assets/screenr_0817090731.swf' flashvars='i=14065' allowFullScreen='true' width='609' height='366' pluginspage='http://www.macromedia.com/go/getflashplayer'></embed></object><br />
<small>IE8 vs IE8 with <em>cf:</em> protocol to force use of Chrome Frame</small></p>
<h2 class="subtitle02">Prompt the user to install Chrome Frame</h2>
<p>What if the user doesn&#8217;t know about or have the Chrome Frame installed on their machine? There&#8217;s a solution for that. Using a script available on Google Ajax APIs</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js&quot;</span>&gt;</span> <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span>
&nbsp;
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;</span>
CFInstall.check();
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></pre></div></div>

<p>The above code will check if Chrome Frame is installed if not it will prompt the user to install it by loading up an iframe with the Chrome Frame site. The <em>check</em> method gives you quite a <a href="http://code.google.com/chrome/chromeframe/developers_guide.html#CFInstall_check_Options">few options</a> all of them are optional the previous link gives a good run down of all the options and what they do.</p>
<h2 class="subtitle02">Force it</h2>
<p>If your are keen to use it before sites start adding the meta tag you can force the site to render using Chrome Frame by appending the <b>cf:</b> protocol to the beginning of any url e.g. <a href="cf:http://bespin.mozilla.com/">cf:http://bespin.mozilla.com/</a> if loaded in IE with Chrome Frame installed it will force the website to render using the Chrome engine.</p>
<h2 class="subtitle02">Early stages</h2>
<p>Right now this plugin is in early development stages but I&#8217;m sure it will move along rapidly to coincide with Google Wave public release.</p>
<p>This is truly an exciting plugin that opens the flood gates to a massive user base being able to use the latest and greatest web apps.<!--more--></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/make-ie-awesome/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Drag and drop file uploading using JavaScript</title>
		<link>http://www.thecssninja.com/javascript/drag-and-drop-upload</link>
		<comments>http://www.thecssninja.com/javascript/drag-and-drop-upload#comments</comments>
		<pubDate>Wed, 26 Aug 2009 08:52:39 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[draganddrop]]></category>
		<category><![CDATA[fileapi]]></category>
		<category><![CDATA[xhr2]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=430</guid>
		<description><![CDATA[With the recent announcement of the File API draft specification being published I&#8217;m sure a lot of people were confused as to what it could really do and why it is truly a powerful API. Firefox&#8217;s latest alpha release of their 3.6 browser, aka Namoroka, is the first to implement this new draft specification. One [...]]]></description>
			<content:encoded><![CDATA[<p>With the recent announcement of the <a href="http://dev.w3.org/2006/webapi/FileUpload/publish/FileAPI.html">File API</a> draft specification being published I&#8217;m sure a lot of people were confused as to what it could really do and why it is truly a powerful API. Firefox&#8217;s latest alpha release of their 3.6 browser, aka Namoroka, is the first to implement this new draft specification.<span id="more-430"></span></p>
<p>One of those powerful things we can do with it is create a file uploader where the user can drag &#038; drop multiple files from their desktop straight into the browser avoiding the previous method of using the file input creating the ultimate killer feature that browsers so badly need.</p>
<p>The below demo only works in <a href="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/3.6a1-candidates/build1/">Firefox 3.6 Alpha 1</a> if you don&#8217;t want to install it you can watch the screencast below.</p>
<div class="cf_info failure" id="usermessagea"><strong>Update:</strong> File API has changed see new article on changes. <a href="http://www.thecssninja.com/javascript/fileapi">The File API has changed</a></div>
<p><object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='609' height='366'><param name='movie' value='http://screenr.com/Content/assets/screenr_0817090731.swf' /><param name='flashvars' value='i=8363' /><param name='allowFullScreen' value='true' /><embed src='http://screenr.com/Content/assets/screenr_0817090731.swf' flashvars='i=8363' allowFullScreen='true' width='609' height='366' pluginspage='http://www.macromedia.com/go/getflashplayer'></embed></object></p>
<div class="resources01"><a href="http://www.thecssninja.com/demo/drag-drop_upload/" title="Drag and drop files from your computer and they're uploaded using a XMLHttpRequest" class="demo" target="_blank">View a live demo</a> <a href="http://www.thecssninja.com/demo/drag-drop_upload/drag-drop_upload.zip" title="Download the source of the Drag and drop upload demo" class="demo source" target="_blank">Download the source files</a></div>
<h2 class="subtitle02">Drag &#038; drop it like it&#8217;s hot</h2>
<p>Now I&#8217;m sure a few people would have seen this functionality already if they watched the Google Wave presentation where they demonstrated drag and drop file uploading, but they used Google Gears to accomplish this. They did mention they will be working on a draft spec to get this functionality into HTML5. This hasn&#8217;t happened yet and instead <a href="http://arunranga.com/blog/about/">Arun Ranganathan</a> of Mozilla wrote the first draft spec for such functionality to be possible.</p>
<p><object width="609" height="366"><param name="movie" value="http://www.youtube.com/v/v_UyVmITiYQ&#038;hl=en&#038;fs=1&#038;start=922"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/v_UyVmITiYQ&#038;hl=en&#038;fs=1&#038;start=922" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="609" height="366"></embed></object><br />
<small>Video will automatically start at 15m22s, where the drag drop is shown</small></p>
<h2 class="subtitle02">The File API</h2>
<p>The File API is what makes this whole thing possible, on the <em>dataTransfer</em> object it has been extended with the <em>file</em> attribute so it can read and convert the files you are dropping which then sends the file information as binary using an xhr <em>upload</em> attribute creating a desktop like behaviour but in the browser, opening great possibilities and much needed functionality that a user will find more intuitive.</p>
<h2 class="subtitle02">XMLHttpRequest 2</h2>
<p>The second revision of the <a href="http://www.w3.org/TR/2009/WD-XMLHttpRequest2-20090820/">XMLHTTPRequest specification</a> adds further functionality so we can actually send our dropped files to the server asynchronously. There are several additions which I use in this demo such as the <a href="http://www.w3.org/TR/2009/WD-XMLHttpRequest2-20090820/#the-upload-attribute"><em>upload</em> attribute</a> and the <a href="http://www.w3.org/TR/2009/WD-XMLHttpRequest2-20090820/#events">progress events</a> like <em>progress</em> and <em>load</em>. With those events we can give the user some detailed feedback such as a percentage loader used in this example.</p>
<h2 class="subtitle02">How it works</h2>
<p>This example uses a few emerging technologies such as xhr2, local file access and the drag and drop API. The order in which the events happen are as follows:</p>
<ul>
<li>The user drags images from their desktop to the drop area in the browser and fires the <em>TCNDDU.handleDrop</em> function.</li>
<li>The <em>dataTransfer</em> object passes through the local files dragged over through the <em>files</em> attribute</li>
<li>Using the <em>getAsDataURL</em> method we can convert the file to a base64 encoded string create an image and sets its source to that string.</li>
<li>The file is then passed into an xhr request where we use the new <em>sendAsBinary</em> method available since Firefox 3.0 and pass in the file as binary data using the <em>getAsBinary</em> method</li>
<li>We attach some <a href="http://www.w3.org/TR/XMLHttpRequest2/#events">progress events</a> to the <a href="http://www.w3.org/TR/XMLHttpRequest2/#the-upload-attribute">upload</a> attribute so we can create a progress bar with percentage feedback and a load progress event so we can remove the progress bar once the image has uploaded successfully</li>
</ul>
<p>I&#8217;ll go through some of the code in the demo to explain a few things in more detail.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> 0; i <span style="color: #339933;">&lt;</span> count; i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	domElements <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span>
		document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'li'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
		document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
		document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'img'</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#93;</span>;
&nbsp;
	domElements<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> files<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">getAsDataURL</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>; <span style="color: #006600; font-style: italic;">// base64 encodes local file(s)</span>
	domElements<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">width</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">300</span>;
	domElements<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">height</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">200</span>;
	domElements<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>domElements<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>;
	domElements<span style="color: #009900;">&#91;</span>0<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">id</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;item&quot;</span><span style="color: #339933;">+</span>i;
	domElements<span style="color: #009900;">&#91;</span>0<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>domElements<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
	imgPreviewFragment.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>domElements<span style="color: #009900;">&#91;</span>0<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
	dropListing.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>imgPreviewFragment<span style="color: #009900;">&#41;</span>;
&nbsp;
	TCNDDU.<span style="color: #660066;">processXHR</span><span style="color: #009900;">&#40;</span>files.<span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> i<span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This for loop is inside the <em>TCNDDU.handleDrop</em> function which will loop through the files, the count var in the for loop is pointing to <em>event.dataTransfer.files.length</em> so we know how many files we are working with.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">domElements<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> files<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">getAsDataURL</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>This line sets the source of the image as a base64 encoded string so we can display the local file to the user straight away.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">fileUpload.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;progress&quot;</span><span style="color: #339933;">,</span> TCNDDU.<span style="color: #660066;">uploadProgressXHR</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;
fileUpload.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;load&quot;</span><span style="color: #339933;">,</span> TCNDDU.<span style="color: #660066;">loadedXHR</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;
fileUpload.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;error&quot;</span><span style="color: #339933;">,</span> TCNDDU.<span style="color: #660066;">uploadError</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>These lines are in the <em>TCNDDU.processXHR</em> that gets fired for each file dragged into the window. The <em>fileUpload</em> points to a <em>new XMLHttpRequest().upload</em> which we attach a few event listeners for progress, load and error so we can give useful feedback to the user.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">xhr.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;POST&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;upload.php&quot;</span><span style="color: #009900;">&#41;</span>;
xhr.<span style="color: #660066;">overrideMimeType</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text/plain; charset=x-user-defined-binary'</span><span style="color: #009900;">&#41;</span>;
xhr.<span style="color: #660066;">sendAsBinary</span><span style="color: #009900;">&#40;</span>file.<span style="color: #660066;">getAsBinary</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Here we post the data to the PHP file for possible further processing etc. We also use the <em>overrideMimeType</em> method to user defined binary and finally use the new <em>sendAsBinary</em> method which has the local file passed in as binary.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">TCNDDU.<span style="color: #660066;">uploadProgressXHR</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>event.<span style="color: #660066;">lengthComputable</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> percentage <span style="color: #339933;">=</span> Math.<span style="color: #660066;">round</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>event.<span style="color: #660066;">loaded</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">100</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> event.<span style="color: #660066;">total</span><span style="color: #009900;">&#41;</span>;
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>percentage <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">100</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			event.<span style="color: #660066;">target</span>.<span style="color: #660066;">log</span>.<span style="color: #660066;">firstChild</span>.<span style="color: #660066;">nextSibling</span>.<span style="color: #660066;">firstChild</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">width</span> <span style="color: #339933;">=</span> 
			<span style="color: #009900;">&#40;</span>percentage<span style="color: #339933;">*</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;px&quot;</span>;
&nbsp;
			event.<span style="color: #660066;">target</span>.<span style="color: #660066;">log</span>.<span style="color: #660066;">firstChild</span>.<span style="color: #660066;">nextSibling</span>.<span style="color: #660066;">firstChild</span>.<span style="color: #660066;">textContent</span> <span style="color: #339933;">=</span> 
			percentage <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;%&quot;</span>;
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>;</pre></div></div>

<p>For the progress event we attached earlier we can check if it will return the right information so we can do a progress bar by checking for the <em>lengthComputable</em> property if that’s available we know the progress event will return two values of <em>loaded</em> and <em>total</em> from there we can work out the percentage that has loaded and adjust our visual cues, in our case a progress bar.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">event.<span style="color: #660066;">target</span>.<span style="color: #660066;">log</span>.<span style="color: #660066;">firstChild</span>.<span style="color: #660066;">nextSibling</span>.<span style="color: #660066;">firstChild</span></pre></div></div>

<p>This line allows us to get access to the current container of the image that is being calculated. <em>event.target</em> will always point back to the xhr object in the <em>TCNDDU.processXHR</em> we added a link to the container by adding <em>log</em> to <em>event.target</em> and pointing it to container variable.</p>
<h2 class="subtitle02">Not without issues</h2>
<p>There are two issues I came across with this demo and most likely are something I have done wrong or it could possibly be a bug.</p>
<p>The first issue I came across was the <em>event.target.log</em> suddenly losing its reference to itself and no longer being able to update the progress bar as the link to the current container is suddenly undefined, this also causes the load event to never get fired and the progress bar never gets removed.</p>
<p>The other issue is the <em>progress</em> event won&#8217;t fire if the file size is below around 140-150kb so no feedback will be given to the user. I&#8217;m not sure if this is intentional or a bug. I hope it&#8217;s the latter as feedback on any sized file would be necessary. You can see this happening on the toucan image in the screencast above.</p>
<p>I took a sceencast of the issues you can watch below.</p>
<p><object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='609' height='366'><param name='movie' value='http://screenr.com/Content/assets/screenr_0817090731.swf' /><param name='flashvars' value='i=8364' /><param name='allowFullScreen' value='true' /><embed src='http://screenr.com/Content/assets/screenr_0817090731.swf' flashvars='i=8364' allowFullScreen='true' width='609' height='366' pluginspage='http://www.macromedia.com/go/getflashplayer'></embed></object></p>
<h2 class="subtitle02">Heading in a great direction</h2>
<p>This functionality is exactly what the web needs going forward and will hopefully see it in other browsers very soon, Google Wave could benefit from this greatly and would make one of their coolest features work without any need for external plugins.</p>
<h2 class="subtitle02">Resources</h2>
<p>This article was inspired from a few examples I have seen throughout my searches for such functionality, what sparked my imagination and got me developing a drag and drop uploader was <a href="https://bug503598.bugzilla.mozilla.org/attachment.cgi?id=388413">this demo</a> found on the Mozilla bug list.</p>
<p>A few people have already figured out and <a href="http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html">demonstrated multiple file uploading</a> in safari 4 and a <a href="http://hacks.mozilla.org/2009/06/xhr-progress-and-richer-file-uploading-feedback/">similar version</a> that works in Firefox 3.5, although you can&#8217;t select multiple files you can upload more than one at a time. That example I used a slightly modified version in this demo to send binary data to the server.</p>
<p>There is also another great article on <a href="http://blog.igstan.ro/2009/01/pure-javascript-file-upload.html">uploading files and posting forms</a> using Ajax. This articles demo works in Firefox 3+.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/drag-and-drop-upload/feed</wfw:commentRss>
		<slash:comments>46</slash:comments>
		</item>
		<item>
		<title>Accessing the GPS in iPhone Safari</title>
		<link>http://www.thecssninja.com/javascript/geolocation-iphone</link>
		<comments>http://www.thecssninja.com/javascript/geolocation-iphone#comments</comments>
		<pubDate>Wed, 08 Jul 2009 13:15:18 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[html 5]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=287</guid>
		<description><![CDATA[Finally with the release of the 3.0 firmware update to the iPhone we now have access to the GPS coordinates in Safari. Using the W3C Geolocation API we can access the users position much the same way a native app would. The user can either allow or disallow the current websites&#8217; access to your location. [...]]]></description>
			<content:encoded><![CDATA[<p>Finally with the release of the 3.0 firmware update to the iPhone we now have access to the GPS coordinates in Safari. Using the <a href="http://www.w3.org/TR/geolocation-API/">W3C Geolocation API</a> we can access the users position much the same way a native app would. The user can either allow or disallow the current websites&#8217; access to your location.<span id="more-287"></span> </p>
<p>This demo will need the iPhone 3G with the 3.0 firmware update or Firefox 3.5 in order to work. The iPhone will give the better results as it has access to the GPS where as Firefox depends on the hardware available.</p>
<div class="resources01"><a href="http://www.thecssninja.com/demo/gps_browser/" title="Location aware web app" class="demo" target="_blank">View a live demo</a> <a href="http://www.thecssninja.com/demo/gps_browser/gps_browser.zip" title="Download the source of the Location aware web app demo" class="demo source" target="_blank">Download the source files</a></div>
<h2 class="subtitle02">Some hurdles</h2>
<p>You may have noticed that I&#8217;m not using Google or Yahoo Maps APIs to plot my location, this is due to both having restrictions on using it in conjunction with real time locations. In <a href="http://maps.google.com/help/terms_maps.html">Google Maps Terms of Use</a>.</p>
<blockquote cite="http://maps.google.com/help/terms_maps.html"><p>use the Service or Content with any products, systems, or applications for or in connection with (i) real time navigation or route guidance, including but not limited to turn-by-turn route guidance that is synchronized to the position of a user&#8217;s sensor-enabled device; or (ii) any systems or functions for automatic or autonomous control of vehicle behaviour.</p></blockquote>
<p><a href="http://info.yahoo.com/legal/us/yahoo/maps/mapsapi/mapsapi-2141.html">Yahoo&#8217;s terms</a> are a bit different they still restrict use of real time location abilities to be no younger than 6 hours, essentially making the safari&#8217;s location awareness a no go zone for these 2 services.</p>
<blockquote cite="http://info.yahoo.com/legal/us/yahoo/maps/mapsapi/mapsapi-2141.html"><p>&#8230;use the Yahoo! Maps APIs with location information that is less than 6 hours old and derived from a GPS device or any other location sensing device;</p></blockquote>
<h2 class="subtitle02">CloudMade to the rescue</h2>
<p>Thanks to <a href="http://www.cloudmade.com/about">CloudMade</a> who is putting a <a href="http://developers.cloudmade.com/projects">rock solid set of tools and API&#8217;s in various languages</a> so we can access the <a href="http://www.openstreetmap.org/">OpenStreetMap</a> map data. Only difference is that these maps are created by the community and are licensed under the <a href="http://creativecommons.org/licenses/by-sa/2.0/">Creative Commons Attribution/ShareAlike licence, version 2</a> which means there are no such restrictions that we would of had with Google or Yahoo maps. I highly recommend you read where they are <a href="http://www.opengeodata.org/?p=262">heading in terms of their licensing</a> and help in giving back to their community by creating maps.</p>
<h2 class="subtitle02">How it works</h2>
<p>Now we have a maps API where we won&#8217;t be abusing the terms of use by using it in conjunction with real time locations. We&#8217;ll get stuck into how to use the <a href="http://www.w3.org/TR/geolocation-API/">W3C Geolocation API</a>.</p>
<h2 class="subtitle02">Request the users location</h2>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">getCurrentPosition</span><span style="color: #009900;">&#40;</span>success<span style="color: #339933;">,</span> fail<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>The above line will try to obtain the users current location using the <em>getCurrentPosition</em> method this can be passed up to 3 arguments; the success callback function, the error callback function and the position options: <em>enableHighAcurracy</em>, <em>timeout</em> &#038; <em>maximumAge</em>.</p>
<p>Upon successfully obtaining the users location the success function will get passed the position object which will contain the <em>coords</em> and <em>timestamp</em> attributes. The <em>coords</em> attribute is the one we need to extract information about the user location and has the following properties available:</p>
<ul>
<li>latitude</li>
<li>longitude</li>
<li>altitude</li>
<li>accuracy</li>
<li>altitudeAccuracy</li>
<li>heading</li>
<li>speed</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">getCurrentPosition</span><span style="color: #009900;">&#40;</span>success<span style="color: #339933;">,</span> fail<span style="color: #009900;">&#41;</span>;
<span style="color: #006600; font-style: italic;">// success callback, gets passed position object</span>
success<span style="color: #009900;">&#40;</span>position<span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// 'position' can be named anything</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Your latitude: &quot;</span> <span style="color: #339933;">+</span> position.<span style="color: #660066;">coords</span>.<span style="color: #660066;">latitude</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;longitude: &quot;</span>
 		<span style="color: #339933;">+</span> position.<span style="color: #660066;">coords</span>.<span style="color: #660066;">longitude</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Not all of the geolocation information in the coords attribute is available to the iPhone, <em>heading</em> and <em>speed</em> currently return <em>null</em> <del datetime="2009-07-04T05:18:30+00:00">but I suspect that both will be functional in the iPhone 3G S thanks to the compass and coreLocation updates</del>. Both these attributes still return <em>null</em> on the iPhone 3GS which is surprising. Speed can alternatively be calculated by using the <a href="http://www.movable-type.co.uk/scripts/latlong.html">Haversine formula</a> to obtain the distance travelled between two points which can then be used to compare time and distance to make a pretty accurate speed approximation. </p>
<p>The options available as the 3rd argument that can be passed to the <em>getCurrentPosition</em> method are:</p>
<ul>
<li>enableHighAccuracy</li>
<li>timeout</li>
<li>maximumAge</li>
</ul>
<p>These options can help in forcing the error callback and having a fallback option if the request cannot be obtained before the <em>timeout</em> ends or the location wasn&#8217;t obtained within the <em>maximumAge</em> set. <em>enableHighAccuracy</em> will force the GPS to get the most accurate results possible this will take longer and chew through the battery.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">getCurrentPosition</span><span style="color: #009900;">&#40;</span>success<span style="color: #339933;">,</span> fail<span style="color: #339933;">,</span><span style="color: #009900;">&#123;</span>maximumAge<span style="color: #339933;">:</span> <span style="color: #CC0000;">300000</span><span style="color: #339933;">,</span> timeout<span style="color: #339933;">:</span>0<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Both <em>maximumAge</em> and <em>timeout</em> are expressed in milliseconds. This is basically saying get the last known location that is no older than 5 minutes, if no position is found timeout immediately and fire the error callback function.</p>
<h2 class="subtitle02">Updating location</h2>
<p>Getting the users initial location is great and all but what we really need is a way to get constant updates of any changes in the users&#8217; location. Thankfully the geolocation API also has the <em>watchPosition</em> method which will fire upon a change in the users&#8217; location.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> updateLocation <span style="color: #339933;">=</span> navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">watchPosition</span><span style="color: #009900;">&#40;</span>success<span style="color: #339933;">,</span> fail<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>This, like the <em>getCurrentPosition</em> method, takes the same arguments the only difference above is that I have stored the <em>watchPosition</em> method in a variable, this is so we can cancel it at anytime if we no longer need to watch for any changes in position.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">clearWatch</span><span style="color: #009900;">&#40;</span>updateLocation<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>This will cancel the watchPosition and stop it from firing the success or error callback. It works in much the same way the <em><a href="http://www.w3schools.com/js/js_timing.asp">clearTimeout</a></em> method works for the <em>setTimeout</em> method.</p>
<h2 class="subtitle02">Handling errors</h2>
<p>If something goes wrong with obtaining the users location e.g. the user decides not to share their location to your web app. We have the error callback so we can handle the situations that might occur and present useful actions or information back to the user.</p>
<p>The <a href="http://www.w3.org/TR/geolocation-API/#position_error_interface">PositionError interface</a> has 4 possible scenarios:</p>
<ul>
<li>UNKNOWN_ERROR (code 0)</li>
<li>PERMISSION_DENIED (code 1)</li>
<li>POSITION_UNAVAILABLE (code 2)</li>
<li>TIMEOUT (code 3)</li>
</ul>
<p>We have 2 attributes on the error callback available which are <em>code</em> &amp; <em>message</em> these will return either the code number 0-3 or the message.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">getCurrentPosition</span><span style="color: #009900;">&#40;</span>success<span style="color: #339933;">,</span> fail<span style="color: #009900;">&#41;</span>;
<span style="color: #006600; font-style: italic;">// fail callback, gets passed error object</span>
fail<span style="color: #009900;">&#40;</span>error<span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// 'error' can be named anything</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">switch</span><span style="color: #009900;">&#40;</span>error.<span style="color: #660066;">code</span><span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// Returns 0-3</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">case</span> 0<span style="color: #339933;">:</span>
			<span style="color: #006600; font-style: italic;">// Unknown error alert error message</span>
			<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>error.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span>;
			<span style="color: #000066; font-weight: bold;">break</span>;
&nbsp;
		<span style="color: #000066; font-weight: bold;">case</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">:</span>
			<span style="color: #006600; font-style: italic;">// Permission denied alert error message</span>
			<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>error.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span>;
			<span style="color: #000066; font-weight: bold;">break</span>;
		... <span style="color: #660066;">etc</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2 class="subtitle02">Just the beginning</h2>
<p>The iPhone 3.0 release isn&#8217;t the only browser to support Geolocation API, currently Firefox 3.5, Opera 10 beta and Opera Mobile 9.7 beta though this is speculation. I&#8217;m sure the other browser vendors will follow in their new releases.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/geolocation-iphone/feed</wfw:commentRss>
		<slash:comments>64</slash:comments>
		</item>
		<item>
		<title>How to create offline webapps on the iPhone</title>
		<link>http://www.thecssninja.com/javascript/how-to-create-offline-webapps-on-the-iphone</link>
		<comments>http://www.thecssninja.com/javascript/how-to-create-offline-webapps-on-the-iphone#comments</comments>
		<pubDate>Tue, 28 Apr 2009 04:30:46 +0000</pubDate>
		<dc:creator>The Css Ninja</dc:creator>
				<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[xhtml]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.thecssninja.com/?p=252</guid>
		<description><![CDATA[Recently Google launched their latest mobile version of Gmail optimised for iPhone and Android based browsers. One of the features that stood out was the offline access thanks to the browsers support of html5 application cache. Documentation on the application cache feature supported in safari iPhone 2.1+ is scarce and of that documentation it doesn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>Recently <a href="http://googlemobile.blogspot.com/2009/04/gmail-gets-new-engine-for-iphone-and.html">Google launched their latest mobile version of Gmail</a> optimised for iPhone and Android based browsers. One of the features that stood out was the offline access thanks to the browsers support of <a href="http://www.w3.org/TR/offline-webapps/#offline">html5 application cache</a>.<span id="more-252"></span></p>
<p>Documentation on the application cache feature supported in safari iPhone 2.1+ is scarce and of that documentation it doesn&#8217;t go into great detail. The best place to learn about this is on the <a href="http://developer.apple.com/safari/mobile.php">Safari DevCenter under the mobile section</a>, there it has 2 documents introducing the user to offline webapps; the first is a <a href="http://developer.apple.com/safari/library/codinghowtos/mobile/dataManagement/index.html#LOCAL_DATA-CREATE_A_WEB_APPLICATION_THAT_WILL_FUNCTION_OFFLINE">quick rundown on just the manifest file</a> and the second article touches on a few <a href="https://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/chapter_2_section_1.html#//apple_ref/doc/uid/TP40007256-CH7-DontLinkElementID_10">more features available to offline webapps</a> such as the javascript events for updating the cache when the user is online. We&#8217;ll delve into these later in the article but first let&#8217;s take a look at a working example.</p>
<div class="resources01"><a class="demo" title="Offline Webapp" href="http://www.thecssninja.com/demo/offline_webapp/">View a live demo</a> <a class="demo source" title="Download the source of the offline webapp demo" href="http://www.thecssninja.com/demo/offline_webapp/offline_webapp.zip">Download the source files</a></div>
<div class="cf_info failure" id="usermessagea"><strong>Update:</strong> Added additional information about the <a href="#event-summary">event summary</a> and the order in which events get executed. Added link to useful tool for sniffing file <a href="#web-sniffer">Content-Types</a>.</div>
<p>To see the offline webapp in action, load the <a title="Offline Webapp" href="http://www.thecssninja.com/demo/offline_webapp/">demo</a> on your iPhone, then turn Airplane Mode on, re-open Safari and reload the <a title="Offline Webapp" href="http://www.thecssninja.com/demo/offline_webapp/">demo</a>. This time it will fetch the files from the cache that was created on the initial load.</p>
<h2 class="subtitle02">How does it all work?</h2>
<p>To get a basic offline webapp up and running is incredibly simple but it does have one caveat which tends to get a lot of people frustrated quickly when for some reason the offline feature isn&#8217;t working. We&#8217;ll explain that issue shortly.</p>
<p>The first thing we need to do is create what is called a cache manifest file which has references to all the resources we want to save. Whether it be JavaScript, CSS, images or html, below we can view the manifest file used in the <a title="Offline Webapp" href="http://www.thecssninja.com/demo/offline_webapp/">demo</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict html4strict" style="font-family:monospace;">CACHE MANIFEST
&nbsp;
# Offline cache v1
# html files
article.html
&nbsp;
# css files
assets/_styles.css
&nbsp;
# js files
assets/_javascript.js
&nbsp;
# images
assets/ico_ninja-star.gif</pre></div></div>

<p>The manifest file is a simple plain text file that holds the file names you wish to cache, the paths are relevant to where you saved the manifest file which is recommended to be in the root of the site. This file will be saved as <em>filename</em>.manifest, where <em>filename</em> is anything you wish. Lines that start with a # are comments and are ignored by the cache.</p>
<h2 class="subtitle02">Referencing the cache file</h2>
<p>We now have our cache manifest file setup and named, the next thing we need to do is reference that file in the html so this offline access will function for the specified files in the manifest.</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span> manifest<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;thecssninja.manifest&quot;</span>&gt;</span></pre></div></div>

<p>The manifest file is referenced in the html tag through the manifest attribute and just points to the filename.</p>
<p>Now the one issue that catches a lot of people when trying this out is not setting up the mime type correctly in their chosen web server. Whether it be IIS, Apache or something else, you&#8217;ll need to make sure that the <em>.manifest</em> file is fed through as <em>text/cache-manifest</em>. For example in IIS the .manifest mime type is actually already declared to serve .manifest files as <em>application/x-ms-manifest</em> for offline webapps to work this will need to be changed to mime type <em>text/cache-manifest</em>.</p>
<p>For Apache you can add the <em>text/cache-manifest</em> to the <em>mime.types</em> file found in the <em>conf</em> folder in apache and add the following to the bottom of the file.</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict html4strict" style="font-family:monospace;"># html 5 application cache - offline access
text/cache-manifest			manifest</pre></div></div>

<p>For IIS open up the IIS manager found in Control Panel > Administrative Tools > Internet Information Services double click the Mime Types icon in the manager and scroll down the list until you find the .manifest file and edit the mime type to have <em>text/cache-manifest</em>.</p>
<p><img src="http://www.thecssninja.com/wp-content/uploads/2009/04/img_iis-mimetypes.png" alt="IIS 7.0 Manager Mime Types" title="IIS 7.0 Manager Mime Types" width="609" height="280" class="article-img main-img" /></p>
<p>That&#8217;s it, to get a basic offline webapp to work is incredibly simple all it takes is the manifest file to specify which files to cache, declare it in on the <em>&lt;html&gt;</em> tag using the manifest attribute and you have yourself a site still accessible even if the user has no network connection.</p>
<p><span  id="web-sniffer">UPDATE:</span> <a href="#comment-925">GeoNomad</a> in the comments suggested a great tool to make sure your manifest file is being fed through with the correct mime type, <a href="http://web-sniffer.net/">Web Sniffer</a>. I put my <a href="http://web-sniffer.net/?url=http%3A%2F%2Fwww.thecssninja.com%2Fdemo%2Foffline_webapp%2Fthecssninja.manifest&#038;submit=Submit&#038;http=1.1&#038;gzip=yes&#038;type=GET&#038;uak=0">manifest file</a> through the Web Sniffer tool, you can see that the <em>Content-Type</em> is set as <em>text/cache-manifest</em>.</p>
<h2 class="subtitle02">Updating the cache</h2>
<p>If you want to update the cache you either need to change/add file references to the manifest and then tell the cache to update. Updating a file that the manifest calls will not make the cache reflect the changes. The <a href="https://developer.mozilla.org/en/Offline_resources_in_Firefox#section_11">mozilla developer article on applicationCache</a> makes a good suggestion to version your manifest file as the JavaScript events described below will only fire if there is a change to the manifest file. To update the cache we have:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">window.<span style="color: #660066;">applicationCache</span>;</pre></div></div>

<p>This object has various stages depending on what the cache is doing which can be checked by using the <em>.status</em> method. There are 6 different stages:</p>
<ul>
<li><strong>Status 0 (UNCACHED)</strong> is returned which means that there is no cache available</li>
<li><strong>Status 1 (IDLE)</strong> is returned means the cache you have is currently the most up-to-date</li>
<li><strong>Status 2 (CHECKING)</strong> is returned means there is a change in your manifest file and it is checking it for changes</li>
<li><strong>Status 3 (DOWNLOADING)</strong> is retuned means changes have been found and they are being added to your cache</li>
<li><strong>Status 4 (UPDATEREADY)</strong> is retuned means your new cache is ready to be updated and override your current cache</li>
<li><strong>Status 5 (OBSOLETE)</strong> is returned means your cache is no longer valid meaning it has been removed</li>
</ul>
<p>These available statuses can be attached to the applicationCache object with event listeners so we can tell the web app what to do on what status. In our case we want to update the cache to reflect changes we have done.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> webappCache <span style="color: #339933;">=</span> window.<span style="color: #660066;">applicationCache</span>;
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> updateCache<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	webappCache.<span style="color: #660066;">swapCache</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span>
&nbsp;
webappCache.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;updateready&quot;</span><span style="color: #339933;">,</span> updateCache<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>In the above example we attach an event listener to the applicationCache looking for the updateready status which means there is a change to the manifest file and our cache is ready to be updated we do so by using the <em><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#dom-appcache-swapcache">swapCache()</a></em> method.</p>
<p>There is 2 more event handlers <del datetime="2009-07-31T14:46:12+00:00">which do not appear in the <em>window.applicationCache.status</em></del> these are part of the event summary. Those are <em>error</em> &amp; <em>progress</em>. We&#8217;ll take a look at how to use the <em>error</em> event, the <em>progress</em> event is basically the same as the <em>downloading</em> event handler.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> webappCache <span style="color: #339933;">=</span> window.<span style="color: #660066;">applicationCache</span>;
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> errorCache<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Cache failed to update&quot;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span>
&nbsp;
webappCache.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;error&quot;</span><span style="color: #339933;">,</span> errorCache<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>All the error event handler does is return the specified function we attached in the event listener when the cache is not available or does not exist.</p>
<h2 class="subtitle02" id="event-summary">Event summary</h2>
<p>In the applicationCache we have <a href="http://www.whatwg.org/specs/web-apps/current-work/#event-summary">various events available</a> so when the cache is being updated, or as mentioned above when something goes wrong. We can attach to those events and keep the user informed on what is happening. These events will execute in specific order based on what is happening with the cache and therefore give us useful hooks to represent that back to the user.</p>
<p>Pete who <a href="#comment-309">commented below</a> and needed a way of indicating to the user that the cache was downloading prompted me to look further into the events that get fired and which ones would be useful in this scenario. I <a href="http://www.thecssninja.com/demo/offline_webapp/loader/">created a demo</a> which will indicate to the user that the cache is downloading by showing a loading icon and once the cache had finished downloading, the loader would be hidden.</p>
<p>The event order for this example was as follows:</p>
<ul>
<li><em>checking</em> &#8211; The page loads and the cache is checked for any changes.</li>
<li><em>progress</em> &#8211; The download event actually gets fired before this but we don&#8217;t need to hook into that. The <em>progress</em> event will fire for each file that is referenced in your manifest until the cache has finished downloading.</li>
<li><em>cached</em> &#8211; The cache has successfully downloaded and the cached event is fired so we utilise that to hide the loader.</li>
<li><em>updateready</em> &#8211; This event is fired so we can then swap the old cache with the newly downloaded one.</li>
</ul>
<p>In the above mentioned demo we also attached event listeners to the error and noupdate events so we can handle errors and if the cache is already up-to-date.</p>
<h2 class="subtitle02">Is the user online</h2>
<p>There is also a new method on the <em>navigator</em> object called <em>onLine</em> which returns a boolean value if there is a network connection or not.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">navigator.<span style="color: #660066;">onLine</span></pre></div></div>

<p>In the <a href="http://www.thecssninja.com/demo/offline_webapp/">article example</a> the onLine method is used to update the title if the user is on/offline.</p>
<h2 class="subtitle02">Only the beginning</h2>
<p>The applicationCache is not yet finalised and is of course subject to change with newer and refined features. I&#8217;m sure there will be additions in the upcoming iPhone OS 3.0 release. If there are updates unfortunately these cannot be discussed until the NDA is lifted. But of course this won&#8217;t stop us speculating.</p>
<p>Some of the features available in applicationCache on firefox 3.1 and safari 4 will inevitably be added in future releases of the iPhone OS. Such as the <a href="https://developer.mozilla.org/en/Offline_resources_in_Firefox#section_8"><em>NETWORK:</em></a> and <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#a-sample-manifest"><em>FALLBACK:</em></a> sections in the manifest file, these allow for the developer to specify a file they wish to never cache or to have a file load if something fails with the first option.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thecssninja.com/javascript/how-to-create-offline-webapps-on-the-iphone/feed</wfw:commentRss>
		<slash:comments>176</slash:comments>
		</item>
	</channel>
</rss>
