<?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>Unknown Kadath</title>
	<atom:link href="http://html5.litten.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://html5.litten.com</link>
	<description></description>
	<lastBuildDate>Tue, 21 Jun 2011 00:38:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Monitoring the impact of Google/Webkit Prerendering of Pages with Piwik Analytics</title>
		<link>http://html5.litten.com/monitoring-the-impact-of-googlewebkit-prerendering-of-pages-with-piwik-analytics/</link>
		<comments>http://html5.litten.com/monitoring-the-impact-of-googlewebkit-prerendering-of-pages-with-piwik-analytics/#comments</comments>
		<pubDate>Tue, 21 Jun 2011 00:38:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[HTML5]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=728</guid>
		<description><![CDATA[Google has announced that their search engine will begin prerendering pages. http://googlewebmastercentral.blogspot.com/2011/06/announcing-instant-pages.html The potential problem with Google&#8217;s prerendering&#8230; It&#8217;s done with Javascript. That means that it happens on the client and not on Google&#8217;s server. There is no way to tell if my page was actually viewed by the user or if the page was [...]]]></description>
			<content:encoded><![CDATA[Google has announced that their search engine will begin prerendering pages. <a href="http://googlewebmastercentral.blogspot.com/2011/06/announcing-instant-pages.html">http://googlewebmastercentral.blogspot.com/2011/06/announcing-instant-pages.html</a><br />
<br />
<strong><em>The potential problem with Google&#8217;s prerendering&#8230;</em></strong><br />

It&#8217;s done with Javascript.<br />
<br />
That means that it happens on the client and not on Google&#8217;s server. There is no way to tell if my page was actually viewed by the user or if the page was prefetched and cached by the user&#8217;s browser because the search page they were viewing told it to prerender the page. Well, no way to tell by just looking at my normal stats. There is a way to detect whether or not the user actually views the page using some javascript.<br />
<br />
I use Piwik on many websites in parallel with Google Analytics. Piwik gives me the ability to monitor performance and trends in real time.<br />
<br />
I use Google Analytics for monitoring trends over greater periods of time like weeks, months or years.<br />
<br />
Google Analytics will likely give me the ability to filter out and monitor prerendered pages in the near future. Piwik will probably add an option for this eventually also but right now, I want to begin monitoring it to see how often it happens and how important it is to my infrastructure.<br />
<br />
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
"><br />
1. How much bandwidth is used by pages that are prerendered but never viewed?<br /><br />

2. What pages does Google rank highly enough that they feel the need to prerender them and what keywords are they resulting from?<br /><br />

3. Who else is causing my pages to prerender besides Google.com?<br /><br />
</div>
<br />
Using some javascript we can check on the webkitVisibilityState of the page as it is viewed or cached by the client based on the W3C Page Visibility spec <a href="http://www.w3.org/TR/2011/WD-page-visibility-20110602/">http://www.w3.org/TR/2011/WD-page-visibility-20110602/</a><br /><br />

Google Chrome Labs has a page on this <a href="http://code.google.com/chrome/whitepapers/pagevisibility.html">http://code.google.com/chrome/whitepapers/pagevisibility.html</a><br /><br />

We&#8217;ll use their technique to log our Piwik stats differently if the page is prerendered and then properly log the visit if the prerendered page is subsequently viewed.<br /><br />

A simple Piwik tracking image will be sufficient for our tests. We can add full javascript based tracking once we know that it works. If it is prerendered then we will track it to a different website account on Piwik using the querystring variable <code>idsite</code> and then monitor it with an event listener so that if it is subsequently viewed then it will track it as normal.<br /><br />

<pre><code>var isPrerendering = false;

function handleVisibilityChange(evt) {
if (!isPrerendering) return;
countView();
isPrerendering = false;
}

function countView(){
document.write('&lt;img src="http://PIWIK WEBHOST/piwik/
   piwik.php?idsite=[ID OF NORMAL SITE]&amp;rec=1" /&gt;');
}

/*
* We can count the view right now if the document isn't being prerendered.
* Browsers that don't support the API will return undefined for
* webkitVisibilityState.
*/
if (document.webkitVisibilityState != "prerender") {
countView();
} else {
//We'll need to count the pageview later
isPrerendering = true;
document.write('&lt;img src="http://PIWIK WEBHOST/piwik/
   piwik.php?idsite=[ID OF PRERENDER TRACKING SITE]&amp;rec=1" /&gt;');
document.addEventListener("webkitvisibilitychange", 
   handleVisibilityChange, false);
}</code></pre>
<br /><br />
Trying it out<br />

Using Chrome 13 <a href="http://tools.google.com/dlpage/chromesxs">http://tools.google.com/dlpage/chromesxs</a> enable prerendering by starting Chrome like this&#8230;<br />

<code>chrome.exe –prerender=enabled</code><br /><br />

To test this I go to <a href="http://prerender-test.appspot.com/">http://prerender-test.appspot.com/</a> and enter the address of a page that I am tracking like this one and it will show a prerendered hit in the Piwik website I set up for tracking them.<br /><br />

I like it.<br />
It&#8217;s fast and enhances the users experience. Using javascript puts all of the cost (processing and bandwidth) on my webserver and user&#8217;s browser so we&#8217;ll see if this causes problems for its adoption. I&#8217;ll keep playing with it and when it does become mainstream, I hope to be ready to embrace it and not allow it to adversely affect my servers, visitors or analytics.<br /><br />]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/monitoring-the-impact-of-googlewebkit-prerendering-of-pages-with-piwik-analytics/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>X10 Lamp Control Over The Internet With Live Streaming Video Example</title>
		<link>http://html5.litten.com/x10-lamp-control-over-the-internet-with-live-streaming-video-example/</link>
		<comments>http://html5.litten.com/x10-lamp-control-over-the-internet-with-live-streaming-video-example/#comments</comments>
		<pubDate>Fri, 13 May 2011 19:28:14 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[Home Automation]]></category>
		<category><![CDATA[X10]]></category>
		<category><![CDATA[home automation]]></category>
		<category><![CDATA[internet controlled]]></category>
		<category><![CDATA[x10]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=688</guid>
		<description><![CDATA[In this project, we are trying to find the simplest way to allow public access to X10 home automation devices while maintaining a secure environment that does not allow anything damaging to happen. The video and button below are live and in my home. This post will describe how this is done. &#160; Currently using [...]]]></description>
			<content:encoded><![CDATA[In this project, we are trying to find the simplest way to allow public access to X10 home automation devices while maintaining a secure environment that does not allow anything damaging to happen. The video and button below are live and in my home. This post will describe how this is done.
<span id="more-688"></span>
&nbsp;
<br /><br /><em>Currently using webcam snapshots instead of stream (delay of up to 5 seconds but much less bandwidth and no ads).</em><br />
<div><iframe id="frame1" src="http://litten.com/switch.php"  height="310" width="420" frameborder="0" scrolling="no"></iframe></div><div><em>Click this button to turn the lamp on/off</em></div>
<h2>Summary of Operation</h2>
This blog post is being served to your browser from a server on the internet provided by GoDaddy hosting. On this server I have created a database using MySQL which has a row in it representing the lamp in the streaming video you see above. In that row is a field representing the state of the lamp (on / off). The button that controls the state of the lamp, simply toggles that field in the database.

In my house there is an XAMPP server running on a Windows 7 PC which has a page open on it that does two things &#8230;
<ol>
	<li>It checks the field on the MySQL server at litten.com that represents the state of the lamp once per second.</li>
	<li>It sends an X10 command through the X10 PC interface to the lamp, setting it to that state.</li>
</ol>
This keeps all of the command and control of the lamp inside my secure home network. All that exists in the wild are three state values of the lamp. On, off or something else (things break or have unexpected results in the wild).

figure I shows the whole setup.
<br /><br />
<div class="wp-caption aligncenter" style="width: 460px"><img class=" " style="border: 0pt none;" title="x10 project diagram" src="http://litten.com/images/x10.jpg" alt="" width="450" height="330" /><p class="wp-caption-text">fig. I</p></div>

&nbsp;
<h2>MySQL Database</h2>
On my hosted server, I have the ability to make MySQL databases. Almost all hosting services have this these days.
<h3>Create new mySQL db</h3>
Most hosts have an option for creating new MySQL databases in their control panel. I used to make these from the command line but nowadays I just use the control panel for generic databases like this one. I created a new database called x10.

&nbsp;
<h3>Add a table</h3>
I rarely use the command line to make tables anymore. I find using the phpmyadmin interface sufficient for most of my needs. You should be able to access phpmyadmin from the control panel at your hosting account. Here are the settings for the table that I created for this project. The table is named <em>x10state</em>. There is a field named <em>device</em> that is a varchar(20) with a default value of the word <em>default</em> and another field named <em>state</em> that is a tinyint(1) with a default value of <em>0.</em>

<em>
</em>
<br /><br />
CREATE TABLE IF NOT EXISTS `x10state` (<br />
`device` varchar(20) NOT NULL default &#8216;default&#8217;,<br />
`state` tinyint(1) NOT NULL default &#8217;0&#8242;<br />
) ENGINE=MyISAM DEFAULT CHARSET=latin1;<br />
<br />
&nbsp;
<h3>Add new restricted users</h3>
We create a user that can only access the database from this server (replace  <span style="color: #008000;"><em>mypassword</em></span> with your own password)

&nbsp;
<br /><br />
CREATE USER &#8216;x10user&#8217;@'localhost&#8217; IDENTIFIED BY &#8216;<span style="color: #008000;"><em>mypassword</em></span>&#8216;;<br />
GRANT SELECT,INSERT,UPDATE,DELETE<br />
ON x10.*<br />
TO &#8216;x10user&#8217;@'localhost&#8217;;<br />
<br />
&nbsp;

We create another user (with the same username as above) that can only access the database from this server (replace  <span style="color: #008000;"><em>mypassword</em> </span>with your own password and replace <span style="color: #008000;"><em>MY FIOS ADDRESS</em></span> with the address that your home server has. You can find it by going to <a href="http://www.displaymyhostname.com/" target="_blank">http://www.displaymyhostname.com/</a> while on the PC that your home webserver will be on.
<br /><br />

CREATE USER &#8216;x10user&#8217;@&#8217;<span style="color: #008000;"><em>MY FIOS ADDRESS</em></span>&#8216; IDENTIFIED BY &#8216;<span style="color: #008000;"><em>mypassword</em></span>&#8216;;<br />
GRANT SELECT,INSERT,UPDATE,DELETE<br />
ON x10.*<br />
TO &#8216;x10user&#8217;@&#8217;<span style="color: #008000;"><em>MY FIOS ADDRESS</em></span>&#8216;;<br />
<br />
&nbsp;
<h2>ON/ OFF Button</h2>
The On / Off button is placed into this post using an IFRAME and consists of two PHP pages with access to the MySQL database and a form to submit the action of clicking it so that it can change the <em>state </em>value of the lamp in the database.
<br />
The IFRAME element looks like this&#8230;
<pre><code>
&lt;iframe id="frame1" src="http://litten.com/switch.php"  height="50"
width="100" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;
</code></pre>


switch.php gets the state of the lamp from the database and applies it as the label for the submit button. The action for the submit button is changestate.php.

<br />
<br />
The code for switch.php
<pre><code>
&lt;?php
$db_host = 'localhost';
$db_user = 'x10user';
$db_pwd = '<span style="color: #008000;"><em>mypassword</em></span>';
$database = 'x10';
$table = 'x10state';

if (!mysql_connect($db_host, $db_user, $db_pwd))
die("Can't connect to database");

if (!mysql_select_db($database))
die("Can't select database");

$result = mysql_query("SELECT * FROM {$table}
 WHERE device = 'lamp'");
if (!$result) {
die("failed");
}

$row = mysql_fetch_row($result);
$state = $row[1];

$lampstate = "OFF";
if ($state == 1) {
$lampstate = "ON";
}
?&gt;

&lt;form method=POST action="http://litten.com/changestate.php"&gt;
&lt;input type="submit" name="switch"
 value= "&lt;?php echo $lampstate ?&gt;"&gt;
&lt;/form&gt;
 </code></pre>
The form in switch.php has the action changestate.php which simply changes the value of the state of the lamp. If it is off, then clicking the button sets it to 1 (on) and if it is on then clicking the button sets it to 0 (off).

<br />
<br />
The code for changestate.php
<pre><code>
&lt;?php
$db_host = 'localhost';
$db_user = 'x10user';
$db_pwd = '<em><span style="color: #008000;">mypassword</span></em>';
$database = 'x10';
$table = 'x10state';

if (!mysql_connect($db_host, $db_user, $db_pwd))
die("Can't connect to database");

if (!mysql_select_db($database))
die("Can't select database");

$result1 = mysql_query("SELECT * FROM {$table}
 WHERE device = 'lamp'");
if (!$result1) {
die("failed");
}

$row = mysql_fetch_row($result1);
$state = $row[1];

$onoff = 1;
if ($state == 1) {
$onoff = 0;
}

$result2 = mysql_query("UPDATE {$table}
 SET state = {$onoff} WHERE device = 'lamp'");
if (!$result2) {
die("failed2");
}

$lampstate = "ON";
if ($state == 1) {
$lampstate = "OFF";
}
?&gt;

&lt;form method=POST action="http://litten.com/changestate.php"&gt;
&lt;input type="submit" name="switch"
 value= "&lt;?php echo $lampstate ?&gt;"&gt;
&lt;/form&gt;
 </code></pre>
<h2>Video Streaming</h2>
<strong>UPDATE:</strong> I am currently testing a solution that uses my webcams ability to detect when the light turns on or off. When a change is detected, it takes a snapshot and uploads it using Dorgem (<a href="http://dorgem.sourceforge.net/" target="_blank">dorgem.sourceforge.net</a>). That snapshot is shown in an IFRAME above the button. It&#8217;s not as pretty as a live stream but it is far more economical and has no ads.<br /><br />
The video stream is <del datetime="2011-05-14T14:28:30+00:00">currently</del> accomplished using a free account at Ustream (<a href="http://www.ustream.tv/" target="_blank">www.ustream.tv</a>) which is supported by ads. It is easy to setup and works very well. Another option would be to use something like Dorgem (<a href="http://dorgem.sourceforge.net/" target="_blank">dorgem.sourceforge.net</a>). I am using an inexpensive webcam with the generic Windows USB Webcam Drivers.
<h2>Web Server on Home PC</h2>
Now we need to set up a webserver on our home network that is capable of displaying a PHP web page that will periodically check the MySQL database at litten.com to get the value of the lamp&#8217;s state and then send that value to our X10 module controlling the lamp. The easiest way to set up a server that can serve PHP pages on a Windows 7 PC like I am using for this is to use XAMPP (<a href="http://www.apachefriends.org/en/xampp-windows.html" target="_blank">XAMPP </a>) (<a href="http://en.wikipedia.org/wiki/XAMPP" target="_blank">Wikipedia entry for XAMPP</a>)
<h2>X10 PC Interface via a PHP page</h2>
Now that we have a webserver on our home network. We need a few things to make this work.
<ul>
	<li>A lamp. I am using a nice Himalayan Salt lamp from Amazon.com.</li>
	<li>An <a href="http://affiliates.x10.com/?property=affiliates&amp;aposition=text29&amp;lineid=xtenafftxt27&amp;affid=x10_13050400551&amp;type=href" target="_blank">X10 3-pin Appliance Module (AM466)</a>. To plug the lamp into. Then it is plugged into an outlet.</li>
	<li>An <a href="http://affiliates.x10.com/?property=affiliates&amp;aposition=text29&amp;lineid=xtenafftxt27&amp;affid=x10_13050400551&amp;type=href" target="_blank">ActiveHome Professional Computer Interface (CM15A)</a>. That is plugged into an outlet and attached to your PC via USB cable.</li>
	<li>The <a href="http://www.activehomepro.com/sdk/index.html" target="_blank">ActiveHome Scripting SDK </a></li>
	<li>A copy of <a href="http://www.dll-files.com/dllindex/dll-files.shtml?msvcp71" target="_blank">msvcp71.dll</a> and <a href="http://www.dll-files.com/dllindex/dll-files.shtml?msvcr71" target="_blank">msvcr71.dll</a> (be careful, this site tries to trick you to click on ads)</li>
</ul>
On our XAMPP webserver, inside the htdocs directory, create a new folder called X10. Inside of that folder create a file called refresher.php. You will be able to access this file in your browser on that server/PC by going to

http://localhost/x10/refresher.php

Inside the X10 folder you also need to put a copy of ahcmd.exe which can be found in AHSDK\samples\php after installing The <a href="http://www.activehomepro.com/sdk/index.html" target="_blank">ActiveHome Scripting SDK</a>.

Inside the X10 folder you also need to put copies of <a href="http://www.dll-files.com/dllindex/dll-files.shtml?msvcp71" target="_blank">msvcp71.dll</a> and <a href="http://www.dll-files.com/dllindex/dll-files.shtml?msvcr71" target="_blank">msvcr71.dll</a> which are needed to support ahcmd.exe

This file will check the MySQL database on the public webserver (in my case at litten.com) and retrieve the state value for the lamp. Then it will use an exec command in PHP to send the state to the actual lamp. Here is the code for refresher.php

&nbsp;
<pre><code>
&lt;META HTTP-EQUIV=Refresh CONTENT='1; URL=refresher.php'&gt;
&lt;?php
$db_host = '<span style="color: #008000;"><em>litten.com</em></span>';
$db_user = 'x10user';
$db_pwd = '<span style="color: #008000;"><em>mypassword</em></span>';
$database = 'x10';
$table = 'x10state';

if (!mysql_connect($db_host, $db_user, $db_pwd))
die("Can't connect to database");

if (!mysql_select_db($database))
die("Can't select database");

$result = mysql_query("SELECT * FROM {$table} WHERE device = 'lamp'");
if (!$result) {
die("failed");
}
$row = mysql_fetch_row($result);
$state = $row[1];
echo $state;

$cmd = 'on';
if ($state == 0){
$cmd = 'off';
}

$cmdstring = "<span style="color: #008000;">A1</span> ".$cmd;
echo $cmdstring;
exec("ahcmd.exe sendplc $cmdstring");
?&gt;
</code></pre>
This page must be open in a browser on your server/PC in order for the lamp to work. To keep this as simple as possible I am using a META tag to refresh the page once per second. There are other options for this. 
<br />
The command string in this case uses A1 which is the house code/unit code of the X10 module that I have the lamp plugged into. Yours may be different. It is sent in this line.
<pre><code>
exec("ahcmd.exe sendplc $cmdstring");
</code></pre>
When $cmdstring is <em>A1on</em> it sends the X10 command to turn the device with house code A and unit code 1 (which is my lamp in this example) on.
&nbsp;
<br /><br />
Please leave comments if you have questions or use my contact page if you&#8217;d prefer to ask me privately.
<br /><br />]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/x10-lamp-control-over-the-internet-with-live-streaming-video-example/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Learning to Use Android NDK With a Neat Augmented Reality Example</title>
		<link>http://html5.litten.com/learning-to-use-android-ndk-with-a-neat-augmented-reality-example/</link>
		<comments>http://html5.litten.com/learning-to-use-android-ndk-with-a-neat-augmented-reality-example/#comments</comments>
		<pubDate>Mon, 07 Mar 2011 19:04:07 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[android]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Native Code]]></category>
		<category><![CDATA[NDK]]></category>
		<category><![CDATA[Augmented Reality]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=672</guid>
		<description><![CDATA[I&#8217;ve been moving some Flash SWF files over to AIR for Android and while looking into how best to optimize ActionScript code for AIR for Android, I got sidetracked. After reading about the obvious optimizations for memory and CPU resources, I decided to take a look at the AIR .apk file that is installed on [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been moving some Flash SWF files over to AIR for Android and while looking into how best to optimize ActionScript code for AIR for Android, I got sidetracked. After reading about the obvious optimizations for memory and CPU resources, I decided to take a look at the AIR .apk file that is installed on my Android phone. I found that the magic was happening in</p>
<p>\lib\armeabi\libCore.so</p>
<p>Ahh, the Adobe AIR runtime kind of runs beside the Dalvik virtual machine rather than completely inside of it.</p>
<p>The libCore.so file is a shared object file using JNI. Java Native Interface(JNI) <a href="http://en.wikipedia.org/wiki/JNI">http://en.wikipedia.org/wiki/JNI</a> code written in C or C++ allows you to access platform specific features and &#8216;touch the metal&#8217; with your code.</p>
<p>Android provides the Android NDK so you can use native code.<br />
<a href="http://developer.android.com/sdk/ndk/index.html">http://developer.android.com/sdk/ndk/index.html</a></p>
<p>Some words of wisdom from the Android developer page <img src='http://html5.litten.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre>The NDK will not benefit most applications. As a developer, you need 
to balance its benefits against its drawbacks; notably, using native 
code does not result in an automatic performance increase, but 
always increases application complexity. In general, you should 
only use native code if it is essential to your application, not just 
because you prefer to program in C/C++.<br /></pre>
<a href="http://developer.android.com/sdk/ndk/overview.html">http://developer.android.com/sdk/ndk/overview.html</a>
<p>I wanted to try compiling and running some native code on my phone (Android 2.2) so that I have that tool in my toolbox when I need it. I found a great example at Qualcomm.<br />
<a href="https://ar.qualcomm.com/qdevnet/sdk">https://ar.qualcomm.com/qdevnet/sdk</a></p>
<p>The sample application that comes with the SDK allows you to detect and track image targets in 3D using your phone&#8217;s camera and then it puts a floating teapot (<a href="http://www.sjbaker.org/wiki/index.php?title=The_History_of_The_Teapot">http://www.sjbaker.org/wiki/index.php?title=The_History_of_The_Teapot</a>) over your target. The NDK is required to compile the native C++ code which uses OpenGL ES <a href="http://en.wikipedia.org/wiki/OpenGL_ES">http://en.wikipedia.org/wiki/OpenGL_ES</a>. It has step by step instructions that will show you how to build the native C++ source files with the NDK package of the Android SDK and then use Eclipse to build the Java sources and create the APK package that can be deployed to the phone.</p>
<p>This is very much like the augmented reality on the new Nintendo 3DS<br />
<a href="http://www.siliconera.com/2011/03/04/lose-your-nintendo-3ds-ar-cards-just-print-out-new-ones/">http://www.siliconera.com/2011/03/04/lose-your-nintendo-3ds-ar-cards-just-print-out-new-ones/</a></p>
<p>If you are having a hard time with the NDK, try the sample that comes with it in \samples\hello-jni along with the tutorial at <a href="http://www.pocketmagic.net/?p=1332">http://www.pocketmagic.net/?p=1332</a> for a very basic example that will help you understand the proper procedure.</p>
<p>I have some broken antique clocks around the house so I made image targets out of their faces and now have a teapot floating in front of them. Next time I get a little break in the action, I&#8217;ll change that teapot to a semi-transparent digital clock so my clocks will no longer be broken provided, I run the program on my phone and point the camera at the clocks <img src='http://html5.litten.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><img src="http://litten.com/images/clock.jpg" alt="Clock Face" /></p>
<p>The NDK combined with current hardware capabilities certainly seem to be enough to make sophisticated and engaging toolkits and engines for game developers and artists. </p>
<p>Anyway, enjoy playing with the code as that is how you learn.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/learning-to-use-android-ndk-with-a-neat-augmented-reality-example/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Developing With Flash CS5 for Adobe AIR on Android</title>
		<link>http://html5.litten.com/developing-with-flash-cs5-for-adobe-air-on-android/</link>
		<comments>http://html5.litten.com/developing-with-flash-cs5-for-adobe-air-on-android/#comments</comments>
		<pubDate>Tue, 22 Feb 2011 20:47:57 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[android]]></category>
		<category><![CDATA[AIR]]></category>
		<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=656</guid>
		<description><![CDATA[Now that Adobe AIR is available for Android 2.2, it is easy to move your Flash games to Android's app store and also to add functionality that takes advantage of things like the camera and GPS.]]></description>
			<content:encoded><![CDATA[<p>Now that Adobe AIR is available for Android 2.2, it is easy to move your Flash games to Android&#8217;s app store and also to add functionality that takes advantage of things like the camera and GPS.</p>

<p>AIR stands for Adobe Integrated Runtime and was originally for</p> 

<pre>
...building rich Internet applications using Adobe Flash, Adobe Flex,
Adobe Dreamweaver (HTML or Ajax), AIR SDK, that can be run as 
desktop applications.
</pre>

<p>But now seems to be headed toward becoming an easy way to quickly develop powerful applications for smartphones, TV&#8217;s, car dashboards, tablets, big computers, tiny computers and everything in between.<br />
<a href="http://www.adobe.com/products/air/">http://www.adobe.com/products/air/</a> </p>
<br />
<h2>Setting up your development environment</h2>

<p>1. Get Flash CS5 (you can get a 30 day free trial at <a href="http://www.adobe.com/downloads">http://www.adobe.com/downloads</a>)</p>
<br />
<p>2. Install Flash extension for AIR  <a href="http://labs.adobe.com/technologies/flashpro_extensionforair/">http://labs.adobe.com/technologies/flashpro_extensionforair/</a></p>
<br />
<p>3. Install AIR SDK  <a href="http://www.adobe.com/products/air/">http://www.adobe.com/products/air/</a></p>
<br />
<p>4. Install Android SDK  <a href="http://developer.android.com/sdk/index.html">http://developer.android.com/sdk/index.html</a></p>
<br />
<h2>Step by step video instructions</h2>
<p>Setting up your development environment with Flash CS5 and AIR for Android<br />
<a href="http://www.gotoandlearn.com/play.php?id=123">http://www.gotoandlearn.com/play.php?id=123</a></p>
<br />
<h2>More instructions for setting up.</h2>
<p>Getting started with Adobe AIR for Android<br />
<a href="http://www.adobe.com/newsletters/edge/august2010/articles/article1/index.html">http://www.adobe.com/newsletters/edge/august2010/articles/article1/index.html</a></p>
<br />
<h2>Some AIR for Android examples</h2>
<p>Build a GPS Speedometer<br />
<a href="http://mobile.tutsplus.com/tutorials/android/build-a-gps-speedometer-getting-into-air-for-android/">http://mobile.tutsplus.com/tutorials/android/build-a-gps-speedometer-getting-into-air-for-android/</a></p>
<br />
<p>AIR for Android MazeFM Application<br />
<a href="http://www.flashandmath.com/mobile/mazefm/index.html">http://www.flashandmath.com/mobile/mazefm/index.html</a></p> 
<br />
<p>Air for Android: Geolocation<br />
<a href="http://www.unitedmindset.com/jonbcampos/2010/08/30/air-for-android-geolocation/">http://www.unitedmindset.com/jonbcampos/2010/08/30/air-for-android-geolocation/</a></p>
<br />
<p>Simple camera application with Flash CS5 and AIR for Android<br />
<a href="http://www.gotoandlearn.com/play.php?id=124">http://www.gotoandlearn.com/play.php?id=124</a></p>
<br />
<p>Publishing AIR for Android Applications to the App Store<br />
<a href="http://www.gotoandlearn.com/play.php?id=131">http://www.gotoandlearn.com/play.php?id=131</a></p>
<br />
<p>The .apk file that is created for AIR for Android has the .swf file in the assets folder and an application.xml file in the assets/META-INF/AIR folder which works with the main AndroidManifest.xml file to set the programs application properties and how it should start (run the swf file).</p> 
<br />
<p>Now it&#8217;s easy to move your  Flash apps and games to the mobile market. Enjoy.</p>]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/developing-with-flash-cs5-for-adobe-air-on-android/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>CSS3 Series: Multiple Columns</title>
		<link>http://html5.litten.com/css3-series-multiple-columns/</link>
		<comments>http://html5.litten.com/css3-series-multiple-columns/#comments</comments>
		<pubDate>Sat, 21 Aug 2010 16:32:37 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[CSS 3.0]]></category>
		<category><![CDATA[css columns]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=642</guid>
		<description><![CDATA[Even though this wonderful feature has been around for five years, it has yet to be implemented consistently across the major browsers. Hopefully, this will change soon. If you know a reason why this is so, please leave a comment. Thanks. The specification for CSS Multi-column Layout has 10 properties for CSS Multiple Columns. They [...]]]></description>
			<content:encoded><![CDATA[<p>Even though this wonderful feature has been around for five years, it has yet to be implemented consistently across the major browsers. Hopefully, this will change soon.<br />
If you know a reason why this is so, please leave a comment. Thanks.</p>
<p>The<a href="http://www.w3.org/TR/css3-multicol/"> specification for CSS Multi-column Layout</a> has 10 properties for CSS Multiple Columns.<br />
They are pretty self explanatory except for maybe &#8216;rule&#8217; which in this context means a vertical divider between the columns that behaves like a CSS border.<br />
<br />
column-width<br />
column-count<br />
columns (This is shorthand that can set either or both &#8216;width&#8217; and &#8216;count&#8217;)<br />
column-gap<br />
column-rule<br />
column-rule-width<br />
column-rule-style<br />
column-rule-color<br />
column-fill (Balances columns height)<br />
<br />
column-span (Allows for titles or headings to span across multiple or all columns)</p>
<h2>Browser Support</h2>
<p>Let&#8217;s look at the current implementations (as of August, 2010)<br /><br />
<strong>Mozilla (Firefox 3.6)</strong><br />
10 standard properties are supported plus <a href="https://developer.mozilla.org/en/CSS3_Columns#Height_Balancing">an extra one created by Mozilla</a><br />
-moz-column-height</p>
<p>-moz-column-width<br />
-moz-column-count<br />
-moz-columns<br />
-moz-column-gap<br />
-moz-column-rule<br />
-moz-column-rule-width<br />
-moz-column-rule-style<br />
-moz-column-rule-color<br />
-moz-column-fill<br />
-moz-column-span</p>
<p><strong>Webkit (Chrome 6, Safari 5)</strong><br />

10 standard properties are supported<br />
-webkit-column-width<br />
-webkit-column-count<br />
-webkit-columns<br />
-webkit-column-gap<br />
-webkit-column-rule<br />
-webkit-column-rule-width<br />
-webkit-column-rule-style<br />
-webkit-column-rule-color<br />
-webkit-column-fill<br />
-webkit-column-span</p>

<p><strong>Opera</strong><br />
Not Supported</p>
<p><strong>IE</strong><br />
Not Supported</p>
<h2>Webkit and Mozilla Render differently</h2>
<p>To further complicate the use of CSS3 multiple columns, even simple examples are rendered differently by Webkit and Mozilla.</p>
<p>If you set both column-width and column-count, visitors with a Webkit browser see a very different result than visitors with a Mozilla browser.<br />

For example, here are images of the following code in Firefox 3.6 and Chrome 6</p>
<p><code>-moz-column-count: 3;<br />
-moz-column-width: 45px;<br />
-webkit-column-count: 3;<br />
-webkit-column-width: 45px;</code></p>
<p><img src="http://html5.litten.com/wp-content/uploads/2010/08/ff.jpg" alt="" title="ff" width="599" height="211" class="alignnone size-full wp-image-647" /><br />
<img src="http://html5.litten.com/wp-content/uploads/2010/08/chr6.jpg" alt="" title="chr6" width="533" height="306" class="alignnone size-full wp-image-649" /></p>
<p>While Chrome limits the column width to what it is set at (45px) Firefox limits the column width based on the column number. If you allow Firefox to automatically set the column number, it will then limit the column width to what it is set at (45px).</p>
<p>It may be quite awhile before the average webmaster uses CSS3 multiple columns.</p>

<p>Some sites for further reading.<br />
W3C Specification <a href="http://www.w3.org/TR/css3-multicol/">http://www.w3.org/TR/css3-multicol/</a><br />
Demo page with source code. <a href="http://www.quirksmode.org/css/multicolumn.html">http://www.quirksmode.org/css/multicolumn.html</a><br />
Mozilla Dev Page <a href="https://developer.mozilla.org/en/CSS3_Columns">https://developer.mozilla.org/en/CSS3_Columns</a>]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/css3-series-multiple-columns/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Graphing Data in the HTML5 Canvas Element Part IV Simple Pie Charts</title>
		<link>http://html5.litten.com/graphing-data-in-the-html5-canvas-element-part-iv-simple-pie-charts/</link>
		<comments>http://html5.litten.com/graphing-data-in-the-html5-canvas-element-part-iv-simple-pie-charts/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 19:57:19 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[Canvas Element]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[2d context]]></category>
		<category><![CDATA[graphing]]></category>
		<category><![CDATA[pie charts]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=614</guid>
		<description><![CDATA[In this post we will create a simple pie chart that is easy to feed data to. This example is coded for readability and not for optimized operation. All you need is a text editor like notepad and an HTML5 friendly browser (I&#8217;m using Firefox 3.6). &#60;!doctype html&#62; &#60;html&#62; &#60;head&#62; &#60;meta charset="UTF-8" /&#62; &#60;title&#62;Canvas Test&#60;/title&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>In this post we will create a simple pie chart that is easy to feed data to.</p>

<p>This example is coded for readability and not for optimized operation. All you need is a text editor like notepad and an HTML5 friendly browser (I&#8217;m using Firefox 3.6).</p>
<pre><code>
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset="UTF-8" /&gt;
&lt;title&gt;Canvas Test&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;section&gt;
&lt;div&gt;
&lt;canvas id="canvas" width="400" height="300"&gt;
This text is displayed if your browser does not support HTML5 Canvas.
&lt;/canvas&gt;
&lt;/div&gt;

&lt;script type="text/javascript"&gt;

var myColor = ["#ECD078","#D95B43","#C02942","#542437","#53777A"];
var myData = [10,30,20,60,40];

function getTotal(){
var myTotal = 0;
for (var j = 0; j &lt; myData.length; j++) {
myTotal += (typeof myData[j] == 'number') ? myData[j] : 0;
}
return myTotal;
}

function plotData() {
var canvas;
var ctx;
var lastend = 0;
var myTotal = getTotal();

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);

for (var i = 0; i &lt; myData.length; i++) {
ctx.fillStyle = myColor[i];
ctx.beginPath();
ctx.moveTo(200,150);
ctx.arc(200,150,150,lastend,lastend+
  (Math.PI*2*(myData[i]/myTotal)),false);
ctx.lineTo(200,150);
ctx.fill();
lastend += Math.PI*2*(myData[i]/myTotal);
}
}

plotData();

&lt;/script&gt;
&lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre></code>
<p>You can copy this code and paste it into a new file called something like simplepie.html and when you open it with an HTML5 friendly browser like Firefox 3.6 it will display the pie chart.</p>
<span id="more-614"></span>
<p><strong>Here is our canvas in action...</strong></p>
  <section>    
    <div>
        <canvas id="canvas" width="400" height="300">
         This text is displayed if your browser does not support HTML5 Canvas.
        </canvas>
    </div>
    
<script type="text/javascript">

var myColor = ["#ECD078","#D95B43","#C02942","#542437","#53777A"];
var myData = [10,30,20,60,40];

function getTotal(){
  var myTotal = 0;  
  for (var j = 0; j < myData.length; j++) {
    myTotal += (typeof myData[j] == 'number') ? myData[j] : 0;
  }
  return myTotal;
}

function plotData() {
  var canvas;  
  var ctx;
  var lastend = 0;
  var myTotal = getTotal();

  canvas = document.getElementById("canvas");
  ctx = canvas.getContext("2d");  
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  for (var i = 0; i < myData.length; i++) {
    ctx.fillStyle = myColor[i];
    ctx.beginPath();
    ctx.moveTo(200,150);    
    ctx.arc(200,150,150,lastend,lastend+(Math.PI*2*(myData[i]/myTotal)),false);
    ctx.lineTo(200,150);
    ctx.fill();
    lastend += Math.PI*2*(myData[i]/myTotal);      
  }
}

plotData();

</script>
  </section>
<br/>
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<p><strong>The algorithm for making a simple pie chart is something like this...</strong></p>

<ol style="font-weight: bold;">
	<li><div style="font-weight: normal;">Get the data that is being represented by the chart (it must be numerical)</div></li>

	<li><div style="font-weight: normal;">Calculate the total by adding all of the data together.</div></li>

	<li><div style="font-weight: normal;">Calculate the amount of pie for each piece of data by dividing it by the total.</div></li>

	<li><div style="font-weight: normal;">Multiply 2*pi radians by the amount of pie to get the length of the arc for that piece of pie.</div></li>

	<li><div style="font-weight: normal;">Draw the resulting arcs at a distance of r (the radius) from the center starting each arc at either 0 (the first arc) or from the end of the last drawn arc.</div></li>

	<li><div style="font-weight: normal;">Each arc has a line from its beginning and its ending to the center of the circle that is of length r</div></li>
</ol>
</div>
<br/>

<p>Since the arc() method of the 2d canvas context is based on paths, this is real easy to code.</p>
<blockquote>
<pre>arc(x, y, radius, startAngle, endAngle, anticlockwise)</pre>
<p><em>This method takes five parameters: x and y are the coordinates of the circle's center. Radius is self explanatory. The startAngle and endAngle parameters define the start and end points of the arc in radians. The starting and closing angle are measured from the x axis. The anticlockwise parameter is a Boolean value which when true draws the arc anticlockwise, otherwise in a clockwise direction.<br/>
Note: Angles in the arc function are measured in radians, not degrees. To convert degrees to radians you can use the following JavaScript expression: var radians = (Math.PI/180)*degrees.<br/>
<a href="https://developer.mozilla.org/en/Canvas_tutorial/Drawing_shapes#Arcs">https://developer.mozilla.org/en/Canvas_tutorial/Drawing_shapes#Arcs</a></em></p>
</blockquote>
<br/>
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<p>Step 1 of the algorithm is accomplished by this loop in our <code>plotData()</code> function <br/>
   <pre>for (var i = 0; i < myData.length; i++) {</pre>
<br/>
Where myData[i] represents the data from the hard coded global variable <br/>
    <pre>var myData = [10,30,20,60,40];</pre>
<br/>
This could easily be from a database, table data or from input textboxes filled in by the visitor.</p>
</div>
<br/>


<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<p>Step 2 of the algorithm is accomplished by our <code>getTotal()</code> function which loops through our data and adds it all together returning our total. It also verifies that our data is numeric giving it a value of zero if it is not.
<pre>function getTotal(){
  var myTotal = 0;  
  for (var j = 0; j < myData.length; j++) {
    myTotal += (typeof myData[j] == 'number') ? myData[j] : 0;
  }
  return myTotal;
}      
</pre>
</p>
</div>
<br/>

<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<p>Step 3 of the algorithm is accomplished by the highlighted part of this line in our <code>plotData()</code> function.
    <pre>ctx.arc(200,150,150,lastend,lastend+
       (Math.PI*2*<span style="background-color:yellow">(myData[i]/myTotal)</span>),false);</pre>
</p>
</div>
<br/>
    
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">    
<p>Step 4 of the algorithm is accomplished by the highlighted part of this line in our <code>plotData()</code> function.
    <pre>ctx.arc(200,150,150,lastend,lastend+
       <span style="background-color:yellow">(Math.PI*2*(myData[i]/myTotal))</span>,false);</pre>    
</p>
</div>
<br/>
    
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">    
<p>Step 5 of the algorithm is accomplished in our <code>plotData()</code> function by using the variable lastend to start at 0 radians and then keep track of where the previous arc ended.
    <pre>lastend += Math.PI*2*(myData[i]/myTotal);</pre> 
</p>
</div>
<br/>    
    
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">    
<p>Step 6 of the algorithm is accomplished in our <code>plotData()</code> function by starting our path at the center of the circle
<pre>    ctx.beginPath();
    ctx.moveTo(200,150);</pre>
    
then we draw our arc which extends our path from the center to the start of our arc        
<pre>    ctx.arc(200,150,150,lastend,lastend+
       (Math.PI*2*(myData[i]/myTotal)),false);</pre>

then we extend our path back to the center of our circle and fill in the shape (our pie slice)    
<pre>    ctx.lineTo(200,150);
    ctx.fill(); </pre>
</p>
</div>
<br/>


<p>Since we use an array of color values to make sure that all the pie slices are easy to see,
<pre>    var myColor = ["#ECD078","#D95B43","#C02942","#542437","#53777A"]; </pre>
we can create a legend saying what each color represents.</p> 

<table border="0" cellpadding="10">
<tbody>
<tr><td align="center" style="color: #ECD078;">&#9608;</td>
<td align="center">10</td></tr>
<tr><td align="center" style="color: #D95B43;">&#9608;</td>
<td align="center">30</td></tr>
<tr><td align="center" style="color: #C02942;">&#9608;</td>
<td align="center">20</td></tr>
<tr><td align="center" style="color: #542437;">&#9608;</td>
<td align="center">60</td></tr>
<tr><td align="center" style="color: #53777A;">&#9608;</td>
<td align="center">40</td></tr>
</tbody>
</table>
<br/>



<p>In our next post, we'll look at making our pie fancy with labels and maybe a few animations. </p>

<p>This is post 4 of a multipart series of posts.</p>
<p><a href="http://html5.litten.com/graphing-data-in-the-html5-canvas-element-part-i/">Graphing Data in the HTML5 Canvas Element Part I</a></p> 
<p><a href="http://html5.litten.com/graphing-data-in-the-html5-canvas-element-part-ii/">Graphing Data in the HTML5 Canvas Element Part II</a></p>
<p><a href="http://html5.litten.com/graphing-data-in-the-html5-canvas-element-part-iii/">Graphing Data in the HTML5 Canvas Element Part III</a></p>


]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/graphing-data-in-the-html5-canvas-element-part-iv-simple-pie-charts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>HTML5 Web Storage, Using localStorage and sessionStorage Objects</title>
		<link>http://html5.litten.com/html5-web-storage-using-localstorage-and-sessionstorage-objects/</link>
		<comments>http://html5.litten.com/html5-web-storage-using-localstorage-and-sessionstorage-objects/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 21:17:33 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Web Storage]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[localStorage]]></category>
		<category><![CDATA[sessionStorage]]></category>
		<category><![CDATA[webstorage]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=583</guid>
		<description><![CDATA[Web storage started as part of the HTML5 spec for storing key-value pair data in web clients. It now has its own spec. There are other plans for storing databases that are structured and can be queried using SQL which are handled in a separate spec . Seeing the need for storing more key-value pair [...]]]></description>
			<content:encoded><![CDATA[<p>Web storage started as part of the HTML5 spec for storing key-value pair data in web clients. It now has <a href="http://www.w3.org/TR/webstorage/">its own spec</a>. There are other plans for storing databases that are structured and can be queried using SQL which are handled in a <a href="http://www.w3.org/TR/webdatabase/">separate spec</a> .</p>
<p>Seeing the need for storing more key-value pair data on the web client than can currently be stored in a cookie, all major web browsers quickly adopted support for a storage object that can hold up to 5MB of data that persists until the web client&#8217;s cache is cleared or the storage object is programatically cleared, or in the case of sessionStorage, the browser window (tab) is closed.
This quick and relatively consistent adoption by web browsers is a rare treat for web developers.</p> 

<div style=" 
background-color: #CCC;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<p><strong>IMPORTANT: Do not store sensitive data in web storage. When I do penetration testing, locally stored data is one of the first things that I look at.</strong></p>
</div><br/>

<div style=" 
background-color: #CCC;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<p><strong>IMPORTANT: All data in web storage is stored as strings. If you want to store an object, you should use JSON and call stringify() on it before storing it and parse() on it after retrieving it.</strong></p>
</div><br/>
<p>There are two flavors of the storage object that we will be looking at.</p>

<h3>sessionStorage object</h3>
<p>The sessionStorage object stores data only for a session, meaning that the data is stored until the browser (or tab) is closed. it is not available when a file is run locally.</p>

<p>Data stored in the sessionStorage object is accessible only from the page that initially stored the data.</p>

<h3>localStorage object</h3>
<p>Data stored using the localStorage object is persisted until it is specifically removed via JavaScript or the user clears the browser&#8217;s cache.</p>

<p>Data stored in the localStorage object is accessible only from the domain that initially stored the data.</p>
<hr />
<p>Both localStorage and sessionStorage objects have the same interface, differing only in how the data stored by them persists and who can access the data.</p>

<div style=" 
background-color: #CCC;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<h3>The setItem method</h3>
<pre>setItem( key, value)
sessionStorage.setItem("name", "Sam")
localStorage.setItem("name", "Sam")

or the property using an <a href="http://en.wiktionary.org/wiki/expando">expando</a>
sessionStorage.name("Sam")
localStorage.name("Sam")
</pre>
</div><br/>
<div style=" 
background-color: #CCC;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<h3>The getItem method</h3>

<pre>getItem(key)
name = sessionStorage.getItem("name")
name = localStorage.getItem("name")

or the property using an expando
name = sessionStorage.name
name = localStorage.name
</pre>
</div><br/>
<div style=" 
background-color: #CCC;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<h3>The removeItem method</h3>

<pre>removeItem(key)
name = sessionStorage.removeItem("name")
name = localStorage.removeItem("name")

</pre>
<p>The property using an expando required an extra &#8216;delete&#8217; keyword and is no longer in the spec.</p> 
</div><br/>
<div style=" 
background-color: #CCC;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<h3>The clear method</h3>
<p>The clear() method causes the list associated with the object to be emptied of all key/value pairs</p>

<pre>sessionStorage.clear
localStorage.clear
</pre>

</div><br/>
<div style=" 
background-color: #CCC;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<h3>The key and length properties</h3>
<p>Key and length are useful for looping through all of the key value pairs, especially if you don&#8217;t know what they all are.</p>
Key is an index of the key values ( key(0), key(1), key(2) &#8230;)
Length is the number of keys.

<pre>
for (var i=0, len = sessionStorage.length; i  <  len; i++){
    var key = sessionStorage.key(i);
    var value = sessionStorage.getItem(key);
    alert(key + "=" + value);
} 
</pre>

</div><br/>
<h3>Storage Event</h3>
<p>The storage event is fired on the window object whenever something changes in storage. For example, if you set an item to its existing value or call clear() when there are no named keys, the storage event will not fire, because nothing actually changed in the storage area.</p>

<p>The storage event has the following attributes</p>
<ul>
<li><strong>key</strong> the named key that was added, removed, or modified</li>

<li><strong>oldValue</strong> the previous value (now overwritten), or null if a 
   new item was added</li>

<li><strong>newValue</strong> any the new value, or null if an item was removed</li>

<li><strong>url</strong> the page which called a method that triggered this change</li>

<li><strong>storageArea</strong> represents the Storage object that was affected.</li>
</ul>
<h3>Some online DEMOs</h3>
<p><a href="http://html5demos.com/storage">HTML5 Demos: Storage</a><br/>
<a href="http://people.opera.com/shwetankd/external/demos/webstorage_demo.htm">Web Storage Example</a></p>
<h3>Browser Compatibility (as of August, 2010)</h3>
<pre>
Internet Explorer 8
Firefox 3.5 
Safari 4
Google Chrome 5
Opera 10.50
</pre>
<p>Only Opera supports the Storage event's attributes but I've verified that the storage event can be triggered on Chrome 5 and Firefox 3.6 though, the attributes for the event are all set to undefined.</p>
<h3>Further Reading</h3>
<p><a href="http://www.amazon.com/dp/047022780X?tag=allcrafts&#038;camp=213381&#038;creative=390973&#038;linkCode=as4&#038;creativeASIN=047022780X&#038;adid=09BTD55PR43DYE1F7JEH&#038;">Professional JavaScript for Web Developers</a> Chapter Chapter 19 section on DOM Storage</p>
<p><a href="http://www.amazon.com/gp/product/0321687299?ie=UTF8&#038;tag=allcrafts&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0321687299">Introducing HTML5</a>  Chapter 6</p>
<hr />]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/html5-web-storage-using-localstorage-and-sessionstorage-objects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing With CSS Transitions On Firefox 4 Beta 2</title>
		<link>http://html5.litten.com/playing-with-css-transitions-on-firefox-4-beta-2/</link>
		<comments>http://html5.litten.com/playing-with-css-transitions-on-firefox-4-beta-2/#comments</comments>
		<pubDate>Thu, 29 Jul 2010 18:31:26 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[CSS 3.0]]></category>
		<category><![CDATA[transitions]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=578</guid>
		<description><![CDATA[I saw the recent announcement by Paul Rouget that Firefox 4 beta 2 has support for CSS transitions and I thought it would be fun to play with it. Here is a demo with complete source code where I chained together a bunch of CSS transitions using the transitionend event to trigger the transitions sequentially. [...]]]></description>
			<content:encoded><![CDATA[<p>I saw the <a href="http://hacks.mozilla.org/2010/07/firefox4-beta2/">recent announcement by Paul Rouget</a> that Firefox 4 beta 2 has support for CSS transitions and I thought it would be fun to play with it.</p>
<p>Here is a demo with complete source code where I chained together a bunch of CSS transitions using the transitionend event to trigger the transitions sequentially.</p>
<p><a href="http://html5.litten.com/csstransitions/csstransitionsdemo.html">DEMO CSS transitions in Firefox 4 beta 2</a></p>
<p>The demo requires <a href="http://www.mozilla.com/en-US/firefox/beta/">Firefox 4 beta 2</a></p>
<p>I found that the transitionend event was triggered more often then I expected and had to remove listeners for the event when I was done with them or they sometimes triggered again. I need to learn more about what triggers them. </p>
<p>Have fun with the code as that is the best way to learn.</p>]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/playing-with-css-transitions-on-firefox-4-beta-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Multiple HTML5 Canvases as Layers</title>
		<link>http://html5.litten.com/using-multiple-html5-canvases-as-layers/</link>
		<comments>http://html5.litten.com/using-multiple-html5-canvases-as-layers/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 21:28:25 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[Canvas Element]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[2d context]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[CSS 3.0]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[restore]]></category>
		<category><![CDATA[save]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=559</guid>
		<description><![CDATA[DEMO Here&#8217;s our finished canvas with full source code. The reasons why you would want to layer multiple canvases on top of each other are many but they all have a common root. There is a requirement in the W3C definition of the 2d context&#8230; There is only one CanvasRenderingContext2D object per canvas, so calling [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://html5.litten.com/layers/canvaslayers.html"><strong>DEMO</strong> Here&#8217;s our finished canvas with full source code.</a></p>

<p>The reasons why you would want to layer multiple canvases on top of each other are many but they all have a common root. There is a requirement in the W3C definition of the 2d context&#8230; </p> 

<blockquote><em>There is only one CanvasRenderingContext2D  object per canvas, so calling the getContext()  method with the 2d  argument a second time must return the same object. <br/>
<a href="http://dev.w3.org/html5/2dcontext/#conformance-requirements">http://dev.w3.org/html5/2dcontext/#conformance-requirements</a></em>
</blockquote>

<p>Having just one 2d context means that you have to keep track of everything on the context even if you only want to change part of the canvas.</p> 

<p>An example of using layers is animation. When I was a child, I loved making animated cartoons and I learned that if I painted them on clear plastic sheets I could stack the sheets and only redraw the parts that moved. I could make an elaborate background and use it over and over instead of redrawing it for every frame. The same principle applies here to our canvases.</p>

<p>In this example, our three canvases have transparent areas that allow you to see what is on the canvas beneath each.</p>
<span id="more-559"></span>
<p>First, let&#8217;s look at our three canvases separately and then we&#8217;ll stack them on top of each other.</p>

  <section>
  <div>
  <p>Our bottom layer</p>
    <canvas id="layer1" height="300px" width="400">
      This text is displayed if your browser does not support HTML5 Canvas.
    </canvas>
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<pre><code>
function draw1() {
  ctx1.clearRect(0, 0, WIDTH, HEIGHT);
  ctx1.fillStyle = "#FAF7F8";
  ctx1.beginPath();
  ctx1.rect(0,0,WIDTH,HEIGHT);
  ctx1.closePath();
  ctx1.fill();
  ctx1.fillStyle = "#444444";
  ctx1.beginPath();
  ctx1.arc(x, y, 10, 0, Math.PI*2, true);
  ctx1.closePath();
  ctx1.fill();

  if (x + dx &gt; WIDTH || x + dx &lt; 0)
    dx = -dx;
  if (y + dy &gt; HEIGHT || y + dy &lt; 0)
    dy = -dy;

  x += dx;
  y += dy;
}
</code></pre> 
<p>The code for this animation is fully explained here. <a href="http://html5.litten.com/simple-animation-in-the-html5-canvas-element/">Simple Animation in the HTML5 Canvas Element</a> </p>
</div>
    </div>
      <div>
  <p>Our middle layer</p>
    <canvas id="layer2" height="300px" width="400">
      This text is displayed if your browser does not support HTML5 Canvas.
    </canvas>
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<pre><code>
function draw2() {
  ctx2.clearRect(0, 0, WIDTH, HEIGHT);
  ctx2.drawImage(city, 0, 0); 
}
</code></pre> 
<p>We are simply drawing city.png <a href="http://html5.litten.com/layers/city.png">http://html5.litten.com/layers/city.png</a> to the canvas. The sky in this image is transparent.</p>
</div>    
    </div>
      <div>
  <p>Our top layer</p>
    <canvas id="layer3" height="300px" width="400">
      This text is displayed if your browser does not support HTML5 Canvas.
    </canvas>
<div style=" 
background-color: #F8F8F8;
padding: 10px;
width: 90%;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
    -webkit-box-shadow: 10px 10px 25px #D5D5D5;
    -moz-box-shadow: 10px 10px 25px #D5D5D5;
    box-shadow: 10px 10px 25px #D5D5D5;
">
<pre><code>
function draw3() {
  ctx3.clearRect(0, 0, WIDTH, HEIGHT);
  ctx3.fillStyle = "#444444";
  ctx3.save();
  ctx3.translate(200,200);
  ctx3.rotate(x/20); 
  ctx3.fillRect(-15, -15, 30, 30);  
  ctx3.restore();
}
</code></pre> 
<p>Here we transform the canvas&#8217;s coordinate system and rotate the square based on the global variable x which is used in layer 1 also. For more information on transforms with save() and restore() go here <a href="http://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/">Understanding save() and restore() for the Canvas Context</a> </p>
</div>
  </div>
<script type="text/javascript">
var layer1;
var layer2;
var layer3;  
var ctx1;
var ctx2;
var ctx3;
var x = 400;
var y = 300;
var dx = 2;
var dy = 4;
var WIDTH = 400;
var HEIGHT = 300; 
var city = new Image();

function init() {
  city.src ="http://html5.litten.com/layers/city.png";
  layer1 = document.getElementById("layer1");
  ctx1 = layer1.getContext("2d");
  layer2 = document.getElementById("layer2");
  ctx2 = layer2.getContext("2d");
  layer3 = document.getElementById("layer3");
  ctx3 = layer3.getContext("2d");
  setInterval(drawAll, 20);
}

function drawAll() {
  draw1();
  draw2();
  draw3();
}

function draw1() {
  ctx1.clearRect(0, 0, WIDTH, HEIGHT);
  ctx1.fillStyle = "#FAF7F8";
  ctx1.beginPath();
  ctx1.rect(0,0,WIDTH,HEIGHT);
  ctx1.closePath();
  ctx1.fill();
  ctx1.fillStyle = "#444444";
  ctx1.beginPath();
  ctx1.arc(x, y, 10, 0, Math.PI*2, true);
  ctx1.closePath();
  ctx1.fill();

  if (x + dx > WIDTH || x + dx < 0)
    dx = -dx;
  if (y + dy > HEIGHT || y + dy < 0)
    dy = -dy;

  x += dx;
  y += dy;
}

function draw2() {
  ctx2.clearRect(0, 0, WIDTH, HEIGHT);
  ctx2.drawImage(city, 0, 0);   
}

function draw3() {
  ctx3.clearRect(0, 0, WIDTH, HEIGHT);
  ctx3.fillStyle = "#444444";
  ctx3.save();
  ctx3.translate(200,200);
  ctx3.rotate(x/20); 
  ctx3.fillRect(-15, -15, 30, 30);  
  ctx3.restore();
}

init();
</script>
  </section>

<h3>Now to stack them</h3>
<p>We use CSS to set all the canvases to an absolute position of (0,0) inside our parent DIV tag.</p>
<pre><code>
    position:absolute;
    left:0px;
    top:0px;
</code></pre>     
<p>We also use CSS to set the z-index of our canvases. The z-index property specifies the stack order of an element. Items with lower z-index values go behind items with higher z-index values.</p>
<pre><code>
<strong>Bottom layer</strong>
    canvas id="layer1" 
    style="z-index: 1;
    
<strong>Middle layer</strong>    
    canvas id="layer2" 
    style="z-index: 2;

<strong>Top Layer </strong>   
    canvas id="layer3" 
    style="z-index: 3;      
</code></pre>     
<p><a href="http://html5.litten.com/layers/canvaslayers.html"><strong>DEMO</strong> Here's our finished canvas with full source code.</a></p>

<p>Now it doesn't matter that a canvas can only have one 2d context because we can just make multiple canvases and stack them.</p>

<p>If you have a question that you do not want published as a public comment, then use my <a href="http://html5.litten.com/contact-me/">contact page</a>. </p>

<p>Have fun with the code as that is the easiest way to learn.</p>      ]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/using-multiple-html5-canvases-as-layers/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>IE Compatible Canvas Drag and Drop With jQuery and ExCanvas</title>
		<link>http://html5.litten.com/ie-compatible-canvas-drag-and-drop-with-jquery-and-excanvas/</link>
		<comments>http://html5.litten.com/ie-compatible-canvas-drag-and-drop-with-jquery-and-excanvas/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 18:25:01 +0000</pubDate>
		<dc:creator>James Litten</dc:creator>
				<category><![CDATA[Canvas Element]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://html5.litten.com/?p=538</guid>
		<description><![CDATA[This post is about making drag and drop work on a canvas in Internet Explorer versions 6, 7 and 8 . The details of how to drag and drop on the canvas can be found in this previous post. How to Drag and Drop on an HTML5 Canvas To modify our canvas in order to [...]]]></description>
			<content:encoded><![CDATA[<p>This post is about making drag and drop work on a canvas in Internet Explorer versions 6, 7 and 8 . The details of how to drag and drop on the canvas can be found in this previous post.
<a href="http://html5.litten.com/how-to-drag-and-drop-on-an-html5-canvas/">How to Drag and Drop on an HTML5 Canvas</a>  </p>


<h3>To modify our canvas in order to make it work in IE we need to &#8230;</h3>
<strong><ul>
<li>Use ExplorerCanvas to make IE&#8217;s VML act like a canvas like object</li>

<li>Use jQuery to manage our events and make them compatible with IE</li>

<li>Use jQuery to calculate our canvas&#8217; offsets</li>

<li>Move our call to <code>init()</code> to the body.onload event</li>
</ul></strong>
<p>Sounds like a lot but it really isn&#8217;t.</p> 

<p><a href="http://html5.litten.com/dragdrop/dragdropie.html">Here&#8217;s the DEMO page that should work in all current browsers including IE</a>. The full source code for the page is listed below the canvas.</p>

<span id="more-538"></span>

<h3>Use ExplorerCanvas to make IE&#8217;s VML act like a canvas like object</h3>
<p>In our &lt;head&gt; we add a conditional reference to Google&#8217;s Explorer Canvas javascript framework so that it loads if the visitor is using IE.</p>
<pre><code>
&lt;!--[if IE]&gt;&lt;script type="text/javascript" src="excanvas.js"&gt;&lt;/script&gt;
&lt;![endif]--&gt;
</code></pre>
<p>The file excanvas.js can be downloaded from here&#8230; </p>
<a href="http://code.google.com/p/explorercanvas/downloads/list">http://code.google.com/p/explorercanvas/downloads/list</a>

<h3>Use jQuery to manage our events and make them compatible with IE</h3>
<p>The jQuery framework does a great job of handling events across browsers. It is the main reason that I have used jQuery in my own projects. You do not even have to download it as it is hosted by Google at.<br/>
http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js <br/>
So simply adding a reference to it in your &lt;head&gt; is enough to use it.</p>
<pre><code>
&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs
/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
</code></pre>
<p>If you want to have it on your server, you can download it from here.<br/>
<a href="http://jquery.com/">http://jquery.com/</a> </p>

<p>Setting our event listener is a little different but we still use the same functions that we wrote in the original post <a href="http://html5.litten.com/how-to-drag-and-drop-on-an-html5-canvas/">How to Drag and Drop on an HTML5 Canvas</a>.</p>
<pre><code>
 $("canvas").mousedown(function myDown(e){
 var position = $("canvas").position();
 if (e.clientX < x + 15 + position.left &#038;&#038; e.clientX > x - 15 + 
  position.left &#038;&#038; e.clientY < y + 15 + position.top &#038;&#038; 
  e.clientY > y -15 + position.top){
    x = e.clientX;
    y = e.clientY;
    dragok = true;
    $("canvas").mousemove(function myMove(e){
       if (dragok){
        x = e.clientX - position.left;
        y = e.clientY - position.top;
       }
});
 }
}); 
 $("canvas").mouseup(function myUp(e){
  dragok = false;
  $("canvas").mousemove(null);
}); 
</code></pre>
<p>Notice that we removed our traditional event listeners and wrapped the functions our events trigger with the jQuery event listeners</p>
<pre><code>
$("canvas").mousedown()
$("canvas").mouseup()
$("canvas").mousemove()
</code></pre>
<p>These are shorthand versions of the jQuery bind method. The longhand looks like this.</p>
<pre><code>
$("canvas").bind(mousemove, mymove())
</code></pre>
<p>The shorthand versions work fine and are easier to read.</p>


<h3>Use jQuery to calculate our canvas&#8217; offsets</h3>
<p>Sometimes I feel as though offsets are the bane of my existence. jQuery makes them consistent across browsers with the position method.<br/>
The position method returns an object containing the position of the top-left corner of the element relative to the top-left corner of the first positioned parent of the element.<br/>
In our <code>myDown(e)</code> function we get our canvas&#8217; offsets with regard to their parent. </p>
<pre><code>
var position = $("canvas").position();
</code></pre>
<p>Now we can use <code>position.left</code> and <code>position.top</code> as our offsets in calculating where our mouse is on the canvas. </p>
<pre><code>
       if (dragok){
        x = e.clientX - position.left;
        y = e.clientY - position.top;
       }
</code></pre>       
<h3>Move our call to init() to the body.onload event</h3>
<p>That&#8217;s all we have left to do.</p>
<pre><code>
&lt;body onload = "init();"&gt;
</code></pre>
<p>This makes sure that <code>init()</code> isn&#8217;t called until the &lt;canvas&gt; is properly loaded in ExplorerCanvas.</p>

<p>That&#8217;s it. <a href="http://html5.litten.com/dragdrop/dragdropie.html">Here is the full source code of our modified canvas as well as a DEMO</a>.</p>

<p>If you have a question that you do not want published as a public comment, then use my <a href="http://html5.litten.com/contact-me/">contact page</a>. </p>]]></content:encoded>
			<wfw:commentRss>http://html5.litten.com/ie-compatible-canvas-drag-and-drop-with-jquery-and-excanvas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

