<?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>bunnyhero dev &#187; JavaScript</title>
	<atom:link href="http://www.bunnyhero.org/category/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bunnyhero.org</link>
	<description>Notes on iPhone, Flash and Web development</description>
	<lastBuildDate>Fri, 23 Jul 2010 18:00:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>iPhone offline web applications: tips and gotchas</title>
		<link>http://www.bunnyhero.org/2010/01/24/iphone-offline-web-applications-tips-and-gotchas/</link>
		<comments>http://www.bunnyhero.org/2010/01/24/iphone-offline-web-applications-tips-and-gotchas/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 01:13:29 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[application cache]]></category>
		<category><![CDATA[gotchas]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=283</guid>
		<description><![CDATA[I spent this evening updating my &#8220;iPhone VR&#8221; Javascript/CSS demo to work with iPhone OS 3.0 (it had stopped working 100% correctly since the OS update). I also decided to spend some time making it work as an offline-capable web application. The basic process of making your web app cacheable offline is, in theory, fairly straightforward, and generally well-documented at Apple&#8217;s website. I ran into some interesting headaches though. Gotchas: First thing to note is that your web server must serve your cache manifest file with a MIME type of text/cache-manifest. This may mean editing mime.types to add a line that looks like this: text/cache-manifest manifest or perhaps a line in httpd.conf that looks like this: AddType text/cache-manifest .manifest The next thing that had me stumped for a while: while your web server may know how to take the URL http://example.com/webapp/ and automatically and invisibly serve up the file http://example.com/webapp/index.html, your offline web app knows nothing of this mapping of webapp/ to webapp/index.html. If the URL bar reads http://example.com/webapp/ and you save it locally using a home screen bookmark, it will fail to launch correctly if the device is offline, even if index.html file has been cached. The device simply [...]]]></description>
			<content:encoded><![CDATA[<p>I spent this evening updating my <a href="http://www.bunnyhero.org/2008/10/13/iphone-vr-viewing-3d-panoramas-in-safari-using-javascript-and-webkit-transform/">&#8220;iPhone VR&#8221; Javascript/CSS demo</a> to work with iPhone OS 3.0 (it had stopped working 100% correctly since the OS update). I also decided to spend some time making it work as an <strong>offline-capable web application</strong>.</p>
<p>The basic process of making your web app cacheable offline is, in theory, fairly straightforward, and generally <a href = "http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html" >well-documented at Apple&#8217;s website</a>. I ran into some interesting headaches though.</p>
<h3>Gotchas:</h3>
<ul>
<li>First thing to note is that your <strong>web server must serve your cache manifest file with a MIME type of <code>text/cache-manifest</code></strong>. This may mean editing <code>mime.types</code> to add a line that looks like this:

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">text/cache-manifest   manifest</pre></div></div>

<p>or perhaps a line in <code>httpd.conf</code> that looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #00007f;">AddType</span> text/cache-manifest  .manifest</pre></div></div>

</li>
<li>The next thing that had me stumped for a while: while your web server may know how to take the URL <code>http://example.com/<strong>webapp/</strong></code> and automatically and invisibly serve up the file <code>http://example.com/<strong>webapp/index.html</strong></code>, <strong>your offline web app knows nothing of this mapping of <code>webapp/</code> to <code>webapp/index.html</code></strong>. If the URL bar reads <code>http://example.com/webapp/</code> and you save it locally using a home screen bookmark, <strong>it will fail to launch correctly if the device is offline, even if <code>index.html</code> file has been cached</strong>. The device simply does not know to look for <code>webapp/index.html</code> instead of <code>webapp/</code>. Thus, you must ensure that the URL bar reads <code>webapp/index.html</code> before the user makes a home screen bookmark.</li>
<li>At first, I thought I would enforce the above with a tiny bit of JavaScript that simply reads <code>window.location</code> and redirects to <code>window.location + "index.html"</code> if the URL ends in a slash. This worked while online, but it broke my app when offline, even when the redirection was not taken. Why? It seems that <strong>any reference to <code>window.location</code> in your script is treated as network access. Since the device is offline, it generates an error alert.</strong>
<p>Instead, I made my app live at <code>webapp/main.html</code>, and created a small <code>webapp/index.html</code> file that simply redirects to <code>main.html</code>. (I could have used a server redirect inside of an <code>.htaccess</code> file instead, but I chose not to, for no particular reason.)</li>
</ul>
<h3>Tips:</h3>
<ul>
<li>You can specify a <strong>custom icon for the home screen bookmark</strong> using a <code>&lt;link&gt;</code> element, like so:

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;apple-touch-icon&quot; href=&quot;custom_icon.png&quot; /&gt;</pre></div></div>

<p><strong>If you don&#8217;t want iPhone to automatically apply the &#8220;shine&#8221; effect on your icon,</strong> use the following instead:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;apple-touch-icon-precomposed&quot; href=&quot;custom_icon.png&quot; /&gt;</pre></div></div>

</li>
<li>Since iPhone OS 3.0, <strong>offline web apps can have custom splash screens</strong>, just a like a native app! Simply add a <code>link</code> element to your web page:

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;apple-touch-startup-image&quot; href=&quot;/splash.png&quot; /&gt;</pre></div></div>

</li>
</ul>
<p>If you want to see the results of all this, go to <a href="http://bunnyherolabs.com/iphone/xform/">http://bunnyherolabs.com/iphone/xform/</a> on your iPhone or iPod Touch, then click the &#8220;+&#8221; (add bookmark) button and choose &#8220;Add to Home Screen.&#8221; Now you can click on the &#8220;Panorama&#8221; icon on your home screen to see the demo at any time, even when not connected to the internet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2010/01/24/iphone-offline-web-applications-tips-and-gotchas/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Twitter follower tracker</title>
		<link>http://www.bunnyhero.org/2009/09/18/twitter-follower-tracker/</link>
		<comments>http://www.bunnyhero.org/2009/09/18/twitter-follower-tracker/#comments</comments>
		<pubDate>Sat, 19 Sep 2009 03:42:16 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=232</guid>
		<description><![CDATA[There are a number of services out there that are supposed to notify you of when people follow or unfollow you on Twitter. I&#8217;ve tried a few and most of them seem mostly broken. The best one out there, formerly at joule.marnanel.org, is currently down and its creator doesn&#8217;t know when it&#8217;s coming back, alas. The problem with running a service like that is scaling when huge numbers of people join. It always struck me that something like this might be better handled on the client side. It&#8217;s such a conceptually simple operation (fetch followers list, do a diff with the last time you checked), and each person/computer only has to worry about their own accounts. I&#8217;m surprised that Twitter clients don&#8217;t have functionality for this built in (that I know of). I&#8217;ve been wanting to play with the Twitter API for a while, and I&#8217;ve also wanted to delve a little bit into some of the newer features that modern web browsers have to offer, so I&#8217;ve created a simple Twitter follower tracker proof of concept in JavaScript. It&#8217;s a very crude app. It doesn&#8217;t update automatically&#8212;you have to manually refresh the data when you want to check to [...]]]></description>
			<content:encoded><![CDATA[<p>There are a number of services out there that are supposed to notify you of when people follow or unfollow you on <a href="http://twitter.com/">Twitter</a>. I&#8217;ve tried a few and most of them seem mostly broken. The best one out there, formerly at <strong>joule.marnanel.org</strong>, is currently down and <a href="http://marnanel.livejournal.com/1280059.html">its creator doesn&#8217;t know when it&#8217;s coming back</a>, alas.</p>
<p>The problem with running a service like that is scaling when huge numbers of people join. It always struck me that something like this <strong>might be better handled on the client side</strong>. It&#8217;s such a conceptually simple operation (fetch followers list, do a diff with the last time you checked), and each person/computer only has to worry about their own accounts. I&#8217;m surprised that Twitter clients don&#8217;t have functionality for this built in (that I know of).</p>
<p>I&#8217;ve been wanting to play with the <a href="http://apiwiki.twitter.com/">Twitter API</a> for a while, and I&#8217;ve also wanted to delve a little bit into some of the newer features that modern web browsers have to offer, so I&#8217;ve created a simple <a href="http://bunnyherolabs.com/follow/">Twitter follower tracker</a> proof of concept in JavaScript.</p>
<p><a href="http://www.bunnyhero.org/wp-content/uploads/2009/09/Picture-48.png"><img class="aligncenter size-medium wp-image-236" title="Twitter follower tracker in action" src="http://www.bunnyhero.org/wp-content/uploads/2009/09/Picture-48-300x169.png" alt="Twitter follower tracker in action" width="300" height="169" /></a><br />
It&#8217;s a very crude app. It doesn&#8217;t update automatically&mdash;you have to manually refresh the data when you want to check to see if your follower list has changed. Also, the new and lost followers are shown only with their numeric user IDs. Each ID is a link, however&mdash;clicking on the link will fetch that user&#8217;s information and convert the number into a username. Clicking again will take you to that user&#8217;s profile. I did this to minimize the quantity of Twitter API calls.</p>
<p>Yes, the page is hosted on my site, but <strong>all of the work is done by the browser</strong>. It uses <a href="http://jquery.com/">jQuery</a> to fetch the data from Twitter; thanks to Twitter&#8217;s handy <a href="http://apiwiki.twitter.com/Things-Every-Developer-Should-Know#5Parametershavecertainexpectations">&#8220;callback&#8221; parameter</a> in JSON responses, I don&#8217;t have to worry about having a proxy on my server handle any cross-domain requests. I use the <a href="http://hacks.mozilla.org/2009/06/localstorage/"><code>localStorage</code></a> property, supported in some modern browsers, to remember the user&#8217;s follower history. LocalStorage is interesting and easy to use. It&#8217;s like a giant browser cookie, except that its contents don&#8217;t get sent to the server.</p>
<p><strong>Caveats:</strong> it&#8217;s just a proof of concept. I&#8217;ve only tested it (minimally) on a <a href="http://www.apple.com/safari/">couple</a> of <a href="http://www.getfirefox.com/">browsers</a>, on Mac OS X. <strong>It doesn&#8217;t do <em>any</em> error checking</strong>. I&#8217;m sure it will break if you have a lot of followers. I&#8217;m sure it may break if you look at it funny. It may well have security issues. I&#8217;m not sure what the storage limits are for <code>localStorage</code>, but if you hit the limit, I have no idea what will happen. Since <code>localStorage</code> is in the browser, you won&#8217;t be able to see your follower history if you move to a different machine or even to a different browser on the same machine.</p>
<p>If you want to look under the hood, all the real work is done in <a href="http://bunnyherolabs.com/follow/follow.js"><code>follow.js</code></a>. It&#8217;s not well-commented at this point&mdash;it&#8217;s kind of a mess. I might put it under some sort of open source licence, although I&#8217;m not really sure if it&#8217;s worth it for something so simple.</p>
<p>Give it a shot and let me know what you think :)</p>
<p><a href="http://bunnyherolabs.com/follow/"><strong>Twitter follower tracker.</strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2009/09/18/twitter-follower-tracker/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone VR: Viewing 3D panoramas in Safari using JavaScript and -webkit-transform</title>
		<link>http://www.bunnyhero.org/2008/10/13/iphone-vr-viewing-3d-panoramas-in-safari-using-javascript-and-webkit-transform/</link>
		<comments>http://www.bunnyhero.org/2008/10/13/iphone-vr-viewing-3d-panoramas-in-safari-using-javascript-and-webkit-transform/#comments</comments>
		<pubDate>Tue, 14 Oct 2008 03:59:48 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[Browsers]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[ipod touch]]></category>
		<category><![CDATA[safari]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/?p=81</guid>
		<description><![CDATA[Apple&#8217;s 2.0 iPhone update brought some interesting enhancements to Mobile Safari, including 3-D perspective and access to multitouch events. Armed with the documentation (of varying quality) from Apple&#8217;s Web Apps Dev Centre, and invaluable information from blog articles such as Idean&#8217;s &#8220;Spin the Bottle&#8221;, SitePen&#8217;s &#8220;Touching and Gesturing on the iPhone&#8221; and Paul Bakaus&#8217;s &#8220;3D CSS Transforms on the iPhone&#8221;, I put together a simple web app that displays a cubic panorama in Mobile Safari. Look left, right, up and down by dragging your finger across the display. No zoom, currently, though. It was pretty straightforward, but I did learn a few things while creating it. Go ahead, take a look :D Visit http://tinyurl.com/iphonevr on your iPhone or iPod Touch. The images used for the panorama are taken from one of the QuickTime VR movies in Apple&#8217;s Cubic VR gallery. I extracted the images from the movie using the procedure explained here (in French, but it&#8217;s easy to follow). I may write a full tutorial on this eventually, but for now I will just share a few notes (and the source code): It&#8217;s a lot easier to get the 3-d transforms right if the elements you want to transform start [...]]]></description>
			<content:encoded><![CDATA[<p>Apple&#8217;s 2.0 iPhone update brought some interesting enhancements to Mobile Safari, including 3-D perspective and access to multitouch events. Armed with the documentation (of varying quality) from <a href="http://developer.apple.com/webapps/">Apple&#8217;s Web Apps Dev Centre</a>, and invaluable information from blog articles such as <a href="http://www.idean.com/blog/spin-the-bottle/">Idean&#8217;s &#8220;Spin the Bottle&#8221;</a>, <a href="http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/">SitePen&#8217;s &#8220;Touching and Gesturing on the iPhone&#8221;</a> and <a href="http://paulbakaus.com/?p=15&#038;language=en">Paul Bakaus&#8217;s &#8220;3D CSS Transforms on the iPhone&#8221;</a>, I put together a <a href="http://tinyurl.com/iphonevr">simple web app</a> that displays a <a href="http://www.panoguide.com/howto/panoramas/types.jsp">cubic panorama</a> in Mobile Safari. Look left, right, up and down by dragging your finger across the display. No zoom, currently, though. It was pretty straightforward, but I did learn a few things while creating it.</p>
<p>Go ahead, take a look :D Visit <a href="http://tinyurl.com/iphonevr">http://tinyurl.com/iphonevr</a> on your iPhone or iPod Touch.</p>
<p><img src="http://www.bunnyhero.org/wp-content/uploads/2008/10/photo-1-200x300.jpg" alt="" title="iphone vr 1" width="200" height="300" class="alignnone size-medium wp-image-84" /> <img src="http://www.bunnyhero.org/wp-content/uploads/2008/10/photo-200x300.jpg" alt="" title="iphone vr 2" width="200" height="300" class="alignnone size-medium wp-image-86" /></p>
<p>The images used for the panorama are taken from one of the QuickTime VR movies in <a href="http://www.apple.com/quicktime/gallery/cubicvr/">Apple&#8217;s Cubic VR gallery</a>.  I extracted the images from the movie using <a href="http://www.qtbridge.com/LS/Tips/GetImagesFromVR/index.html">the procedure explained here</a> (in French, but it&#8217;s easy to follow).</p>
<p>I may write a full tutorial on this eventually, but for now I will just share a few notes (and the <a href="http://www.bunnyhero.org/static/iphonevr/iphone-vr.zip">source code</a>):</p>
<ul>
<li>It&#8217;s a lot easier to get the 3-d transforms right if the elements you want to transform start out centred in their containing block (so that they start at (0, 0, 0), essentially). I did this with regular CSS, but I suppose this could also be done as part of the transform.
</li>
<li>The above also applies (especially) to any DIV that contains nothing but other DIVs. At first my cube was spinning around its top edge, instead of its centre, because its children (the cube faces) were absolute-positioned, and thus the &#8220;cube&#8221; DIV itself had no height! Giving it an explicit width and height solved this.
</li>
<li>Touch events on 3-D transformed elements seemed to be little bit unreliable. I worked around this by putting a normal transparent DIV on top of the whole thing and listened to events on that instead.
</li>
</ul>
<p><a href="http://www.bunnyhero.org/static/iphonevr/iphone-vr.zip">Download the source code</a> (MIT Licence).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2008/10/13/iphone-vr-viewing-3d-panoramas-in-safari-using-javascript-and-webkit-transform/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>AIR Monster Attack</title>
		<link>http://www.bunnyhero.org/2007/09/26/air-monster-attack/</link>
		<comments>http://www.bunnyhero.org/2007/09/26/air-monster-attack/#comments</comments>
		<pubDate>Thu, 27 Sep 2007 03:42:56 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/2007/09/26/air-monster-attack/</guid>
		<description><![CDATA[Well that was easy! I made a quick AIR version of my monster attack &#8220;application&#8221;. The copy of AIR for JavaScript Developers Pocket Guide that they gave us at the on AIR Tour Bus event was very helpful (along with the demos that they actually presented at the event). All I had to do was create the application descriptor XML file and add a bit of AIR code (in JavaScript) to maximize the window and make it &#8220;always on top&#8221; (or alwaysInFront in the AIR API), and voil&#224;: monster attacking your desktop! It&#8217;s not quite finished though. The biggest problem is that the current beta of the AIR runtime does not display animated GIFs correctly (it just displays the first frame), so the fires do not look right (this is a known bug and should be fixed by the 1.0 release of AIR). I may change the code to do the animations myself. Besides that, I have not created any application icons yet, and has only been tested on Windows, on a single machine :P No idea how well it runs on the Mac. UPDATE: After fixing the mime type for AIR files, it now downloads on Safari on my [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://www.bunnyhero.org/wp-content/uploads/2007/09/lizard.gif' alt='lizard' align="right" />Well that was easy!</p>
<p>I made a quick AIR version of my <a href="http://bunnyherolabs.com/dhtml/monster-info.php">monster attack</a> &#8220;application&#8221;. The copy of <a href="http://www.amazon.com/Integrated-Runtime-JavaScript-Developers-Developer/dp/0596515197"><em>AIR for JavaScript Developers Pocket Guide</em></a> that they gave us at the <a href="http://onair.adobe.com/">on AIR Tour Bus event</a> was very helpful (along with the demos that they actually presented at the event).</p>
<p>All I had to do was create the application descriptor XML file and add a bit of AIR code (in JavaScript) to maximize the window and make it &#8220;always on top&#8221; (or <code>alwaysInFront</code> in the AIR API), and <em>voil&agrave;</em>: monster attacking your desktop!</p>
<p>It&#8217;s not quite finished though. The biggest problem is that the current beta of the AIR runtime does not display animated GIFs correctly (it just displays the first frame), so the fires do not look right (this is a known bug and should be fixed by the 1.0 release of AIR). I may change the code to do the animations myself. Besides that, I have not created any application icons yet, and has only been tested on Windows, on a single machine :P No idea how well it runs on the Mac. <em>UPDATE: After fixing the mime type for AIR files, it now downloads on Safari on my Mac and runs correctly. On top of that, the animated GIFs run properly on Mac OS X!</em></p>
<p>If you run this, be warned that it eats a lot of CPU time, which is not a surprise; after all, it&#8217;s a full-screen transparent window!</p>
<p><a href="/static/monsterattack/monster-screenshot.png"><img src='http://www.bunnyhero.org/wp-content/uploads/2007/09/monster-screenshot.jpg' alt='monster-screenshot.jpg' /><br />
View screenshot</a></p>
<p>I&#8217;m pretty excited about the possibilities of JavaScript/HTML AIR apps that leverage the Flex libraries <em>in JavaScript</em>. Plus I think it might be a great way to learn the new Flex/Flash/AS3 APIs without having to learn MXML at the same time (especially since I don&#8217;t have Flash CS3 yet).</p>
<p>If you have the AIR runtime installed (<a href="http://www.adobe.com/go/air">available here</a>), then give this a try.</p>
<p><a href="/static/monsterattack/v01/monsterattack.air"><strong>Download monster attack!</strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2007/09/26/air-monster-attack/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>SWFFix releases public alpha!</title>
		<link>http://www.bunnyhero.org/2007/07/28/swffix-releases-public-alpha/</link>
		<comments>http://www.bunnyhero.org/2007/07/28/swffix-releases-public-alpha/#comments</comments>
		<pubDate>Sun, 29 Jul 2007 00:30:24 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[Browsers]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/2007/07/28/swffix-releases-public-alpha/</guid>
		<description><![CDATA[I was excited to see SWFFix announce the release of a public alpha. I had begun to fear that the project was moribund. SWFFix is from the developers of SWFObject, UFO and the Flash player detection kit, joining forces to create what one hopes will be the best Flash-embedding method yet. I haven&#8217;t tried it yet, but based on reading the documentation, it seems they&#8217;ve come up with a clever approach, one that&#8217;s different than both SWFObject and UFO (although you can also use it in a SWFObject/UFO-like manner if you want to). Instead of using JavaScript to write the Flash object or embed tags, you instead use regular W3C-compliant markup to add the Flash content to your page. Then the SWFFix JavaScript library steps in and fixes the issues that can arise on different browsers and platforms. For example, it fixes Internet Explorer&#8217;s &#8220;click-to-activate&#8221; mechanism. It can also optionally adds enhancements like ExpressInstall. I think it&#8217;s a great approach. If JavaScript is disabled, for example, the Flash content will still play (unlike what happens with SWFObject and UFO). I will have to try it out soon.]]></description>
			<content:encoded><![CDATA[<p><img src='http://www.bunnyhero.org/wp-content/uploads/2007/07/swffix_logo_small.jpg' alt='SWFFix logo' align="right" />I was excited to see <a href="http://www.swffix.org/devblog/?p=8">SWFFix announce the release of a public alpha</a>. I had begun to fear that the project was moribund. <a href="http://code.google.com/p/swffix/">SWFFix</a> is from the developers of  <a href="http://blog.deconcept.com/swfobject/">SWFObject</a>, <a href="http://www.bobbyvandersluis.com/ufo/">UFO</a> and the <a href="http://www.adobe.com/products/flashplayer/download/detection_kit/">Flash player detection kit</a>, joining forces to create what one hopes will be the best Flash-embedding method yet.</p>
<p>I haven&#8217;t tried it yet, but based on reading the <a href="http://code.google.com/p/swffix/wiki/SWFFix_documentation">documentation</a>, it seems they&#8217;ve come up with a clever approach, one that&#8217;s different than both SWFObject and UFO (although you <em>can</em> also use it in a SWFObject/UFO-like manner if you want to).</p>
<p>Instead of using JavaScript to write the Flash object or embed tags, you instead use regular W3C-compliant markup to add the Flash content to your page. Then the SWFFix JavaScript library steps in and <em>fixes</em> the issues that can arise on different browsers and platforms. For example, it fixes Internet Explorer&#8217;s &#8220;click-to-activate&#8221; mechanism. It can also optionally adds enhancements like ExpressInstall.</p>
<p>I think it&#8217;s a great approach. If JavaScript is disabled, for example, the Flash content will still play (unlike what happens with SWFObject and UFO). I will have to try it out soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2007/07/28/swffix-releases-public-alpha/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Deeper into the rabbit hole: Gmail scripting part 3!</title>
		<link>http://www.bunnyhero.org/2007/07/13/deeper-into-the-rabbit-hole-gmail-scripting-part-3/</link>
		<comments>http://www.bunnyhero.org/2007/07/13/deeper-into-the-rabbit-hole-gmail-scripting-part-3/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 05:01:59 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[Bookmarklets]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/2007/07/13/deeper-into-the-rabbit-hole-gmail-scripting-part-3/</guid>
		<description><![CDATA[I have discovered that the &#8220;reply&#8221; editing area is not always named &#8220;hc_0&#8221; or &#8220;ta_0&#8220;. No, the number following the underscore can be other numbers &#8212; it seems to correspond to the index of message in the conversation. This gets more complex, because I forgot that more than one reply editing area can be open at the same time! And they can be of different types (i.e. rich or plain text)! So now not only do we have to find the editing area(s), we have to determine which one has the current focus. So far, I&#8217;ve not been able to find a way to determine what element has the focus, using JavaScript, on a page I didn&#8217;t create. Hmmm&#8230;! More later&#8230;]]></description>
			<content:encoded><![CDATA[<p>I have discovered that the &#8220;reply&#8221; editing area is not always named &#8220;<code>hc_0</code>&#8221; or &#8220;<code>ta_0</code>&#8220;. No, the number following the underscore can be other numbers &#8212; it seems to correspond to the index of message in the conversation.</p>
<p>This gets more complex, because I forgot that more than one reply editing area can be open at the same time! And they can be of different types (i.e. rich or plain text)! So now not only do we have to find the editing area(s), we have to determine which one has the current focus. So far, I&#8217;ve not been able to find a way to determine what element has the focus, using JavaScript, on a page I didn&#8217;t create. Hmmm&#8230;!</p>
<p>More later&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2007/07/13/deeper-into-the-rabbit-hole-gmail-scripting-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scripting Gmail part 2</title>
		<link>http://www.bunnyhero.org/2007/07/06/scripting-gmail-part-2/</link>
		<comments>http://www.bunnyhero.org/2007/07/06/scripting-gmail-part-2/#comments</comments>
		<pubDate>Fri, 06 Jul 2007 23:25:54 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[Bookmarklets]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/2007/07/06/scripting-gmail-part-2/</guid>
		<description><![CDATA[UPDATE: Haha, alas this does not work all the time. Yep. See my next post&#8230; sigh. After some time poking around with Firebug, here&#8217;s the updated code that also handles the &#8220;reply&#8221; text-editing area! /* gmail seems to cycle between frames 'v1', 'v2' and 'v3'. try all */ var success = false; var editorNames = &#91; 'hc_compose', 'ta_compose', 'hc_0', 'ta_0' &#93;; for &#40;var i=1; i&#60;=3 &#38;&#38; !success; i++&#41; &#123; /* if the frame is offscreen, it's not the active composing window */ /* do this with a DOM element */ var fe = top.main.document.getElementById&#40;'v'+i&#41;; if &#40;fe &#38;&#38; fe.offsetLeft &#62;= 0&#41; &#123; /* the element name of the edit box could be one of 4 values, depending on rich text/plain text, as well as whether replying or composing. try them all. */ var d = top.main.frames&#91;&#34;v&#34;+i&#93;.document; /* note we have to use oldschool frames[] syntax */ var ed = null; for &#40;var j=0; j&#60;editorNames.length; j++&#41; &#123; ed = d.getElementById&#40;editorNames&#91;j&#93;&#41;; if &#40;ed != null&#41; &#123; break; &#125; &#125; &#160; if &#40;ed != null&#41; &#123; /* found it! rich text? or plain? */ switch &#40;ed.nodeName&#41; &#123; case &#34;TEXTAREA&#34;: &#123; /* plain text */ /* do something with 'ed' */ success = true; break; [...]]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE</strong>: Haha, alas this does not work all the time. Yep. See my next post&#8230; sigh.</p>
<p>After some time poking around with Firebug, here&#8217;s the updated code that also handles the &#8220;reply&#8221; text-editing area!</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* gmail seems to cycle between frames 'v1', 'v2' and 'v3'. try all */</span>
<span style="color: #003366; font-weight: bold;">var</span> success <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> editorNames <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span> <span style="color: #3366CC;">'hc_compose'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'ta_compose'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'hc_0'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'ta_0'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">;</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><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;=</span><span style="color: #CC0000;">3</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>success<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #009966; font-style: italic;">/* if the frame is offscreen, it's not the active composing window */</span>
    <span style="color: #009966; font-style: italic;">/* do this with a DOM element */</span>
    <span style="color: #003366; font-weight: bold;">var</span> fe <span style="color: #339933;">=</span> top.<span style="color: #660066;">main</span>.<span style="color: #660066;">document</span>.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'v'</span><span style="color: #339933;">+</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>fe <span style="color: #339933;">&amp;&amp;</span> fe.<span style="color: #660066;">offsetLeft</span> <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">/* the element name of the edit box could be one of 4 values, depending
           on rich text/plain text, as well as whether replying or composing.
           try them all. */</span>
        <span style="color: #003366; font-weight: bold;">var</span> d <span style="color: #339933;">=</span> top.<span style="color: #660066;">main</span>.<span style="color: #660066;">frames</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;v&quot;</span><span style="color: #339933;">+</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">document</span><span style="color: #339933;">;</span> <span style="color: #009966; font-style: italic;">/* note we have to use oldschool frames[] syntax */</span>
        <span style="color: #003366; font-weight: bold;">var</span> ed <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</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> j<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> j<span style="color: #339933;">&lt;</span>editorNames.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> j<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            ed <span style="color: #339933;">=</span> d.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span>editorNames<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ed <span style="color: #339933;">!=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ed <span style="color: #339933;">!=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #009966; font-style: italic;">/* found it! rich text? or plain? */</span>
            <span style="color: #000066; font-weight: bold;">switch</span> <span style="color: #009900;">&#40;</span>ed.<span style="color: #660066;">nodeName</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">&quot;TEXTAREA&quot;</span><span style="color: #339933;">:</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #009966; font-style: italic;">/* plain text */</span>
                    <span style="color: #009966; font-style: italic;">/* do something with 'ed' */</span>
                    success <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
                    <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">&quot;IFRAME&quot;</span><span style="color: #339933;">:</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #009966; font-style: italic;">/* rich text */</span>
                    <span style="color: #009966; font-style: italic;">/* do something with 'ed' */</span>
                    ed.<span style="color: #660066;">contentDocument</span>.<span style="color: #660066;">execCommand</span><span style="color: #009900;">&#40;</span> <span style="color: #009966; font-style: italic;">/* something something */</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    success <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
                    <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Phew!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2007/07/06/scripting-gmail-part-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Scripting Gmail with Bookmarklets</title>
		<link>http://www.bunnyhero.org/2007/07/02/scripting-gmail-with-bookmarklets/</link>
		<comments>http://www.bunnyhero.org/2007/07/02/scripting-gmail-with-bookmarklets/#comments</comments>
		<pubDate>Mon, 02 Jul 2007 19:45:32 +0000</pubDate>
		<dc:creator>bunnyhero</dc:creator>
				<category><![CDATA[Bookmarklets]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.bunnyhero.org/2007/07/02/scripting-gmail-with-bookmarklets/</guid>
		<description><![CDATA[I am working on some bookmarklets for Gmail. I discovered that targetting any specific element in the Gmail window is a bit tricky, due to Google&#8217;s interesting use of frames. It turns out that Gmail swaps between using frames named &#8220;v1&#8243; and &#8220;v2&#8243; to display the main content (at least in Firefox). If I had to guess, I&#8217;d mumble something about history and the back button and maybe cacheing :P Anyway: here is how I find the text-editing area (it&#8217;ll be either a textarea or an iframe, depending on whether the user is using rich formatting or not): /* gmail seems to swap between frames 'v1' and 'v2'. try both */ var success = false; for &#40;var i=1; i&#60;=2 &#38;&#38; !success; i++&#41; &#123; var ta = top.main.frames&#91;&#34;v&#34;+i&#93;.document.getElementById&#40;&#34;hc_compose&#34;&#41;; if &#40;ta&#41; &#123; /* do something with ta, for example: */ ta.contentDocument.execCommand&#40;/* something something */&#41;; success = true; &#125; else &#123; // try getting the plain text area ta = top.main.frames&#91;&#34;v&#34;+i&#93;.document.getElementById&#40;&#34;ta_compose&#34;&#41;; if &#40;ta&#41; &#123; /* do something with ta here, a textarea element */ success = true; &#125; &#125; &#125; I&#8217;m certain this could be done more cleanly, but you get the idea. Share and enjoy! UPDATE: This currently doesn&#8217;t work for a [...]]]></description>
			<content:encoded><![CDATA[<p>I am working on some <a href="http://en.wikipedia.org/wiki/Bookmarklet">bookmarklets</a> for Gmail. I discovered that targetting any specific element in the Gmail window is a bit tricky, due to Google&#8217;s interesting use of frames.</p>
<p>It turns out that Gmail swaps between using frames named &#8220;v1&#8243; and &#8220;v2&#8243; to display the main content (at least in Firefox). If I had to guess, I&#8217;d mumble something about history and the back button and maybe cacheing :P</p>
<p>Anyway: here is how I find the text-editing area (it&#8217;ll be either a textarea or an iframe, depending on whether the user is using rich formatting or not):</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* gmail seems to swap between frames 'v1' and 'v2'. try both */</span>
<span style="color: #003366; font-weight: bold;">var</span> success <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</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><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;=</span><span style="color: #CC0000;">2</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>success<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> ta <span style="color: #339933;">=</span> top.<span style="color: #660066;">main</span>.<span style="color: #660066;">frames</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;v&quot;</span><span style="color: #339933;">+</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">document</span>.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;hc_compose&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ta<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #009966; font-style: italic;">/* do something with ta, for example: */</span>
        ta.<span style="color: #660066;">contentDocument</span>.<span style="color: #660066;">execCommand</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/* something something */</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        success <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</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;">//  try getting the plain text area</span>
        ta <span style="color: #339933;">=</span> top.<span style="color: #660066;">main</span>.<span style="color: #660066;">frames</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;v&quot;</span><span style="color: #339933;">+</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">document</span>.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;ta_compose&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ta<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #009966; font-style: italic;">/* do something with ta here, a textarea element */</span>
            success <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I&#8217;m certain this could be done more cleanly, but you get the idea. Share and enjoy!</p>
<p><strong>UPDATE</strong>: This currently doesn&#8217;t work for a &#8220;reply&#8221; editing area. I will (I hope) update the snippet to cover that case, too.</p>
<p><strong>UPDATE 2</strong>: Sorry, this doesn&#8217;t work consistently. I should test more before posting :P I am now finding a frame called &#8220;v3&#8243;. Perhaps Gmail increments this continuously? In any case, I am leaving this post up for research purposes.</p>
<p><strong>UPDATE 3</strong>: Got it working reliably (I think). See the <a href="http://www.bunnyhero.org/2007/07/06/scripting-gmail-part-2/">fixed version</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bunnyhero.org/2007/07/02/scripting-gmail-with-bookmarklets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
