<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3651123362811338649</id><updated>2011-09-26T23:55:46.873-07:00</updated><category term='Map'/><category term='debug'/><category term='Gears'/><category term='Geo'/><category term='Cross Document Messaging'/><category term='Label2'/><category term='YouTube'/><category term='javascript'/><category term='minify'/><category term='Google App Engine'/><category term='Label1'/><category term='HTML5'/><title type='text'>Open Web Corner</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://austinchau.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://austinchau.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>austinchau</name><uri>http://www.blogger.com/profile/01633572775665164303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3651123362811338649.post-6208005233089593702</id><published>2010-01-25T15:49:00.001-08:00</published><updated>2010-01-25T15:49:18.793-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Label2'/><category scheme='http://www.blogger.com/atom/ns#' term='Label1'/><title type='text'>JS-Blogger-Client: inserted post</title><content type='html'>This is the body of the blog post.  I can include &lt;b&gt;HTML&lt;/b&gt; tags.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3651123362811338649-6208005233089593702?l=austinchau.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://austinchau.blogspot.com/feeds/6208005233089593702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3651123362811338649&amp;postID=6208005233089593702' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/6208005233089593702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/6208005233089593702'/><link rel='alternate' type='text/html' href='http://austinchau.blogspot.com/2010/01/js-blogger-client-inserted-post.html' title='JS-Blogger-Client: inserted post'/><author><name>austinchau</name><uri>http://www.blogger.com/profile/01633572775665164303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3651123362811338649.post-7703456830898013986</id><published>2008-11-17T10:47:00.000-08:00</published><updated>2008-11-17T12:40:14.503-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML5'/><category scheme='http://www.blogger.com/atom/ns#' term='Cross Document Messaging'/><title type='text'>HTML5 Cross Document Messaging</title><content type='html'>So I got to play with &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/#crossDocumentMessages"&gt;HTML5 Cross Document Messaging&lt;/a&gt; this weekend and built this quick demo -
&lt;br&gt;&lt;br&gt;
[ &lt;a href="http://achau.appspot.com/demo/html5/crossdoc/index.html"&gt;demo&lt;/a&gt; ] [ &lt;a href="http://code.google.com/p/austinchau/source/browse/#svn/trunk/demo/html5/crossdoc"&gt;source code&lt;/a&gt; ]
&lt;br&gt;&lt;br&gt;
The demo demonstrates how easy it is for two iframe of different origins to talk to each other.  In real time, each iframe is passing its own mouse coordinates from "onmousemove" event to each other.Right now, this feature is only supported in Firefox 3, IE8, Opera 9 and Safari Nightlies.  
&lt;br&gt;&lt;br&gt;
The basic semantic is to use postMessage() to send data to a window object and the receiving window should register for the "onmessage" event to receive data.
&lt;br&gt;
&lt;pre class="javascript" name="code"&gt;
    window.document.onmousemove = function(e) {
      var x = (window.Event) ? e.pageX : window.event.clientX;
      var y = (window.Event) ? e.pageY : window.event.clientY;
      
      // this send data to the second iframe of the current page
      window.parent.frames[1].postMessage('x = ' + x + ' y = ' + y, '*');      
    };

    var onmessage = function(e) {
      var data = e.data;
      var origin = e.origin;
      document.getElementById('display').innerHTML = data;
    };

    if (typeof window.addEventListener != 'undefined') {
      window.addEventListener('message', onmessage, false);
    } else if (typeof window.attachEvent != 'undefined') {
      window.attachEvent('onmessage', onmessage);
    }
&lt;/pre&gt;
One thing to beware of is that for some reason it would not receive data properly if you use the traditional event listener setup for "onmessage" event. You have to use addEventListener() -
&lt;br&gt;
&lt;pre class="javascript" name="code"&gt;
  window.onmessage = function() {
    // did not work in FF3
  };
&lt;/pre&gt;
This is a really neat feature and I can see it being extremely useful for platform builder or widget container to share common data easily and efficiently.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3651123362811338649-7703456830898013986?l=austinchau.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://austinchau.blogspot.com/feeds/7703456830898013986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3651123362811338649&amp;postID=7703456830898013986' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/7703456830898013986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/7703456830898013986'/><link rel='alternate' type='text/html' href='http://austinchau.blogspot.com/2008/11/html5-cross-document-messaging.html' title='HTML5 Cross Document Messaging'/><author><name>austinchau</name><uri>http://www.blogger.com/profile/01633572775665164303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3651123362811338649.post-3172352526449746076</id><published>2008-11-11T11:41:00.000-08:00</published><updated>2008-11-11T12:03:26.483-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Map'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Geo'/><category scheme='http://www.blogger.com/atom/ns#' term='YouTube'/><category scheme='http://www.blogger.com/atom/ns#' term='Gears'/><title type='text'>Using Gears Geolocation API + YouTube Geo Search</title><content type='html'>I just put together a sample to demonstrate combining both &lt;a href="http://code.google.com/apis/gears/api_geolocation.html"&gt;Gears Geolocation API&lt;/a&gt; and the new &lt;a href="http://code.google.com/apis/youtube/2.0/reference.html#locationsp"&gt;YouTube geo search&lt;/a&gt;.
&lt;br&gt;&lt;br&gt;
I have also posted this on the official &lt;a href="http://apiblog.youtube.com/2008/11/youtube-geo-search-gears-geolocation.html"&gt;YouTube API blog&lt;/a&gt;.
&lt;br&gt;&lt;br&gt;
[ &lt;a href="http://achau.appspot.com/demo/gears/geolocation/index.html"&gt;Go to demo&lt;/a&gt; ]
&amp;nbsp;&amp;nbsp;[ &lt;a href="http://code.google.com/p/google-ajax-examples/source/browse/#svn/trunk/youtubegeowithgears%3Fstate%3Dclosed"&gt;Source code&lt;/a&gt; ]
&lt;br&gt;&lt;br&gt;
&lt;img src="http://achau.appspot.com/static/images/youtube_gears.jpg" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3651123362811338649-3172352526449746076?l=austinchau.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://austinchau.blogspot.com/feeds/3172352526449746076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3651123362811338649&amp;postID=3172352526449746076' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/3172352526449746076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/3172352526449746076'/><link rel='alternate' type='text/html' href='http://austinchau.blogspot.com/2008/11/using-gears-geolocation-api-youtube-geo.html' title='Using Gears Geolocation API + YouTube Geo Search'/><author><name>austinchau</name><uri>http://www.blogger.com/profile/01633572775665164303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3651123362811338649.post-1588567168975692909</id><published>2008-11-03T13:31:00.000-08:00</published><updated>2008-11-03T13:59:05.154-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='debug'/><title type='text'>console.log() everywhere</title><content type='html'>I love using console.log() from Firebug.  I can't imagine debugging JavaScript without it.  Althought Chrome, Firefox(with Firebug) and Safari all support console.log(), IE and some other browsers do not.  
&lt;br&gt;&lt;br&gt;
Another problem is that I am too lazy to remove or comment all the console.log() in the production code (actually they are quite useful to leave around for future maintenance).  
&lt;br&gt;&lt;br&gt;
So I have written this quick snippet that basically injects the console.log() into the window object on unsupported browsers.  The "virtual" window.console will appear as a removable div (click to remove) on the top rightmost corner.  And the snippet would selectively turn on and off console.log() based on whether the flag ?__debug__ is appended to the end of the URL.  
&lt;br&gt;
&lt;pre name="code" class="javascript"&gt;
/*
 * Selectively turn on or off (using http://url/?__debug__ to turn on) 
 * console.log for debug.  Also create a virtual console.log() if it doesn't 
 * exist already (IE)
 */
if (/__debug__$/i.test(document.location.href)) {
  if (!window.console) {
    window.console = {};
    window.console.log = function(message) {
      
      var divId = 'v_window_console';
      var consoleDiv = document.getElementById(divId);
      
      if (!consoleDiv) {
        // create the virtual window console        
        var consoleDiv = document.createElement('div');
        consoleDiv.id = divId;
        consoleDiv.style.position = 'absolute';
        consoleDiv.style.top = '0';
        consoleDiv.style.right = '0';

        consoleDiv.onclick = function() {
          consoleDiv.innerHTML = '';
        };

        document.body.appendChild(consoleDiv);
      } 

      messageDiv = document.createElement('div');
      messageDiv.innerHTML = message;
      
      consoleDiv.appendChild(messageDiv);
    }
  }       
} else {
  // non-debug mode, an empty function
  window.console = window.console || {};
  window.console.log = function(message) {};
}
&lt;/pre&gt;
&lt;br&gt;
You can also link to this &lt;a href="http://achau.appspot.com/js_min/util.js"&gt; file &lt;/a&gt; which contains this snippet and all other utilities function that I collect.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3651123362811338649-1588567168975692909?l=austinchau.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://austinchau.blogspot.com/feeds/1588567168975692909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3651123362811338649&amp;postID=1588567168975692909' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/1588567168975692909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/1588567168975692909'/><link rel='alternate' type='text/html' href='http://austinchau.blogspot.com/2008/11/windowconsolelog-everywhere.html' title='console.log() everywhere'/><author><name>austinchau</name><uri>http://www.blogger.com/profile/01633572775665164303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3651123362811338649.post-2125673437081930009</id><published>2008-11-03T11:12:00.000-08:00</published><updated>2008-11-03T14:59:26.888-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='minify'/><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><title type='text'>Serving minified JavaScript files with Google App Engine</title><content type='html'>JavaScript minification is the process that removes source code comments and newlines in order to create a compacted version of the file.  This is especially useful when your web app is loading very large JavaScript files, minification can boost performance by cutting a big portion of the download time.  
&lt;br&gt;&lt;br&gt;
Since I host a lot of JavaScript using Google App Engine, I have made a script that can automate minification whenever JavaScript is requested.  The goal is to make this process as transparent as possible.  I am using &lt;a href="http://javascript.crockford.com/jsmin.html"&gt;Douglas Crockford JSMin&lt;/a&gt; in my python script.
&lt;br&gt;&lt;br&gt;
So you just need to place all your JavaScript under a "js/" directory.  When you request a file like this &lt;a href="http://achau.appspot.com/js/cmc-core.js"&gt;http://achau.appspot.com/js/cmc-core.js&lt;/a&gt;, this will serve original file without minification.  But when you request the file with this URL 
&lt;a href="http://achau.appspot.com/js_min/cmc-core.js"&gt;http://achau.appspot.com/js_min/cmc-core.js&lt;/a&gt;, the minified version will be served.  
&lt;br&gt;&lt;br&gt;
To further enhance performance, I used the App Engine &lt;a href="http://code.google.com/appengine/docs/memcache/"&gt;memcache&lt;/a&gt; feature so that file request will be served out of App Engine cache.  This works great for stable files in production.  But since files served out of memcache can be outdated (in javascript.py - default cache expires every 15 minutes), I have added extra access points to retrieve the latest copies directly from disk instead of cache. Use "js_/myfile.js" to access your original JavaScript files without hitting the cache and likewise use "js_min_/myfile.js" to access the minified JavaScript without hitting the cache.
&lt;br&gt;&lt;br&gt;
This script can actually minfiy CSS files as well - 
&lt;a href="http://achau.appspot.com/js_min/codemirror/css/jscolors.css"&gt;http://achau.appspot.com/js_min/codemirror/css/jscolors.css&lt;/a&gt;

&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight:bold;"&gt;How to install:&lt;/span&gt;
&lt;br&gt;&lt;br&gt;
1) Upload these two python scripts to your App Engine account: &lt;a href="http://achau.appspot.com/static/javascript.py"&gt;javascript.py&lt;/a&gt; and &lt;a href="http://achau.appspot.com/static/jsmin.py"&gt;jsmin.py&lt;/a&gt;
&lt;br&gt;&lt;br&gt;
2) Add this entry to your App Engine app.yaml file -
&lt;pre name="code" class="python"&gt;
- url: /js.*
  script: javascript.py
&lt;/pre&gt;
Now your App Engine account is ready to serve minified JavaScript :)
&lt;br&gt;&lt;br&gt;
&lt;span style="font-weight:bold;"&gt;Summary:&lt;/span&gt;
&lt;br&gt;&lt;br&gt;
After the installation, you now have four different URLs to access your JavaScript files.
&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;
Original file serving from memcache - &lt;br&gt;
&lt;a href="http://achau.appspot.com/js/cmc-core.js"&gt;http://achau.appspot.com/js/cmc-core.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Original file serving from disk - &lt;br&gt;
&lt;a href="http://achau.appspot.com/js_/cmc-core.js"&gt;http://achau.appspot.com/js_/cmc-core.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Minified file serving from memcache - &lt;br&gt;
&lt;a href="http://achau.appspot.com/js_min/cmc-core.js"&gt;http://achau.appspot.com/js_min/cmc-core.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Minified file serving from disk - &lt;br&gt;
&lt;a href="http://achau.appspot.com/js_min_/cmc-core.js"&gt;http://achau.appspot.com/js_min_/cmc-core.js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3651123362811338649-2125673437081930009?l=austinchau.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://austinchau.blogspot.com/feeds/2125673437081930009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3651123362811338649&amp;postID=2125673437081930009' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/2125673437081930009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3651123362811338649/posts/default/2125673437081930009'/><link rel='alternate' type='text/html' href='http://austinchau.blogspot.com/2008/11/serving-javascript-minified-with.html' title='Serving minified JavaScript files with Google App Engine'/><author><name>austinchau</name><uri>http://www.blogger.com/profile/01633572775665164303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry></feed>
