<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEAERno_fSp7ImA9WhBVE0g.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209</id><updated>2013-04-19T07:25:07.445+01:00</updated><category term="NTFS" /><category term="Gaming" /><category term="jQuery" /><category term="CloudFront" /><category term="MineCon" /><category term="Minecraft" /><category term="Cowon" /><category term="Yogscast" /><category term="Amazon" /><category term="YQL" /><category term="Others" /><category term="UCI Framework" /><category term="AJAX" /><category term="Blogger" /><category term="Human" /><category term="Oneiric Ocelot" /><category term="HTTP" /><category term="Flash" /><category term="RSS" /><category term="The Hobbit" /><category term="Synaptics" /><category term="Skyrim" /><category term="Mathematics" /><category term="The Matrix" /><category term="Linux" /><category term="VPS" /><category term="TeX" /><category term="ActionScript 2" /><category term="MMO" /><category term="Ubuntu" /><category term="JavaScript" /><category term="CDN" /><category term="Missing Files Host" /><category term="HHGTTG" /><category term="UCI" /><category term="synclient" /><category term="Notch" /><category term="Books" /><title>The Wook Book</title><subtitle type="html">The Blog of a Physicist who loves Linux, Programming and Design.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.swook.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.swook.net/" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>24</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/TheWookBook" /><feedburner:info uri="thewookbook" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;C0YMQHYzeyp7ImA9WhVTEEo.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-7591000464358831353</id><published>2012-02-19T16:41:00.000Z</published><updated>2012-02-24T08:13:01.883Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-24T08:13:01.883Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="CloudFront" /><category scheme="http://www.blogger.com/atom/ns#" term="Amazon" /><title>CloudFront Invalidator | Wildcards, Resubmission and Credentials Saving</title><content type="html">While I had a lot of fun writing my &lt;a href="http://www.swook.net/p/cloudfront-invalidator.html"&gt;little tool&lt;/a&gt; up, it was not too heartening to see that my hours of work almost seemed rather useless.&lt;br /&gt;
&lt;br /&gt;
Today however, I was able to get some motivation thanks to Toby who was the first user to comment on my little tool.&lt;br /&gt;
&lt;br /&gt;
Toby had two suggestions:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Wildcard path submissions&lt;/li&gt;
&lt;li&gt;Re-submitting previous invalidations&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
I immediately set off on a mission to get them done.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Wildcard Paths&lt;/h2&gt;&lt;div&gt;The first sounded impossible at first since Amazon CloudFront does not accept wildcards as paths. I was able to add a similar feature however - searching through previous paths and matching those with the wildcard.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-1wmDxTsbTVo/T0EVgrihCTI/AAAAAAAAAOE/I8jBq90lUj0/s1600/cfi_newfeats2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="270" src="http://4.bp.blogspot.com/-1wmDxTsbTVo/T0EVgrihCTI/AAAAAAAAAOE/I8jBq90lUj0/s320/cfi_newfeats2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Here's what you can do now:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Type something like &lt;b&gt;*.js&lt;/b&gt;&amp;nbsp;and add all JavaScript files (ending with &lt;b&gt;.js&lt;/b&gt;)&amp;nbsp;from history.&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;That's it, just one step!&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;h2&gt;Credentials (Cookies) Wiping&lt;/h2&gt;&lt;div&gt;There was one aspect of my Invalidator that I was concerned about, the storing of data. I felt that users should have an easy way of opting out and wiping all traces.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Those who have used my lovely little tool before will notice a new red box on the image above. This box lets you do two things:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Enable the saving of history and credentials&lt;/li&gt;
&lt;li&gt;Disable the saving of anything and wipe all previous traces&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;If you have used the Invalidator before, the checkbox will be un-checked but the text fields will be filled in for you.&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;To wipe all data, simply leave the checkbox unchecked and refresh.&lt;/li&gt;
&lt;li&gt;To keep all data, simply click on the checkbox.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;If you are a new user, note that data will only be saved once you have made use of your credentials once (one example is clicking &lt;b&gt;Refresh&lt;/b&gt; on the &lt;b&gt;Get Invalidations&lt;/b&gt;&amp;nbsp;tab.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;h2&gt;Re-submitting Previous Invalidations&lt;/h2&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-PKeCI3oemqM/T0Eek2bU6NI/AAAAAAAAAOU/AUCcMgA_6OM/s1600/cfi_newfeats1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="272" src="http://4.bp.blogspot.com/-PKeCI3oemqM/T0Eek2bU6NI/AAAAAAAAAOU/AUCcMgA_6OM/s320/cfi_newfeats1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;This job is now much easier thanks to the glaringly obvious &lt;b&gt;Submit this Invalidation again&lt;/b&gt;&amp;nbsp;button.&lt;/div&gt;&lt;div&gt;While viewing the list of invalidations, simply click on an invalidation to get more details about it, then click &lt;b&gt;Submit this Invalidation again&lt;/b&gt;&amp;nbsp;to submit the invalidation again.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Actively re-try Get Invalidations requests on failure&lt;/h2&gt;An extra feature I added is the retrying of GET requests for Invalidation Lists.&lt;br /&gt;
&lt;br /&gt;
Depending on the status of the YQL server and/or CloudFront server, you may sometimes get failed requests. This can get annoying when you are trying to look at the list for an overview.&lt;br /&gt;
&lt;br /&gt;
I therefore made it so that the tool tries to pull the Invalidation List again in 10 seconds.&lt;br /&gt;
This behaviour is cancelled once you switch to a new tab.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Extra&lt;/h2&gt;Thanks to my hours of work wrestling with Javascript, the whole website in general is much faster as well, both to load and to switch pages.&lt;br /&gt;
(Hover your mouse over the search box for a hidden feature!)&lt;br /&gt;
&lt;br /&gt;
If you have any more suggestions, please do not hesitate to ask.&lt;br /&gt;
Do use my &lt;a href="http://www.swook.net/p/cloudfront-invalidator.html"&gt;Online CloudFront Invalidator&lt;/a&gt; and share it with your co-workers, family and friends!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=x8A0DLdzzWw:e0iO21ohUww:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=x8A0DLdzzWw:e0iO21ohUww:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=x8A0DLdzzWw:e0iO21ohUww:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=x8A0DLdzzWw:e0iO21ohUww:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/x8A0DLdzzWw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/7591000464358831353/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2012/02/cloudfront-invalidator-wildcards.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/7591000464358831353?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/7591000464358831353?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/x8A0DLdzzWw/cloudfront-invalidator-wildcards.html" title="CloudFront Invalidator | Wildcards, Resubmission and Credentials Saving" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-1wmDxTsbTVo/T0EVgrihCTI/AAAAAAAAAOE/I8jBq90lUj0/s72-c/cfi_newfeats2.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2012/02/cloudfront-invalidator-wildcards.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IDSXsyeip7ImA9WhRaEUw.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-4916796341290727911</id><published>2012-02-13T05:49:00.001Z</published><updated>2012-02-13T07:52:58.592Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-13T07:52:58.592Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Blogger" /><category scheme="http://www.blogger.com/atom/ns#" term="AJAX" /><title>Blogger | Statistics with AJAX</title><content type="html">Blogger has been receiving numerous updates in the past few months, mainly in the new templates called &lt;a href="http://buzz.blogger.com/2011/09/dynamic-views-seven-new-ways-to-share.html"&gt;Dynamic Views&lt;/a&gt;. I first rejected the option seeing how little customisability it offered, but it seems like my own template is quickly converging towards what Google's Dynamic Views is like in its core: full of JavaScript and depending on the blog's RSS feed.&lt;br /&gt;
&lt;br /&gt;
I started my journey by writing &lt;a href="http://www.swook.net/p/jquery-ajaxify-plugin.html"&gt;some JavaScript&lt;/a&gt; which would let users navigate through pages without having the page refresh fully via some AJAX calls and DOM replacement.&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-fMxK0Cy_0Uw/TziQ8EAsf4I/AAAAAAAAANw/40TtDXJGnM4/s1600/WookbarSearch.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="228" src="http://1.bp.blogspot.com/-fMxK0Cy_0Uw/TziQ8EAsf4I/AAAAAAAAANw/40TtDXJGnM4/s320/WookbarSearch.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;The instant search, with a scrollable results box&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Then I designed the top bar that you can see floating above this post and thought how nice it could be if I could have a semi-instant search (Blogger's search is quite slow). I then thought of a way which involved downloading the RSS feed for the blog, and parsing all text in the feed. I wrote an occurrence based points algorithm which allows for basic search.&lt;br /&gt;
&lt;br /&gt;
Back when I was implementing the instant search, I found that with the RSS feed in my hands, I could load full pages as well! This would allow me to flick through pages on my site almost instantly.&lt;br /&gt;
&lt;br /&gt;
This week, I got around to doing that very job, and if you navigate around a little bit, you will see that page loads are almost instant.&lt;br /&gt;
&lt;br /&gt;
There was one problem though, Blogger statistics were not getting updated...&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Pageviews Increase with Dynamic Views?&lt;/h2&gt;I remembered claims from various sources that pageviews had increased by twofolds or more with Dynamic Views enabled. Here's what I found from Google's &lt;a href="http://support.google.com/blogger/bin/answer.py?hl=en&amp;amp;answer=1662435"&gt;support page&lt;/a&gt;:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;If you enable Dynamic Views for your blog, you might notice an increase in pageviews. The reason for this is that Dynamic Views provides more specific information about actions on your blog. Specifically, every click to a post is recorded as a pageview. If a reader clicks on 10 posts, you’ll see those clicks recorded as 10 pageviews. In a traditional Blogger template, if a reader enters your blog once, they can scroll through ten blog posts in a single pageview. So while it may appear that traffic to your blog has increased, it's more likely that Blogger is simply recording more accurate data about your blog than was possible in the past.&lt;/blockquote&gt;Hmm interesting...&lt;br /&gt;
&lt;br /&gt;
Naturally, I felt that there must be some JavaScript trickery going on to allow for this to happen. Dynamic Views afterall, is mostly JavaScript!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The 'Hacking'&lt;/h2&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-IbGnevm67jE/TziT6gyFJoI/AAAAAAAAAN4/D0o6sabUYKo/s1600/DynamicViewsSource.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="107" src="http://1.bp.blogspot.com/-IbGnevm67jE/TziT6gyFJoI/AAAAAAAAAN4/D0o6sabUYKo/s200/DynamicViewsSource.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;abcdefasdjnasdlaksmdaljadxyz&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;As expected, the JavaScript source used has been compiled using Google's very own &lt;a href="http://code.google.com/closure/compiler/"&gt;closure compiler&lt;/a&gt;, and therefore has been made uglified and obfuscated. A bit of magic with the &lt;a href="http://jsbeautifier.org/"&gt;Online JavaScript Beautifier&lt;/a&gt;&amp;nbsp;alleviated that issue somewhat and I started combing through the code to see any evidence of statistics reporting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soon enough, I was able to find a piece of code which seemed to be doing the job:&lt;br /&gt;
&lt;pre class="lang-js"&gt;function Rt(a, b) {
    var c = Q.decode(b).normalize().encode();
    b &amp;amp;&amp;amp; !a.Lc[c] &amp;amp;&amp;amp; !Q.isCrossDomain(c) &amp;amp;&amp;amp; (a.Lc[c] = j, Q.decode(b).path != Q.decode(Pt).path &amp;amp;&amp;amp; setTimeout(function () {
        $.ajax({
            type: Ng,
            async: j,
            url: Q.decode(b).param(Ml, 1).param(Uq, 0).encode()
        })
    }, 1E3), window._gaq &amp;amp;&amp;amp; b &amp;amp;&amp;amp; window._gaq.push([Mj, Q.decode(b).path]))
};&lt;/pre&gt;&lt;br /&gt;
The &lt;code&gt;window._gaq &amp;&amp; b &amp;&amp; window._gaq.push([Mj, Q.decode(b).path]))&lt;/code&gt; bit is for Google Analytics. The &lt;a href="https://support.google.com/analytics/bin/answer.py?hl=en&amp;answer=1009686&amp;topic=1009685&amp;parent=1726910&amp;rd=1"&gt;documentation&lt;/a&gt; mentions that this is the way to update Analytics for dynamic sites.&lt;br /&gt;
&lt;br /&gt;
The other large piece of code can be translated into the following:&lt;br /&gt;
&lt;pre class="lang-js"&gt;setTimeout(function () {
    $.ajax({
        type: 'GET',
        async: true,
        url: document.URL+'?dynamicviews=1&amp;v=0'
    })
}, 1000)&lt;/pre&gt;This code basically submits an AJAX GET request for the new page, a second after it has been loaded.&lt;br /&gt;
&lt;br /&gt;
I had a good laugh.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;If you have not caught on yet, the solution for reporting Blogger statistics on dynamic sites, is simply requesting the page behind your backs! (The delay is to reduce impact on 'loading times')&lt;br /&gt;
&lt;br /&gt;
I have a feeling that while this is the sensible thing to do at the moment - while Dynamic Views is still in development - I find that the quick loading illudes users into thinking either that less bandwidth is being used and/or that their connection is magically fast!&lt;br /&gt;
&lt;br /&gt;
Loading the RSS feeds in the first place, is basically like loading the content of the blog in its entirety and therefore could be almost equivalent to downloading the blog. This would be awesome if you did not have to make all these requests later on while browsing the website!&lt;br /&gt;
&lt;br /&gt;
I would make a careful assumption that the appended parameters, &lt;code&gt;?dynamicviews=1&amp;v=0&lt;/code&gt; was intended to allow the script to request an empty version of the page. Unfortunately, it does not seem so at the moment.&lt;br /&gt;
&lt;br /&gt;
Ah well, for now I shall use Google's own trick.&lt;br /&gt;
&lt;br /&gt;
Oh, and if you wish to do the same, simply run the last snippet once you've updated the browser history with &lt;code&gt;History.pushState&lt;/code&gt; or equivalent.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=PWzTMTLEcqA:jowNVs9meew:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=PWzTMTLEcqA:jowNVs9meew:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=PWzTMTLEcqA:jowNVs9meew:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=PWzTMTLEcqA:jowNVs9meew:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/PWzTMTLEcqA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/4916796341290727911/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2012/02/blogger-statistics-with-ajax.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/4916796341290727911?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/4916796341290727911?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/PWzTMTLEcqA/blogger-statistics-with-ajax.html" title="Blogger | Statistics with AJAX" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-fMxK0Cy_0Uw/TziQ8EAsf4I/AAAAAAAAANw/40TtDXJGnM4/s72-c/WookbarSearch.png" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://www.swook.net/2012/02/blogger-statistics-with-ajax.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8DRXo6cSp7ImA9WhRUFEo.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-8861628581108882935</id><published>2012-01-24T09:55:00.000Z</published><updated>2012-01-25T06:44:34.419Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-25T06:44:34.419Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="Mathematics" /><category scheme="http://www.blogger.com/atom/ns#" term="TeX" /><category scheme="http://www.blogger.com/atom/ns#" term="jQuery" /><title>jQuery | Easy TeX Equations</title><content type="html">Anyone who has used &lt;span class="Apple-style-span" style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; white-space: nowrap;"&gt;T&lt;/span&gt;&lt;span style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; margin-left: -0.1667em; margin-right: -0.125em; text-transform: uppercase; vertical-align: -0.5ex; white-space: nowrap;"&gt;E&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; white-space: nowrap;"&gt;X&lt;/span&gt; will agree that no other method of typesetting mathematical equations look nicer. (Thank you &lt;a href="http://en.wikipedia.org/wiki/Donald_Knuth"&gt;Dr. Knuth&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
While &lt;span class="Apple-style-span" style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; white-space: nowrap;"&gt;T&lt;/span&gt;&lt;span style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; margin-left: -0.1667em; margin-right: -0.125em; text-transform: uppercase; vertical-align: -0.5ex; white-space: nowrap;"&gt;E&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; white-space: nowrap;"&gt;X&lt;/span&gt; typesetting can be done easily on your desktop via your favourite program based on the idea, it isn't so on the web.&lt;br /&gt;
&lt;br /&gt;
Of course, there are ways to get this done. You could use the popular &lt;a href="http://www.math.union.edu/~dpvc/jsMath/"&gt;jsMath&lt;/a&gt;, a JavaScript package which transforms your &lt;span class="Apple-style-span" style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; white-space: nowrap;"&gt;T&lt;/span&gt;&lt;span style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; margin-left: -0.1667em; margin-right: -0.125em; text-transform: uppercase; vertical-align: -0.5ex; white-space: nowrap;"&gt;E&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; white-space: nowrap;"&gt;X&lt;/span&gt; code into beautiful equations using various fonts and images. You could also use sites such as &lt;a href="http://www.codecogs.com/latex/eqneditor.php"&gt;Code Cogs&lt;/a&gt; where you can produce equation images which can then be included into your blog post. These methods however, often require extra processing client-side, and/or more time spent on producing the intended result.&lt;br /&gt;
&lt;br /&gt;
I will talk about a very easy method of doing an equivalent of the above.&lt;br /&gt;
&lt;br /&gt;
Here's the Schrödinger equation for a taster:&lt;br /&gt;
&lt;code class="tex"&gt;i\hbar\frac{\partial\psi}{\partial t} = \frac{\hbar^2}{2m}\nabla^2\psi + V(\mathbf{r})\psi&lt;/code&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The method I am about to introduce, uses one of Google's many resources: The &lt;a href="http://code.google.com/apis/chart/infographics/docs/formulas.html"&gt;Infographics Tool&lt;/a&gt;, based on the Chart API.&lt;br /&gt;
As mentioned in the API information page, all you need to do to get an equation image, is to get the image from a specific URL where Google does all of the complicated processing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Code&lt;/h2&gt;The following script does the job, assuming that you have &lt;a href="http://stackoverflow.com/questions/1458349/installing-jquery"&gt;jQuery installed&lt;/a&gt;.&lt;br /&gt;
&lt;pre class="lang-js"&gt;function TeXify () {
    $('code.tex').each(function(i, e) {
        e = $(e);
        e.replaceWith('&amp;lt;img class="tex" src="http://'+
                      +(i % 10)
                      +'.chart.apis.google.com/chart?cht=tx&amp;amp;chf=bg,s,000000&amp;amp;chl='
                      +encodeURIComponent(e.text())+'"/&amp;gt;');
    });
}
$(document).ready(TeXify);&lt;/pre&gt;&lt;br /&gt;
For example, it converts the following declaration of &lt;span class="Apple-style-span" style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; white-space: nowrap;"&gt;T&lt;/span&gt;&lt;span style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; margin-left: -0.1667em; margin-right: -0.125em; text-transform: uppercase; vertical-align: -0.5ex; white-space: nowrap;"&gt;E&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: cmr10, LMRoman10-Regular, Times, serif; font-size: 13px; line-height: 16px; white-space: nowrap;"&gt;X&lt;/span&gt; code:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;code class="tex"&amp;gt;e^{i\pi}+1=0&amp;lt;/code&amp;gt;&lt;/pre&gt;&lt;br /&gt;
into this, once the page is loaded:&lt;br /&gt;
&lt;code class="tex"&gt;e^{i\pi}+1=0&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
That small script also parallelizes the downloading of your equation images, reducing impact on page load times.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Styling&lt;/h2&gt;If you want to make your image blend in, simply declare a set of CSS styles as follows:&lt;br /&gt;
&lt;pre class="lang-css"&gt;img.tex {
  display: block;
  margin: 5px auto;
  border: none !important;
  box-shadow: 0 0 0 !important;
  background-color: transparent !important;
}&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;While this solution has the downside (as all JavaScript solutions do) that it won't work if your user does not have JavaScript enabled, it is definitely one of the fastest solutions available as you do not have to leverage client resources, but Google's, and we all know Google is blazing fast.&lt;br /&gt;
&lt;br /&gt;
Now, it's time to show off your newly prettified math pages!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Examples&lt;/h2&gt;&lt;code class="tex"&gt;E=mc^2&lt;/code&gt;&lt;pre class="lang-js"&gt;&amp;lt;code class='tex'&amp;gt;E=mc^2&amp;lt;/code&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;code class="tex"&gt;\Delta x \Delta p \geq h&lt;/code&gt;&lt;pre class="lang-js"&gt;&amp;lt;code class='tex'&amp;gt;\Delta x \Delta p \geq h&amp;lt;/code&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;code class="tex"&gt;\oint\limits_c \, \mathbf{A}\cdot\mathbf{dl} = \iint\limits_s \, \nabla\times\mathbf{A}\cdot\mathbf{ds}&lt;/code&gt;&lt;pre class="lang-js"&gt;&amp;lt;code class='tex'&amp;gt;
\oint\limits_c \, \mathbf{A}\cdot\mathbf{dl} = \iint\limits_s \, \nabla\times\mathbf{A}\cdot\mathbf{ds}
&amp;lt;/code&amp;gt;&lt;/pre&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=KIRUDUws2TM:kf6H2shH4IM:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=KIRUDUws2TM:kf6H2shH4IM:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=KIRUDUws2TM:kf6H2shH4IM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=KIRUDUws2TM:kf6H2shH4IM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/KIRUDUws2TM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/8861628581108882935/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2012/01/jquery-easy-tex-equations.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/8861628581108882935?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/8861628581108882935?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/KIRUDUws2TM/jquery-easy-tex-equations.html" title="jQuery | Easy TeX Equations" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://www.swook.net/2012/01/jquery-easy-tex-equations.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEGR3k4eyp7ImA9WhRVF00.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-2938709556397070410</id><published>2012-01-16T07:35:00.000Z</published><updated>2012-01-16T09:37:06.733Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-16T09:37:06.733Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Blogger" /><category scheme="http://www.blogger.com/atom/ns#" term="RSS" /><title>Blogger | RSS for Labels</title><content type="html">Sometimes, your reader wants to keep up to date with your tips and tricks about tweaking a Blogger blog.&lt;br /&gt;
The reader however does not want to listen to your rants about Facebook, nor about those annoying kittens.&lt;br /&gt;
All he/she wants to subscribe to is your posts which are labelled, &lt;b&gt;Blogger&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
There is a solution for that as mentioned in &lt;a href="http://support.google.com/blogger/bin/answer.py?hl=en&amp;amp;answer=53336"&gt;one of Blogger's FAQs&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The question is, how do you get these links onto your blog's label pages?&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-JQCmmyEN9bw/TxPK93bKr0I/AAAAAAAAANI/C5GWeKCiBkA/s1600/subscriberss.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="84" src="http://2.bp.blogspot.com/-JQCmmyEN9bw/TxPK93bKr0I/AAAAAAAAANI/C5GWeKCiBkA/s320/subscriberss.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;An example for the tag, &lt;b&gt;Blogger&lt;/b&gt;&amp;nbsp;(&lt;a href="http://www.swook.net/search/label/Blogger"&gt;Visit&lt;/a&gt;)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
There is a solution for this, though you do have to touch a slight bit of templating code to get it working.&lt;br /&gt;
&lt;br /&gt;
First, open up your Blog's dashboard.&lt;br /&gt;
&lt;br /&gt;
Find the &lt;b&gt;Template&lt;/b&gt;&amp;nbsp;menu and click the&amp;nbsp;&lt;b&gt;Edit HTML&lt;/b&gt;&amp;nbsp;button under your &lt;b&gt;Live on Blog&lt;/b&gt;&amp;nbsp;theme screenshot.&lt;br /&gt;
Click on the &lt;b&gt;Expand Widget Templates&lt;/b&gt;&amp;nbsp;checkbox near to the top of your dialog window.&lt;br /&gt;
&lt;br /&gt;
Search for &lt;i style="font-weight: bold;"&gt;status-msg-body&lt;/i&gt;&amp;nbsp;with the &lt;i&gt;find&lt;/i&gt;&amp;nbsp;tool which is usually available via &lt;b&gt;F3&lt;/b&gt;&amp;nbsp;or &lt;b&gt;CTRL-F&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
You should have something like this on your screen:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-PJ1_4bQ0MfY/TxPK9OpvslI/AAAAAAAAANE/JhGL3RxXwi0/s1600/editstatusmsgwidget.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="167" src="http://2.bp.blogspot.com/-PJ1_4bQ0MfY/TxPK9OpvslI/AAAAAAAAANE/JhGL3RxXwi0/s320/editstatusmsgwidget.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Currently, the code should look like the following:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;b:includable id='status-message'&amp;gt;
  &amp;lt;b:if cond='data:navMessage'&amp;gt;
  &amp;lt;div class='status-msg-wrap'&amp;gt;
    &amp;lt;div class='status-msg-body'&amp;gt;
      &amp;lt;data:navMessage/&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class='status-msg-border'&amp;gt;
      &amp;lt;div class='status-msg-bg'&amp;gt;
        &amp;lt;div class='status-msg-hidden'&amp;gt;&amp;lt;data:navMessage/&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div style='clear: both;'/&amp;gt;
  &amp;lt;/b:if&amp;gt;
&amp;lt;/b:includable&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
What we'll do is add a link to the end of the 'status message', which is the message that usually reads:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
Showing posts with label &lt;b&gt;Blogger&lt;/b&gt;. &amp;nbsp; &lt;a href="http://www.swook.net/"&gt;Show all posts&lt;/a&gt;&amp;nbsp;&lt;/blockquote&gt;
&lt;br /&gt;
We'll turn this into this:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
Showing posts with label&amp;nbsp;&lt;b&gt;Blogger&lt;/b&gt;. &amp;nbsp;&amp;nbsp;&lt;a href="http://www.swook.net/"&gt;Show all posts&lt;/a&gt;&amp;nbsp; &amp;nbsp;&lt;a href="http://www.swook.net/feeds/posts/default/-/Blogger?alt=rss"&gt;Subscribe (RSS)&lt;/a&gt;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;(Skip to the bottom to get the final code, and read on for more explanation.)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To do this, we must detect if the page is a label page.&lt;br /&gt;
We do that with the following code:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;b:if cond='data:blog.pageType == &amp;amp;quot;index&amp;amp;quot;'&amp;gt;
  &amp;lt;b:if cond='data:blog.searchLabel'&amp;gt;
  &amp;lt;/b:if&amp;gt;
&amp;lt;/b:if&amp;gt;&lt;/pre&gt;
This code checks if the page is an index of posts, and if a label has been specified.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we can construct the link:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;a class='noajax' type='application/rss+xml' expr:href='data:blog.homepageUrl + &amp;amp;quot;feeds/posts/default/-/&amp;amp;quot; + data:blog.searchLabel + &amp;amp;quot;?alt=rss&amp;amp;quot;'&amp;gt;Subscribe (RSS)&amp;lt;/a&amp;gt;&lt;/pre&gt;
Note the concatenation (adding) done between the expressions and strings - the &lt;b&gt;+&lt;/b&gt;&amp;nbsp;operator requires spaces.&lt;br /&gt;
The &lt;code&gt;class='noajax'&lt;/code&gt; bit is for &lt;a href="http://www.swook.net/2011/12/ajax-ifying-blogger-no-1-flickerless.html"&gt;Ajaxified Blogger blogs&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is what it should look like once you've put everything together:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;b:includable id='status-message'&amp;gt;
  &amp;lt;b:if cond='data:navMessage'&amp;gt;
  &amp;lt;div class='status-msg-wrap'&amp;gt;
    &amp;lt;div class='status-msg-body'&amp;gt;
      &amp;lt;data:navMessage/&amp;gt;
      &amp;lt;b:if cond='data:blog.pageType == &amp;amp;quot;index&amp;amp;quot;'&amp;gt;
        &amp;lt;b:if cond='data:blog.searchLabel'&amp;gt;
          &amp;lt;a class='noajax' type='application/rss+xml' expr:href='data:blog.homepageUrl + &amp;amp;quot;feeds/posts/default/-/&amp;amp;quot; + data:blog.searchLabel + &amp;amp;quot;?alt=rss&amp;amp;quot;'&amp;gt;Subscribe (RSS)&amp;lt;/a&amp;gt;
        &amp;lt;/b:if&amp;gt;
      &amp;lt;/b:if&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class='status-msg-border'&amp;gt;
      &amp;lt;div class='status-msg-bg'&amp;gt;
        &amp;lt;div class='status-msg-hidden'&amp;gt;&amp;lt;data:navMessage/&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div style='clear: both;'/&amp;gt;
  &amp;lt;/b:if&amp;gt;
&amp;lt;/b:includable&amp;gt;&lt;/pre&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=13uFgu_OHdY:CfjQOk8CMwQ:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=13uFgu_OHdY:CfjQOk8CMwQ:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=13uFgu_OHdY:CfjQOk8CMwQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=13uFgu_OHdY:CfjQOk8CMwQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/13uFgu_OHdY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/2938709556397070410/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2012/01/blogger-rss-for-labels.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/2938709556397070410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/2938709556397070410?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/13uFgu_OHdY/blogger-rss-for-labels.html" title="Blogger | RSS for Labels" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-JQCmmyEN9bw/TxPK93bKr0I/AAAAAAAAANI/C5GWeKCiBkA/s72-c/subscriberss.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://www.swook.net/2012/01/blogger-rss-for-labels.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YFQ34_eSp7ImA9WhRVF00.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-7481226504211022956</id><published>2012-01-15T11:52:00.000Z</published><updated>2012-01-16T10:18:32.041Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-16T10:18:32.041Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="The Hobbit" /><title>The Naming of Sting</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-IWY0l8vSAs8/TxP5VKcINaI/AAAAAAAAANU/5t7kj-iHc1U/s1600/thehobbit-thenamingofsting.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="266" src="http://3.bp.blogspot.com/-IWY0l8vSAs8/TxP5VKcINaI/AAAAAAAAANU/5t7kj-iHc1U/s400/thehobbit-thenamingofsting.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span class="Apple-style-span" style="color: #444444; font-family: Georgia, 'Times New Roman', serif;"&gt;There was the usual dim grey light of the forest-day about him when he came to his senses. The spider lay dead beside him, and his sword-blade was stained black. Somehow the killing of the giant spider, all alone by himself in the dark without the help of the wizard or the dwarves or of anyone else, made a great difference to Mr. Baggins. He felt a different person, and much fiercer and bolder in spite of an empty stomach, as he wiped his sword on the grass and put it back into its sheath.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span class="Apple-style-span" style="color: #444444; font-family: Georgia, 'Times New Roman', serif;"&gt;“I will give you a name,” he said to it, “and I shall call you Sting.”&lt;/span&gt;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Source: &lt;a href="http://www.theonering.net/torwp/2012/01/14/52695-la-times-new-pic-of-martin-freeman-as-bilbo-surfaces-the-naming-of-sting/"&gt;http://www.theonering.net/torwp/2012/01/14/52695-la-times-new-pic-of-martin-freeman-as-bilbo-surfaces-the-naming-of-sting/&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=HO4RREPCC-4:nq330j4-_g8:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=HO4RREPCC-4:nq330j4-_g8:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=HO4RREPCC-4:nq330j4-_g8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=HO4RREPCC-4:nq330j4-_g8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/HO4RREPCC-4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/7481226504211022956/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2012/01/naming-of-sting.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/7481226504211022956?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/7481226504211022956?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/HO4RREPCC-4/naming-of-sting.html" title="The Naming of Sting" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-IWY0l8vSAs8/TxP5VKcINaI/AAAAAAAAANU/5t7kj-iHc1U/s72-c/thehobbit-thenamingofsting.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2012/01/naming-of-sting.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUHSXg8eyp7ImA9WhRWEUg.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-5095189247050018369</id><published>2011-12-15T17:45:00.000Z</published><updated>2011-12-29T10:23:58.673Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-29T10:23:58.673Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="AJAX" /><category scheme="http://www.blogger.com/atom/ns#" term="CloudFront" /><category scheme="http://www.blogger.com/atom/ns#" term="YQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Amazon" /><category scheme="http://www.blogger.com/atom/ns#" term="jQuery" /><title>It's here! The first Online CloudFront Invalidator</title><content type="html">Two blog posts ago, I talked about my discovery of the Amazon CloudFront invalidation service and how I decided to go about getting a tool made for it using JavaScript. Read my early musings &lt;a href="http://www.swook.net/2011/12/js-creating-cloudfront-authorization.html"&gt;over here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
After much deliberation and man-hours, I have finally completed what I set out to do when I entered the JavaScript ranges, armed with a YQL guide published by Yahoo.&lt;br /&gt;
&lt;br /&gt;
I present to you, the &lt;a href="http://www.swook.net/p/cloudfront-invalidator.html"&gt;Online CloudFront Invalidator&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-gtD160dS_cE/TusYRRg0d6I/AAAAAAAAAJc/7Xv3uuW4S8c/s1600/oci.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="288" src="http://2.bp.blogspot.com/-gtD160dS_cE/TusYRRg0d6I/AAAAAAAAAJc/7Xv3uuW4S8c/s320/oci.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Read on for more information...&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;YQL, what?&lt;/h2&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-1rdiwf4lFxw/TusX2WL0xxI/AAAAAAAAAJU/J0K31oQwe70/s1600/ydn.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="27" src="http://4.bp.blogspot.com/-1rdiwf4lFxw/TusX2WL0xxI/AAAAAAAAAJU/J0K31oQwe70/s200/ydn.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Thank you Yahoo!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;If you have ever come across &lt;a href="http://en.wikipedia.org/wiki/SQL"&gt;SQL&lt;/a&gt;, the name will ring a bell. YQL is basically what SQL is with the difference being the actual data tables which you can access.&lt;br /&gt;
&lt;br /&gt;
As the slogan, "Query the Web!" implies, YQL was designed to allow for developers to access and manipulate data from many different &lt;a href="http://developer.yahoo.com/yql/console/"&gt;available tables&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
To allow for this 'querying', YQL has to perform various HTTP requests. These requests include GET/POST/PUT requests which are usually done using server-side web programming with languages such as PHP.&lt;br /&gt;
&lt;br /&gt;
With effective use of &lt;a href="http://www.datatables.org/"&gt;Open Data Tables&lt;/a&gt; however, one can create their own tables to perform GET/POST requests. This is amazing as it allows one to perform these requests via JavaScript. These requests are usually impossible due to the &lt;a href="https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript"&gt;Same Origin Policy&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
You might be wondering how I can receive and send data to the YQL servers in the first place. This is because the communication is done using &lt;a href="http://en.wikipedia.org/wiki/JSONP"&gt;JSONP&lt;/a&gt;, which was created specifically for cross-domain communication.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://cdn.swook.net/js/cfInval.xml"&gt;Here's the open data table&lt;/a&gt; I created for my purpose. I won't go into the specifics but you can find out how everything works from the &lt;a href="http://developer.yahoo.com/yql/guide/yql-opentables-chapter.html"&gt;useful documentation&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Why YQL?&lt;/h2&gt;&lt;blockquote&gt;"Okay great, but why didn't you simply create a server-side proxy? The code already exists &lt;a href="http://www.subchild.com/2010/09/17/amazon-cloudfront-php-invalidator/"&gt;here (for PHP)&lt;/a&gt;, &lt;a href="http://tomatohater.com/2010/10/22/cloudfront-object-invalidation-python/"&gt;here (for Python)&lt;/a&gt;, &lt;a href="http://blog.confabulus.com/2011/05/13/cloudfront-invalidation-from-ruby/"&gt;here (for Ruby)&lt;/a&gt; and probably at several places more so why re-invent the wheel?"&lt;/blockquote&gt;The answer is performance, security, and scalability.&lt;br /&gt;
&lt;br /&gt;
By not relying on my &lt;a href="http://www.swook.net/2011/10/blogger-374-vps-speedy-mirror-cdn-bliss.html"&gt;$3.74/mo VPS&lt;/a&gt;, I make sure that the tool does not slow down due to the number of users using it. Also, query times are significantly increased as it is handled by Yahoo!'s network. This increases scalability and performance.&lt;br /&gt;
&lt;br /&gt;
Security is greatly increased since all code is open to you, the user. All handling of data is transparent and you can easily see how sensitive credentials are dealt with on the client, and the signature, sent only to Yahoo!'s YQL server. If any data was being sent to a proxy server of mine, it would be difficult for users to determine whether I am leaking sensitive information.&lt;br /&gt;
&lt;br /&gt;
However, even after implementing client-side signature generation, YQL querying and HTTPS encoded requests, I was &lt;a href="https://forums.aws.amazon.com/thread.jspa?threadID=82416#jive-message-301797"&gt;accused of trying to steal user credentials&lt;/a&gt;. Ah well...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Convenient Features&lt;/h2&gt;My invalidator has a few features for your convenience.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;When viewing the &lt;b&gt;Get Invalidations&lt;/b&gt; tab, the invalidation list will be reloaded every 30 seconds if there are invalidations in progress.&lt;/li&gt;
&lt;li&gt;Your access key, secret key and distribution ID will be filled in for you when you visit the page again, after having performed an invalidation GET or POST request using your details.&lt;/li&gt;
&lt;li&gt;Also, file names which have been invalidated before are cached, letting you add them back to your new request easily.&lt;/li&gt;
&lt;li&gt;Amazon states that you have to provide correct paths which start with &lt;b&gt;/&lt;/b&gt;. With the Online CloudFront Invalidator, you can paste in full URLs as well as paths which have invalid characters such as spaces in them.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that you know that the Online CloudFront Invalidator is safe and easy to use, &lt;a href="http://www.swook.net/p/cloudfront-invalidator.html"&gt;what are you waiting for&lt;/a&gt;?&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=tEmdZQNC9ck:0xgbmaCoNmM:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=tEmdZQNC9ck:0xgbmaCoNmM:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=tEmdZQNC9ck:0xgbmaCoNmM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=tEmdZQNC9ck:0xgbmaCoNmM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/tEmdZQNC9ck" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/5095189247050018369/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/12/its-here-first-online-cloudfront.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/5095189247050018369?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/5095189247050018369?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/tEmdZQNC9ck/its-here-first-online-cloudfront.html" title="It's here! The first Online CloudFront Invalidator" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-gtD160dS_cE/TusYRRg0d6I/AAAAAAAAAJc/7Xv3uuW4S8c/s72-c/oci.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/12/its-here-first-online-cloudfront.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08FSHw8eCp7ImA9WhRXEko.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-2208124210640893471</id><published>2011-12-15T08:37:00.000Z</published><updated>2011-12-19T07:30:19.270Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-19T07:30:19.270Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ActionScript 2" /><category scheme="http://www.blogger.com/atom/ns#" term="Flash" /><title>AS2 | Long Click Detection (Fixed)</title><content type="html">A few weeks ago, I blogged about writing an easy-to-use long click detection for Flash ActionScript 2.&lt;br /&gt;
You can find the post &lt;a href="http://www.swook.net/2011/11/as2-long-click-detection.html"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Bug&lt;/h2&gt;Recently &lt;a href="http://kizune.square7.de/"&gt;Kizune&lt;/a&gt;, a respected Cowon UCI developer and designer informed me that my implementation had a bug which rendered it useless.&lt;br /&gt;
&lt;br /&gt;
What happens is that when you apply my code, only the highest level parent MovieClips respond to &lt;code&gt;onPress&lt;/code&gt;, &lt;code&gt;onDragOut&lt;/code&gt;, and &lt;code&gt;onRelease&lt;/code&gt; events.&lt;br /&gt;
&lt;br /&gt;
This occurs due to the events being assigned to all &lt;code&gt;MovieClip&lt;/code&gt;s via the &lt;code&gt;MovieClip.prototype.addProperty&lt;/code&gt; calls.&lt;br /&gt;
&lt;br /&gt;
In ActionScript 2, MovieClips only become clickable when a &lt;code&gt;MovieClip.onPress&lt;/code&gt; function is defined. If it is defined for a parent MovieClip, further declarations of the same event for child MovieClips do not work. Simply because the parent takes priority.&lt;br /&gt;
My clever code had defined replacement methods for all these events... for all MovieClips.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Fix&lt;/h2&gt;The fix is simple, don't assign the replacement event listeners via &lt;a href="http://www.swook.net/2011/11/as2-objectaddproperty.html"&gt;&lt;code&gt;addProperty&lt;/code&gt;&lt;/a&gt; to all &lt;code&gt;MovieClip&lt;/code&gt;s when they don't need it!&lt;br /&gt;
Only hijack the events when needed, ie. when &lt;code&gt;.onShortClick&lt;/code&gt; or &lt;code&gt;.onLongClick&lt;/code&gt; is registered.&lt;br /&gt;
&lt;br /&gt;
The following code should fix the issue:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="lang-as"&gt;var LongClickHandler = {};
LongClickHandler.DELAY = 350;
LongClickHandler.INTERVAL = 150;

LongClickHandler.Init = function ( func ):Void {
    // NOTE: this == MovieClip
    if ( this.LongClick != undefined ) return;

    if ( this.onPress ) this.onPress_ = this.onPress;
    this.addProperty( "onPress",
                      function ():Function {
                          return LongClickHandler.onPress;
                      },
                      function ( func:Function ):Void {
                          this.onPress_ = func;
                      } );

    if ( this.onDragOut ) this.onDragOut_= this.onDragOut;
    this.addProperty( "onDragOut",
                      function ():Function {
                          return LongClickHandler.onDragOut;
                      },
                      function ( func:Function ):Void {
                          this.onDragOut_ = func;
                      } );

    if ( this.onRelease ) this.onRelease_ = this.onRelease;
    this.addProperty( "onRelease",
                      function ():Function {
                          return LongClickHandler.onRelease;
                      },
                      function ( func:Function ):Void {
                          this.onRelease_ = func;
                      } );

    this.LongClick = {};
    this.LongClick.mc = this;
    this.LongClick.onEnterFrame = LongClickHandler.onEnterFrame;
}

LongClickHandler.cleanUp = function ():Void {
    // NOTE: this == MovieClip
    delete this.LongClick.last_t;
    delete this.LongClick.trail_done;
    MovieClip.removeListener( this.LongClick );
}

LongClickHandler.onEnterFrame = function ():Void {
    // NOTE: this == MovieClip.LongClick
    var dt:Number = Time.Ticks - this.start_t;
    if ( this.last_t ) {
        var ivl:Number = LongClickHandler.INTERVAL;
        if ( !this.trail_done ) {
            var inc:Number = ( ivl * 100000 / dt / dt ) &gt;&gt; 0;
            if ( inc &lt; 10 ) this.trail_done = true;
            ivl += inc;
        }

        dt = Time.Ticks - this.last_t;
        if ( dt &gt;= ivl ) {
            this.last_t = Time.Ticks;
            this.func_long.call( this.mc );
        }
        return;
    }
    else if ( dt &gt; LongClickHandler.DELAY ) {
        this.last_t = Time.Ticks;
        this.func_long.call( this.mc );
    }
}


// Replace onPress
LongClickHandler.onPress = function ():Void {
    // NOTE: this == MovieClip
    if ( this.LongClick.func_long ) {
        this.LongClick.start_t = Time.Ticks;
        MovieClip.addListener( this.LongClick );
    }
    this.onPress_();
}


// Replace onDragOut
LongClickHandler.onDragOut = function ():Void {
    // NOTE: this == MovieClip
    LongClickHandler.cleanUp.call( this );
    this.onDragOut_();
}


// Replace onRelease
LongClickHandler.onRelease = function ():Void {
    // NOTE: this == MovieClip
    if ( !this.LongClick.last_t ) this.LongClick.func_short();
    LongClickHandler.cleanUp.call( this );
    this.onRelease_();
}


MovieClip.prototype.addProperty( "onLongClick",
                                 function ():Function {
                                     return this.LongClick.func_long;
                                 },
                                 function ( func:Function ):Void {
                                     LongClickHandler.Init.call( this );
                                     this.LongClick.func_long = func;
                                 } );

MovieClip.prototype.addProperty( "onShortClick",
                                 function ():Function {
                                     return this.LongClick.func_short;
                                 },
                                 function ( func:Function ):Void {
                                     LongClickHandler.Init.call( this );
                                     this.LongClick.func_short = func;
                                 } );
&lt;/pre&gt;&lt;br /&gt;
Usage of the code has not changed and can be found in my &lt;a href="http://www.swook.net/2011/11/as2-long-click-detection.html"&gt;original post&lt;/a&gt;.&lt;br /&gt;
If there are any further problems or bugs, please do not hesitate to comment below!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Lesson Learnt&lt;/h2&gt;&lt;code&gt;MovieClip.prototype&lt;/code&gt; is evil. Be careful when you mess with it!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=HyBvI6FeUhI:RSuZPKWQMq0:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=HyBvI6FeUhI:RSuZPKWQMq0:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=HyBvI6FeUhI:RSuZPKWQMq0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=HyBvI6FeUhI:RSuZPKWQMq0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/HyBvI6FeUhI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/2208124210640893471/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/12/as2-long-click-detection-fixed.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/2208124210640893471?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/2208124210640893471?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/HyBvI6FeUhI/as2-long-click-detection-fixed.html" title="AS2 | Long Click Detection (Fixed)" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/12/as2-long-click-detection-fixed.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcEQHY-fCp7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-501763738200761023</id><published>2011-12-08T04:41:00.001Z</published><updated>2011-12-08T17:06:41.854Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T17:06:41.854Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="CloudFront" /><category scheme="http://www.blogger.com/atom/ns#" term="Amazon" /><title>JS | Creating a CloudFront Authorization Signature</title><content type="html">I started using Amazon CloudFront to serve some static files for my blog... and I noticed that there was no easy way for me to 'refresh' files which have been copied to Edge locations.&lt;br /&gt;
&lt;br /&gt;
The CloudFront management console offered me the most minimal options of adding and removing distributions and nowhere could I find a nice little button which looked remotely like it would let me reload/refresh my files.&lt;br /&gt;
&lt;br /&gt;
Then I stumbled across &lt;a href="http://aws.amazon.com/cloudfront/faqs/#Is_there_a_limit_to_the_number_of_invalidation_requests"&gt;Amazon CloudFront Invalidation&lt;/a&gt; and 'Oh Joy! There MUST be an online invalidator somewhere!' was what I thought, only to be proven wrong by the almighty Google seconds later.&lt;br /&gt;
&lt;br /&gt;
But I told myself that it's all alright since there's an &lt;a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html"&gt;API&lt;/a&gt;. Someone must have written an implementation of it!&lt;br /&gt;
Yes, there were a few but all of them were commandline tools, written in &lt;a href="http://blog.confabulus.com/2011/05/13/cloudfront-invalidation-from-ruby/"&gt;Ruby&lt;/a&gt;, &lt;a href="http://www.subchild.com/2010/09/17/amazon-cloudfront-php-invalidator/"&gt;PHP&lt;/a&gt;, and &lt;a href="http://tomatohater.com/2010/10/22/cloudfront-object-invalidation-python/"&gt;Python&lt;/a&gt;. I wanted an online invalidator and that could be easily achieved by using these tools with them being hosted on a server. I had to think twice about that though since if I am right and there are thousands of people who'd want to use an online invalidator, my little VPS would simply keel over and die. It wasn't a sustainable idea.&lt;br /&gt;
&lt;br /&gt;
Then I turned to look towards the mighty hills of JavaScript-dom and lo there was a solution to satisfy my needs. The lush green hills also bordered the busy trading posts of &lt;a href="http://developer.yahoo.com/yql/"&gt;YQL&lt;/a&gt;, which let JavaScript fairies talk to other JavaScript fairies from different domains. Everything was going to be alright.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Authorization Signature&lt;/h2&gt;To communicate with Amazon CloudFront, one must generate a &lt;a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?RESTAuthentication.html"&gt;signature&lt;/a&gt; with which Amazon can verify that you are indeed who you claim to be.&lt;br /&gt;
&lt;br /&gt;
This requires you to have a few details:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Access Key ID&lt;/li&gt;
&lt;li&gt;Secret Access Key&lt;/li&gt;
&lt;/ol&gt;both, which could be created and acquired at the &lt;a href="https://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key"&gt;AWS account management page&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The instructions are &lt;a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/RESTAuthentication.html#Signature"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Doing it in JavaScript&lt;/h2&gt;After reading through carefully, it was clear what I had to do. I was to send along a header containing a date in GMT, provided by &lt;code&gt;new Date().toGMTString()&lt;/code&gt; as well as an authorization header formatted in the following way:&lt;br /&gt;
&lt;pre class="highlight"&gt;AWS [Access Key ID]:[Base64(HMAC-SHA1(UTF8([Date String]), UTF8([Secret Access Key])))]&lt;/pre&gt;&lt;br /&gt;
I looked up a JavaScript encoding libraries for &lt;a href="http://code.google.com/p/crypto-js/#HMAC-SHA1"&gt;HMAC-SHA1&lt;/a&gt;, &lt;a href="http://farhadi.ir/works/utf8"&gt;UTF8&lt;/a&gt; and ended up with the following signature code:&lt;br /&gt;
&lt;pre class="lang-js"&gt;date = 'Thu, 14 Aug 2008 17:08:48 GMT';
secretkey = '/Ml61L9VxlzloZ091/lkqVV5X1/YvaJtI9hW4Wr9';
signature = btoa(Crypto.HMAC(Crypto.SHA1, utf8Encode(date), utf8Encode(secretkey)));&lt;/pre&gt;The code however, did not yield the correct signature! The used sample keys from the &lt;a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?RESTAuthentication.html"&gt;documentation&lt;/a&gt; should have yielded &lt;code&gt;4cP0hCJsdCxTJ1jPXo7+e/YSu0g=&lt;/code&gt; but was instead yielding &lt;code&gt;ZTFjM2Y0ODQyMjZjNzQyYzUzMjc1OGNmNWU4ZWZlN2JmNjEyYmI0OA==&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
I scratched my head, then scratched it again.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-JOUdEbnckes/TuCNPbk1tNI/AAAAAAAAAI4/ikJKBWxMxxA/s1600/Amazon.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-JOUdEbnckes/TuCNPbk1tNI/AAAAAAAAAI4/ikJKBWxMxxA/s1600/Amazon.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Smirk!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;I could feel Amazon smirk at me from America.&lt;br /&gt;
&lt;br /&gt;
At first, I was convinced that Amazon was wrong. Their example could not be right!&lt;br /&gt;
I tried out doing the encoding in &lt;a href="http://ipython.org/"&gt;IPython&lt;/a&gt; and it was the same as what I had got. I tried using online hmac tools, base64 tools and the result was always consistent.&lt;br /&gt;
&lt;br /&gt;
Then I found &lt;a href="http://insidepro.com/hashes.php"&gt;InsidePro&lt;/a&gt;. I &lt;a href="http://insidepro.com/hashes.php?lang=eng&amp;amp;T1=Thu,%2014%20Aug%202008%2017:08:48%20GMT&amp;amp;T2=/Ml61L9VxlzloZ091/lkqVV5X1/YvaJtI9hW4Wr9"&gt;keyed in the sample key and date&lt;/a&gt; and lo, there were hundreds of hashes for me to observe.&lt;br /&gt;
I quickly scrolled down to the line marked with &lt;b&gt;SHA-1(HMAC)&lt;/b&gt; and found 4 unique hashes, the second one being equal to Amazon's result and the first being equal to mine. The key mentioned that it was hashed to base 64 and nothing more.&lt;br /&gt;
But then, maybe the hashing in JavaScript was being faulty, I should try putting my calculated hash into the generator! &lt;a href="http://insidepro.com/hashes.php?lang=eng&amp;amp;T1=e1c3f484226c742c532758cf5e8efe7bf612bb48"&gt;And so I did&lt;/a&gt;, but with the hash produced by Crypto's HMAC-SHA1 encoding.&lt;br /&gt;
&lt;br /&gt;
To my surprise, Amazon's result was staring at me in the face, down at the bottom of the page on the row marked &lt;b&gt;Hex -&amp;gt; Base64&lt;/b&gt;. Oh dear... I had spent hours searching for a solution and that's it?&lt;br /&gt;
&lt;br /&gt;
If you haven't noticed yet, all I had to do was to add an extra call to decode my hmac-sha1 hash from &lt;a href="http://stackoverflow.com/questions/3745666/how-to-convert-from-hex-to-ascii-in-javascript"&gt;hex string to ascii string&lt;/a&gt; then encode it to base 64 using JavaScript's &lt;code&gt;btoa()&lt;/code&gt;.&lt;br /&gt;
The final code is something like this:&lt;br /&gt;
&lt;pre class="lang-js"&gt;function hex2a(hex) {
    var str = '';
    for (var i = 0; i &amp;lt; hex.length; i += 2)
        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
    return str;
}

date = 'Thu, 14 Aug 2008 17:08:48 GMT';
secretkey = '/Ml61L9VxlzloZ091/lkqVV5X1/YvaJtI9hW4Wr9';
signature = btoa(hex2a(Crypto.HMAC(Crypto.SHA1, utf8Encode(date), utf8Encode(secretkey))));&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Moral of the Story&lt;/h2&gt;The moral of the story?&lt;br /&gt;
Check what your hashing function outputs and what your next one takes.&lt;br /&gt;
&lt;br /&gt;
This is especially important with JavaScript since the encoding functions are not native and thus implementations vary.&lt;br /&gt;
In this scenario, only the base 64 function, &lt;code&gt;btoa()&lt;/code&gt; is native.&lt;br /&gt;
This whole problem was caused due to the hash function for HMAC-SHA1 returning the hexadecimal as a string and not as a JavaScript hexadecimal.    &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Code Used&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/crypto-js/#HMAC-SHA1"&gt;HMAC-SHA1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://farhadi.ir/works/utf8"&gt;UTF8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/3745666/how-to-convert-from-hex-to-ascii-in-javascript"&gt;hex string to ascii string&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=Zwe-qQz4NZo:DQDTK7pDXu8:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=Zwe-qQz4NZo:DQDTK7pDXu8:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=Zwe-qQz4NZo:DQDTK7pDXu8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=Zwe-qQz4NZo:DQDTK7pDXu8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/Zwe-qQz4NZo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/501763738200761023/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/12/js-creating-cloudfront-authorization.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/501763738200761023?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/501763738200761023?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/Zwe-qQz4NZo/js-creating-cloudfront-authorization.html" title="JS | Creating a CloudFront Authorization Signature" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-JOUdEbnckes/TuCNPbk1tNI/AAAAAAAAAI4/ikJKBWxMxxA/s72-c/Amazon.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/12/js-creating-cloudfront-authorization.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcGSH49cSp7ImA9WhVQFEg.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-5444103811470439863</id><published>2011-12-02T11:32:00.001Z</published><updated>2012-04-03T11:47:09.069+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-03T11:47:09.069+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="Blogger" /><category scheme="http://www.blogger.com/atom/ns#" term="AJAX" /><category scheme="http://www.blogger.com/atom/ns#" term="jQuery" /><title>Ajax-ifying Blogger No. 2: Keeping content updated</title><content type="html">As mentioned in &lt;a href="http://www.swook.net/2011/12/ajax-ifying-blogger-no-1-flickerless.html"&gt;my first post&lt;/a&gt; about Ajax-ifying Blogger, I talked about &lt;a href="http://www.swook.net/p/jquery-ajaxify-plugin.html"&gt;my jQuery plugin&lt;/a&gt; which lets you load your blog pages without a flicker. I also talked about how different components needed to be updated or reloaded manually.&lt;br /&gt;
&lt;br /&gt;
I'll now talk about the components which caused problems, and how I dealt with them.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;jquery.ajaxify.js&lt;/h2&gt;If you don't know about this plugin, you can visit &lt;a href="http://www.swook.net/p/jquery-ajaxify-plugin.html"&gt;the plugin page&lt;/a&gt; and/or read &lt;a href="http://www.swook.net/2011/12/ajax-ifying-blogger-no-1-flickerless.html"&gt;my post&lt;/a&gt; about its development.&lt;br /&gt;
&lt;br /&gt;
Install it in the following way:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;b:if cond='data:blog.isMobile'&amp;gt;
&amp;lt;b:else/&amp;gt;
  &amp;lt;script src='https://raw.github.com/swook/jquery-ajaxify-plugin/master/jquery.ajaxify.min.js' type='text/javascript'/&amp;gt;
&amp;lt;/b:if&amp;gt;&lt;/pre&gt;This is to avoid problems on mobile phones, where using AJAX would be slower.&lt;br /&gt;
&lt;br /&gt;
Here's my configuration:&lt;br /&gt;
&lt;pre class="lang-js"&gt;$.Ajaxify.container = [
    '#Blog1',          // Main Column Content
    '.Label',          // Labels
    '#topbar-social'   // The Social icons in my custom top bar (Will be dealt with in No.3)
];
&lt;/pre&gt;&lt;br /&gt;
This isn't all though and I'll be doing a few more tricks to keep your site consistent.&lt;br /&gt;
I'll be using jQuery and that shouldn't be a problem since you'd be using my &lt;a href="http://www.swook.net/p/jquery-ajaxify-plugin.html"&gt;jQuery plugin&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;"View Mobile Version" Link&lt;/h2&gt;In your template, there is the following code:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;b:if cond='data:mobileLinkUrl'&amp;gt;
  &amp;lt;div class='blog-mobile-link'&amp;gt;
    &amp;lt;a expr:href='data:mobileLinkUrl'&amp;gt;&amp;lt;data:mobileLinkMsg/&amp;gt;&amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/b:if&amp;gt;&lt;/pre&gt;&lt;br /&gt;
add the &lt;code&gt;noajax&lt;/code&gt; class to the link:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;b:if cond='data:mobileLinkUrl'&amp;gt;
  &amp;lt;div class='blog-mobile-link'&amp;gt;
    &amp;lt;a&amp;nbsp;class='noajax' expr:href='data:mobileLinkUrl'&amp;gt;&amp;lt;data:mobileLinkMsg/&amp;gt;&amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/b:if&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
This allows for a refresh when a user clicks on the button, 'View Mobile Version'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Tab bar&lt;/h2&gt;Your tab bar displays in a different way depending on whether you are on a page which is listed on the bar.&lt;br /&gt;
The bar could easily be updated by simply adding the tab bar identifier, &lt;code&gt;.tabs-inner&lt;/code&gt; to the list of selectors which you can see in my configuration.&lt;br /&gt;
This method however, can show un-necessary flickers.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="lang-js"&gt;$.Ajaxify.pageChange(function() {
    $('.tabs-inner li').each(function() {
        var target = $('a',$(this)).attr('href');
        if (target) {
            if (target == document.location.href)
                $(this).addClass('selected');
            else $(this).removeClass('selected');
        }
    });
});
&lt;/pre&gt;This snippet updates the links' classes to show them as being selected or not depending on the new page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Lightbox&lt;/h2&gt;Do you use lightboxes for your images?&lt;br /&gt;
You can enable them at your Blogger panel in &lt;code&gt;Settings - Posts and comments - Showcase images with Lightbox&lt;/code&gt;. Lightboxes let your user view a post's image enlarged, in a nice full screen overlay.&lt;br /&gt;
&lt;br /&gt;
Update them with this:&lt;br /&gt;
&lt;pre class="lang-js"&gt;$.Ajaxify.pageChange(function() {
    _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', null, document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'http://www.blogger.com/static/v1/jsbin/1146871538-lbx_en-GB.js', 'lightboxCssUrl': 'http://www.blogger.com/static/v1/v-css/3429760955-lightbox_bundle.css'}, 'displayModeFull'));
});
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Google Analytics&lt;/h2&gt;Use Google Analytics?&lt;br /&gt;
Check that your Analytics code looks like this:&lt;br /&gt;
&lt;pre class="lang-js"&gt;var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-22477387-1']);
_gaq.push(['_trackPageview']);
(function() {
    var ga = document.createElement('script');
    ga.type = 'text/javascript';
    ga.async = true;
    ga.src = (document.location.protocol == 'https:' ?
             'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(ga, s);
})();
&lt;/pre&gt;The &lt;code&gt;_gaq.push(['_trackPageview']);&lt;/code&gt; line is crucial.&lt;br /&gt;
&lt;br /&gt;
If it isn't like the above, find&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;b:include data='blog' name='google-analytics'/&amp;gt;
&lt;/pre&gt;in &lt;code&gt;Template - Edit HTML&lt;/code&gt; and remove it then place the custom analytics code into a JavaScript file or snippet of your choice.&lt;br /&gt;
Remember to use your own Analytics Account ID! (ie. Modify the snippet above so that it reports to your account!)&lt;br /&gt;
&lt;br /&gt;
Then enter this into your JavaScript:&lt;br /&gt;
&lt;pre class="lang-js"&gt;$.Ajaxify.pageChange(function() {
    _gaq.push(['_trackPageview', $.Ajaxify.current_url.relative]);
});
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Google AdSense&lt;/h2&gt;I would post my solution which works but I will wait for Google's approval, which I have asked via e-mail a few days ago.&lt;br /&gt;
This solution lets you refresh your ad depending on context and does not require manual declaration of keywords like &lt;a href="http://www.jguru.com/forums/view.jsp?EID=1305379"&gt;this solution&lt;/a&gt;.&lt;br /&gt;
I was very excited when I found my solution but unfortunately it will have to wait!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Comment Form&lt;/h2&gt;&lt;em&gt;Note: Does not work with latest threaded comments&lt;/em&gt;&lt;br /&gt;
You'll need to add this to get your comment form working:&lt;br /&gt;
&lt;pre class="lang-js"&gt;var commentShown = false;

// Initiate comment form only when about to be visible
$(window).bind('scroll', function(){
    var pos = $(this).scrollTop();
    if (commentShown) return;
    if (pos &amp;lt; ($('.comment-form').offset().top-800)) return;
    if (($('.comment-form &amp;gt; iframe').attr('src') &amp;gt; '') || ($('.comment-form').length == 0)) commentShown = true;
    else BLOG_CMT_createIframe('http://www.blogger.com/rpc_relay.html', '16182952069663634409');
});

$(document).ready(function() {
    commentShown = false;
    if ($('.comment-form').length == 0) commentShown = true;
});
$.Ajaxify.pageChange(function() {
    commentShown = false;
    if ($('.comment-form').length == 0) commentShown = true;
    else {
        // Comment iFrame
        var jsO, target;
        jsO = document.createElement("script");
        jsO.type = "text/javascript";
        jsO.src = 'http://www.blogger.com/static/v1/jsbin/884844084-comment_from_post_iframe.js';
        target = document.getElementsByClassName('comment-form');
        for (var i = 0; i &amp;lt; target.length; i++) {
            target[i].appendChild(jsO);
        }
    }
});
&lt;/pre&gt;This snippet checks if a comment form exists, then loads it only when your user scrolls down near to the comment form. You will have to tweak it though the tweak is simple. Visit a page with your comment form showing, right click and select 'View Source' or similar. Press CTRL-F and find a place where you see something like the following:&lt;br /&gt;
&lt;pre class="lang-html"&gt;&amp;lt;script type="text/javascript" src="http://www.blogger.com/static/v1/jsbin/884844084-comment_from_post_iframe.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type='text/javascript'&amp;gt;
    BLOG_CMT_createIframe('http://www.blogger.com/rpc_relay.html', '16182952069663634409');
&amp;lt;/script&amp;gt;
&lt;/pre&gt;Get the massive numbers, &lt;b&gt;884844084&lt;/b&gt; and &lt;b&gt;16182952069663634409&lt;/b&gt; and replace accordingly in the snippet.&lt;br /&gt;
&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=L9NRdNczCNM:xGJ5y72AMlE:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=L9NRdNczCNM:xGJ5y72AMlE:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=L9NRdNczCNM:xGJ5y72AMlE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=L9NRdNczCNM:xGJ5y72AMlE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/L9NRdNczCNM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/5444103811470439863/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/12/ajax-ifying-blogger-no-2-keeping.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/5444103811470439863?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/5444103811470439863?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/L9NRdNczCNM/ajax-ifying-blogger-no-2-keeping.html" title="Ajax-ifying Blogger No. 2: Keeping content updated" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://www.swook.net/2011/12/ajax-ifying-blogger-no-2-keeping.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUAHRXk8fSp7ImA9WhRQFkw.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-5972702407328699240</id><published>2011-12-01T18:10:00.001Z</published><updated>2011-12-11T15:35:34.775Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-11T15:35:34.775Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="Blogger" /><category scheme="http://www.blogger.com/atom/ns#" term="AJAX" /><category scheme="http://www.blogger.com/atom/ns#" term="jQuery" /><title>Ajax-ifying Blogger No. 1: Flickerless Page Loads</title><content type="html">&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-T_D4iXH2Vxo/TtfFWtJVvLI/AAAAAAAAAIw/5nA0t8_GAWc/s1600/ajax_logo-285x300.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/-T_D4iXH2Vxo/TtfFWtJVvLI/AAAAAAAAAIw/5nA0t8_GAWc/s200/ajax_logo-285x300.jpg" width="190" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;No... not the detergent.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;One of the problems I experienced while messing around with this blog was the fact that the experience as a whole was not polished enough. Many web services nowadays make extensive use of &lt;a href="http://en.wikipedia.org/wiki/Ajax_(programming)"&gt;AJAX&lt;/a&gt; (and JavaScript) to add and remove content from your screen as you browse the website. What this achieves is an experience where your screen always has content on it, and flickers are never evident.&lt;br /&gt;
&lt;br /&gt;
I wanted that on my blog.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;First Thoughts&lt;/h2&gt;Since Blogger is a proprietary service with many of its doors closed, I realised that I cannot go the conventional way and ask for Google to give me a url where I can request certain bits of data.&lt;br /&gt;
&lt;br /&gt;
I would instead need to pull all of the data for the next page, and cherry-pick what I need from it.&lt;br /&gt;
&lt;br /&gt;
I decided to create a jQuery plugin which would do this for me. It would hijack all links which point back to the blog, and instead of taking the user to that page after showing them a gaping pit of whiteness, it would load bits of data from the clicked target page onto the current page.&lt;br /&gt;
&lt;br /&gt;
I had not done much JavaScript or AJAX before so on my way to the result, I had to encounter many baffling moments.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;URL Parsing&lt;/h2&gt;It didn't take long for me to get to my first hurdle. Parsing the target URLs from the internal links.&lt;br /&gt;
I soon found &lt;a href="http://james.padolsey.com/"&gt;James Padolsey&lt;/a&gt;'s &lt;a href="http://james.padolsey.com/javascript/parsing-urls-with-the-dom/"&gt;parseURL&lt;/a&gt; which uses a genius method: Letting your browser do most of the work by using the DOM. The method was great and all potential problems related to URL parsing was gone.&lt;br /&gt;
&lt;br /&gt;
I do use &lt;a href="http://blog.stevenlevithan.com/about"&gt;Steve&lt;/a&gt;'s &lt;a href="http://blog.stevenlevithan.com/archives/parseuri"&gt;parseUri&lt;/a&gt; now though due to its faster speed from only using regexes. I had to add a few more checks to certain parameters but I'm sure the speed benefit helps for webpages which contain many internal links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Retrieving the right elements for the next page.&lt;/h2&gt;&lt;a href="http://api.jquery.com/category/selectors/"&gt;jQuery selectors&lt;/a&gt; are awesome. I myself do use it for parsing elements out of data pulled from target links. However, there are problems with one being crucial. That is the ignoring of javascript entries which look like this:&lt;br /&gt;
&lt;pre class="lang-js"&gt;&amp;lt;script src='http://www.domain.tld/js/script.js' type='text/javascript'&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;br /&gt;
This was a proper blow and while it could be remedied by adding the &lt;code&gt;$.Ajaxify.pageChange()&lt;/code&gt; method which lets users register functions which are run when new pages are loaded, it made everything un-necessarily difficult. For example, I have so far had to add code to update and refresh software such as Google Analytics, AdSense, AddThis, the Blogger comment form and various other elements which display page data. How inconvenient is this? The process of keeping these components in time with the context of the page also requires some reverse engineering of the components depending on the amount of documentation available.&lt;br /&gt;
&lt;br /&gt;
While I have tried out other methods, such as using iframes to let the DOM parse html, they have proved to be much slower, triggering all JavaScript initiations as well as rendering all DOM elements which do not have to be loaded onto the page at all. If anyone finds a nice method which keeps &lt;code&gt;script&lt;/code&gt; elements and comments intact while selecting specific elements from a chunk of html, please let me know!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;History&lt;/h2&gt;After having successfully swapped the shown content for new content, I felt satisfied and was starting to think that my work was almost done. How wrong I was!&lt;br /&gt;
&lt;br /&gt;
All web browsers have this feature called &lt;b&gt;history&lt;/b&gt; which lets you traverse between pages you have been to. Pages  like mine, which change content without actually moving to a whole new page, do not actually add entries into your browsers history unless the JavaScript does that for you.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.w3.org/TR/html5/history.html"&gt;W3C's specifications&lt;/a&gt; regarding session history helped a lot and I was able to get history working after a while. If you press the 'back' button now, you'll notice that you'll be taken back to the previous page smoothly (if you were already on my website).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Final Product&lt;/h2&gt;You can find my final work here: &lt;a href="http://www.swook.net/p/jquery-ajaxify-plugin.html"&gt;http://www.swook.net/p/jquery-ajaxify-plugin.html&lt;/a&gt; together with instructions on installation and configuration.&lt;br /&gt;
&lt;br /&gt;
Simply install the script along with jQuery, and configure it, and off you go with a nice AJAX-ified Blogger.&lt;br /&gt;
There are some tweaks that you'll have to perform to keep everything updated as your page changes but that should be discussed in another post.&lt;br /&gt;
&lt;br /&gt;
If you want a demo, you have probably already used the plugin on your way to this page! This blog sports my Ajaxify jQuery plugin and you'll notice if you look carefully for blank-outs or whole-screen flickers when you click on a link which points to another page in my blog.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To read the next article in this series, click below:&lt;br /&gt;
&lt;a href="http://www.swook.net/2011/12/ajax-ifying-blogger-no-2-keeping.html"&gt;Ajax-ifying Blogger No. 2: Keeping Content Updated&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=SfPEpVE8jXg:1sg-XnlzaxA:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=SfPEpVE8jXg:1sg-XnlzaxA:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=SfPEpVE8jXg:1sg-XnlzaxA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=SfPEpVE8jXg:1sg-XnlzaxA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/SfPEpVE8jXg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/5972702407328699240/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/12/ajax-ifying-blogger-no-1-flickerless.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/5972702407328699240?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/5972702407328699240?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/SfPEpVE8jXg/ajax-ifying-blogger-no-1-flickerless.html" title="Ajax-ifying Blogger No. 1: Flickerless Page Loads" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-T_D4iXH2Vxo/TtfFWtJVvLI/AAAAAAAAAIw/5nA0t8_GAWc/s72-c/ajax_logo-285x300.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://www.swook.net/2011/12/ajax-ifying-blogger-no-1-flickerless.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08DSHw7eCp7ImA9WhRREE8.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-6012321438253744394</id><published>2011-11-23T03:20:00.001Z</published><updated>2011-11-23T04:17:59.200Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-23T04:17:59.200Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Yogscast" /><category scheme="http://www.blogger.com/atom/ns#" term="Minecraft" /><category scheme="http://www.blogger.com/atom/ns#" term="MineCon" /><category scheme="http://www.blogger.com/atom/ns#" term="Notch" /><title>Notch vs Yogscast</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-CkVR2IgEc7g/TsxxTobmq-I/AAAAAAAAAGY/8hlPg2lmYr8/s1600/holler.png" imageanchor="1" style="clear: right; float: right; font-size: medium; font-weight: normal; margin-bottom: 1em; margin-left: 1em; text-align: center;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-CkVR2IgEc7g/TsxxTobmq-I/AAAAAAAAAGY/8hlPg2lmYr8/s200/holler.png" width="180" /&gt;&lt;/a&gt;&lt;/div&gt;There has been much drama lately over in the Minecraft community due to a series of Twitter posts by Markus Persson. Read the thread at &lt;a href="http://www.minecraftforum.net/news/330-mojang-yogscast-in-dispute/"&gt;Minecraft Forum&lt;/a&gt; and &lt;a href="http://www.reddit.com/r/Minecraft/comments/mkjci/hate_insults_and_threats_are_flooding_in_from/c31oib6"&gt;TotalBiscuit's reply&lt;/a&gt; to get an idea about what's going on.&lt;br /&gt;
There have been several points made and I'd like to comment on a few:&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Notch owes Yogscast vs Yogscast owes Notch&lt;/h2&gt;Neither owes the other.&lt;br /&gt;
Either could have done without the other.&lt;br /&gt;
However, the fact is that both co-exist and both are important in maintaining the community.&lt;br /&gt;
&lt;br /&gt;
People mention often that it wasn't the Yogscast which drew them to Minecraft.&lt;br /&gt;
That is true, Yogscast videos are not aimed at drawing new users but they are aimed at maintaining the community by sharing mods, new features, texture packs, adventure maps, and skins.&lt;br /&gt;
They maintain a certain 'freshness' by having a casual and honest approach (sometimes unfair) to new content, allowing for continued interest in the community.&lt;br /&gt;
They could do without Minecraft however, as they were well established before entering the Minecraft community. However, it is a fact that they now co-exist with the community.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Yogscast were correct to demand payment&lt;/h2&gt;Notch could have done without the Yogscast and yes, Notch has no obligation to pay the Yogscast.&lt;br /&gt;
The Yogscast do make a living out of their videos.&lt;br /&gt;
&lt;br /&gt;
However, what is Minecon? Is it not a convention in Mojang's interest?&lt;br /&gt;
Is it not a hype machine which has been un-necessarily spamming the otherwise useful news updates with the glam prospect of a party in Las Vegas?&lt;br /&gt;
&lt;br /&gt;
If Mojang had the community's benefit in its highest interest, it would have held an online convention, open and available to all Minecraft fans. They would work on proper documentation and proper, clear information about their releases.&lt;br /&gt;
They however, chose Las Vegas as Notch wished so. Having chosen Las Vegas, the emphasis for Minecon was definitely placed on the hype it can produce, the attention it can acquire, and the glamour with which Mojang could exhibit its greatness.&lt;br /&gt;
&lt;br /&gt;
With the purpose of the convention in mind, it is not hard to come to a conclusion that the Yogscast, as part of the hype-machine should have been paid for their part in it.&lt;br /&gt;
Minecon benefited from their attendance but the Yogscast did not as they already have maximum exposure through Youtube.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Unprofessional Behaviour&lt;/h2&gt;A similar situation to this one is when Notch &lt;a href="http://notch.tumblr.com/post/9038258448/hey-bethesda-lets-settle-this"&gt;challenged Bethesda to a Quake match&lt;/a&gt; to settle the court dispute regarding a supposed trademark infringement from Mojang, with their new game &lt;i&gt;Scrolls&lt;/i&gt;, with Bethesda's &lt;i&gt;Elder Scrolls&lt;/i&gt; Series.&lt;br /&gt;
&lt;br /&gt;
Utilising the community to his benefit, Notch successfully gained the support of millions with his flamboyant attitude.&lt;br /&gt;
You may be arguing, "but he really did challenge Bethesda!" but I'd like to ask: "Would Mojang have wanted to &lt;i&gt;change the name of Scrolls to something you’re fine with.&lt;/i&gt;"? No.&lt;br /&gt;
&lt;br /&gt;
This strategy works marvellously when dealing with corporates like Bethesda.&lt;br /&gt;
Why use the same strategy towards a large part of your own community though?&lt;br /&gt;
&lt;br /&gt;
Professional behaviour is not about suits, ties and the common set of boring phrases. It is about being wary about the responsibilities one can take as a result of one's actions.&lt;br /&gt;
Notch's introduction of this issue through his personal Twitter account was not professional.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;British Humour&lt;/h2&gt;There are many mentions with regards to how Simon and Lewis' supposed remarks are examples of British dark humour.&lt;br /&gt;
There are also comparisons of British and Swedish humour.&lt;br /&gt;
This is irrelevant to the situation.&lt;br /&gt;
&lt;br /&gt;
The joke (proposing to cross out Notch's signature and replace it with a &lt;i&gt;Fuck Off&lt;/i&gt;) was most likely a failed attempt. Face it, the Yogscast, while good performers in the space of edited Youtube videos, are not real-time entertainers (for the most part) and such a failed attempt at humour should be ignored with respect or merely used for entertainment.&lt;br /&gt;
&lt;br /&gt;
The issue is whether this was a joke or whether it was simply being rude.&lt;br /&gt;
I will wait for the Yogscast to give their own statement as there is currently only one side to the story.&lt;br /&gt;
However, I fail to imagine a situation where this was not a failed joke attempt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Yogscast = Celebrity?&lt;/h2&gt;There are many comments about how the Yogscast have become full of themselves, how they are rude and do not deserve to feel as if they are real celebrities.&lt;br /&gt;
Real celebrities.&lt;br /&gt;
&lt;br /&gt;
The platform for entertainment has shifted and expanded over the years and continuously does so.&lt;br /&gt;
&lt;br /&gt;
Minecraft is an indie game, produced by an independent and small company.&lt;br /&gt;
The Yogscast is an indie production, run by a small company as well.&lt;br /&gt;
&lt;br /&gt;
Both have garnered much attention and both are recognised in the community but both have also not gone through traditional methods of gaining attention. The internet has changed much and it is time we not only observe but also accept that fact.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=JxTWdnsuEcQ:HrbGjnCNivs:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=JxTWdnsuEcQ:HrbGjnCNivs:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=JxTWdnsuEcQ:HrbGjnCNivs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=JxTWdnsuEcQ:HrbGjnCNivs:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/JxTWdnsuEcQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/6012321438253744394/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/11/notch-vs-yogscast.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/6012321438253744394?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/6012321438253744394?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/JxTWdnsuEcQ/notch-vs-yogscast.html" title="Notch vs Yogscast" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-CkVR2IgEc7g/TsxxTobmq-I/AAAAAAAAAGY/8hlPg2lmYr8/s72-c/holler.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/11/notch-vs-yogscast.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MHSXk9fCp7ImA9WhRREk4.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-3825513142740848948</id><published>2011-11-22T08:26:00.000Z</published><updated>2011-11-25T15:37:18.764Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T15:37:18.764Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="Blogger" /><title>Push Blogger's Sidebar Ad Down to the Bottom</title><content type="html">&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-eVbJJjh92A4/TsutnbqRvgI/AAAAAAAAAGQ/9pkYCmGw58g/s1600/blogolddesign.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="128" src="http://1.bp.blogspot.com/-eVbJJjh92A4/TsutnbqRvgI/AAAAAAAAAGQ/9pkYCmGw58g/s200/blogolddesign.jpg" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Good Bye Old Design!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;While changing the design of my blog from the old copper themed mess to this new clean template, I was carrying out numerous changes to the CSS of the template.&lt;br /&gt;
&lt;br /&gt;
I made myself busy changing the colours of everything, enlarging and shrinking text, and tapping the refresh button on my browser to check things were peachy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Kx3bOPYZe3s/Tstv7XSehPI/AAAAAAAAAGI/EwKD5gL-Feg/s1600/blognewdesign.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="109" src="http://2.bp.blogspot.com/-Kx3bOPYZe3s/Tstv7XSehPI/AAAAAAAAAGI/EwKD5gL-Feg/s200/blognewdesign.jpg" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Hello New Design!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;After having gone through many templates, I settled on the design which you can see on this page. 'Clean', I thought and I especially made sure that I praised myself enough for the ninja page buttons which were done so that it didn't form a boring old bar. As my eyes roamed around the screen, I gasped when I took a glimpse of the AdSense advertisement at the bottom of the sidebar.&lt;br /&gt;
&lt;br /&gt;
There were a few problems to it:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;The advertisement was placed right below the last widget, with no breathing space.&lt;/li&gt;
&lt;li&gt;Having the advertisement in an easy-to-view location is beneficial for increased exposure of the ad but I prefer a more discreet placement. At the time, my sidebar ad was glaring at me in the face!&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
What I wanted was for the advertisement to be placed at the bottom of the sidebar pane and effectively at the bottom of the page, disregarding the height of the page (which changes depending on content). This would allow ads to be viewed after the reader finishes reading a post, not before.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Usually, the easiest method of placing an element at the bottom of a div is by doing something like the following:&lt;br /&gt;
&lt;pre class="lang-css"&gt;#elementId {
  bottom: 0px;
}
&lt;/pre&gt;Unfortunately, the sidebar div does not extend down to fill up the full length of the page. Therefore, when using the code above, it does not affect the position of the advertisement.&lt;br /&gt;
&lt;br /&gt;
Googling around brought my attention to &lt;a href="http://www.alistapart.com/articles/fauxcolumns/"&gt;faux columns&lt;/a&gt; which allow for divs which extend as I wish mine to do. On inspecting the template code of my site, I found that this was already being done. However, the faux columns were not actually holding the sidebar widgets and therefore I had to find a way to apply the height of the faux columns to my sidebar.&lt;br /&gt;
&lt;br /&gt;
There were mentions of using &lt;code&gt;position: absolute&lt;/code&gt; somewhere and setting &lt;code&gt;height: 100%&lt;/code&gt; for the container and so on but none of it seemed feasible enough as the template code is rather confusing and there are at least 10 parent divs for the ad div.&lt;br /&gt;
&lt;br /&gt;
What I could do though, was to write a piece of JavaScript which lets me move the ad down. This would actually be the easiest solution since calculating the height of the flexible page can only be done client-side. Here's the code I ended up with:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="lang-js"&gt;&amp;lt;script type="text/javascript"&amp;gt;
//&amp;lt;![CDATA[
  onload = function(){
    var sidebar = document.getElementById('sidebar-right-1');
    var newheight = document.getElementsByClassName('fauxcolumns')[0].clientHeight;
    var oldheight = sidebar.clientHeight;
    sidebar.style.height = newheight+'px';
    document.getElementById('AdSense1').style.top = (newheight - oldheight)+'px';
  }
//]]&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
To use this code, place it anywhere in your template (before &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt;). You can edit your template for Blogger via the menu accessible through: &lt;i&gt;Dashboard - Template - Edit HTML&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
The div class and id names used will vary depending on your Blogger template, but should not differ too much as long as you are using Blogger's classic templates (not the odd 'Dynamic' ones). This small piece of code runs once the page is loaded and carries a few jobs out. It first gets the height of the fully extended sidebar from the faux columns, then it sets the sidebar to be that height so that it can extend downwards fully. The code then calculates where the ad should be using the previous height of the sidebar and places the ad there using the CSS property &lt;code&gt;top&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
If you have any problems, let me know and I will try to help.&lt;br /&gt;
Also, if you found this post helpful, please share it and if you wish to, &lt;a href="https://flattr.com/thing/435575/Atomic-Landscape"&gt;flattr me&lt;/a&gt;.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=lFT7t5ubZSQ:F23x39X1nPA:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=lFT7t5ubZSQ:F23x39X1nPA:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=lFT7t5ubZSQ:F23x39X1nPA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=lFT7t5ubZSQ:F23x39X1nPA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/lFT7t5ubZSQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/3825513142740848948/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/11/push-bloggers-sidebar-ad-down-to-bottom.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/3825513142740848948?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/3825513142740848948?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/lFT7t5ubZSQ/push-bloggers-sidebar-ad-down-to-bottom.html" title="Push Blogger's Sidebar Ad Down to the Bottom" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-eVbJJjh92A4/TsutnbqRvgI/AAAAAAAAAGQ/9pkYCmGw58g/s72-c/blogolddesign.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/11/push-bloggers-sidebar-ad-down-to-bottom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUCRHkzeip7ImA9WhRQGU4.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-1604638202971527550</id><published>2011-11-15T07:21:00.000Z</published><updated>2011-12-15T08:37:45.782Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-15T08:37:45.782Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ActionScript 2" /><category scheme="http://www.blogger.com/atom/ns#" term="Flash" /><title>AS2 | Long Click Detection</title><content type="html">&lt;i&gt;This article deals with Long Click (aka Long Press aka Press and Hold) detection implementation using ActionScript 2.&lt;br /&gt;
Prerequisite: &lt;a href="http://www.swook.net/2011/11/as2-objectaddproperty.html"&gt;AS2 | Object.addProperty&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
When working with a touch screen UI, one has to often consider what someone else would intuitively do when dealing with the UI. Naturally, people tend to fall back to experience from older analogue devices which provide tactile feedback.&lt;br /&gt;
&lt;br /&gt;
Think back to a few years ago, when the first &lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/Walkman"&gt;Walkman&lt;/a&gt;&lt;/i&gt;s were becoming hip. You'd see teenagers walking down the street with a pair of earphones in their ears, clutching onto a small grey device. Looking closer, you would notice the spinning wheels of a cassette tape. These devices were in no way complex but they did what they were built to do: play music from cassette tapes.&lt;br /&gt;
&lt;br /&gt;
Part of the playback relied on seeking which was done by pressing the fast forward or rewind keys. If you pressed the keys for a short time, the tape would rewind or fast forward just a little bit. If you held on for a longer moment, hearing the whirring in your earphones, you would be sent further back or forwards in the cassette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Need for better Long Click Detection&lt;/h2&gt;When designing a music UI, it is often expected that pressing the fast forward or rewind keys briefly will change the track being played. It is also expected that holding onto the forward or rewind keys will let you seek within the current track.&lt;br /&gt;
&lt;br /&gt;
This feature is by no means difficult to write with ActionScript 2. In fact, I will do that now for a &lt;i&gt;MovieClip&lt;/i&gt; button named &lt;i&gt;mcPrev&lt;/i&gt;:&lt;br /&gt;
&lt;pre class="lang-as"&gt;var count:Number = 0;

mcPrev.onPress = function (Void):Void
{
    this.onEnterFrame = function (Void):Void
    {
        if ( count &amp;lt; 10 ) {
            ext_fscommand("Rewind");
        }
        count++;
    }
}

mcPrev.onRelease = function (Void):Void
{
    if ( count &amp;lt;= 10 )
    {
        ext_fscommand("PreviousTrack");
    }
    count = 0;
    delete this.onEnterFrame;
}
&lt;/pre&gt;The code above starts counting up to 10 once you press the button. When it reaches 10, it starts rewinding the current track. When the button is released, the code checks if the counting had been done above 10 and if not, changes the current track to the previously played track.&lt;br /&gt;
&lt;br /&gt;
It's all very simple and Just Works.&lt;br /&gt;
&lt;br /&gt;
What happens though when you want to get that working for 10 different clips?&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;First off, you can't use the variable &lt;i&gt;count&lt;/i&gt; like I do, it must be tied to the &lt;i&gt;MovieClip&lt;/i&gt; since it would be over-written by other actions.&lt;/li&gt;
&lt;li&gt;Secondly, you would end up with hundreds of un-necessary lines of code.&lt;/li&gt;
&lt;li&gt;Thirdly, you would get confused about how and when you should be using &lt;i&gt;MovieClip.onEnterFrame&lt;/i&gt;. This is because the code above relies on the said event.&lt;/li&gt;
&lt;li&gt;Fourthly, you would get tired of writing this piece of code, having to alter it ever so slightly as you increase the usage of it.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Would it not simply &lt;b&gt;rock&lt;/b&gt; for you to be able to do the following?&lt;br /&gt;
&lt;pre class="lang-as"&gt;mcPrev.onLongClick = function (Void):Void
{
    ext_fscommand("Rewind");
}

mcPrev.onShortClick = function (Void):Void
{
    ext_fscommand("PreviousTrack");
}
&lt;/pre&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Long Click Detection&lt;/h2&gt;To start off, we need to find a way to listen to the &lt;i&gt;onEnterFrame&lt;/i&gt; event which occurs for every rendered frame in your flash movie. This is so that we can wait for a certain amount of time (delay) until we start announcing that a long click is occuring. This is also so that we can periodically announce when to run the &lt;i&gt;onLongClick&lt;/i&gt; function.&lt;br /&gt;
&lt;br /&gt;
The solution is to use a hidden Flash MX class called OnEnterFrameBeacon. This class has a single method called &lt;i&gt;init()&lt;/i&gt; which starts listening to a ghost &lt;i&gt;MovieClip&lt;/i&gt;'s onEnterFrame event.&lt;br /&gt;
It relays the event to all &lt;i&gt;listening Objects&lt;/i&gt;, allowing you to have an &lt;i&gt;onEnterFrame&lt;/i&gt; listener anywhere in your code. &lt;i&gt;OnEnterFrameBeacon&lt;/i&gt; is initiated in the following way:&lt;br /&gt;
&lt;pre class="lang-as"&gt;import mx.transitions.OnEnterFrameBeacon;
OnEnterFrameBeacon.init();
&lt;/pre&gt;&lt;br /&gt;
Now let's consider what sort of events we have to listen to. There's the &lt;i&gt;onPress&lt;/i&gt;, &lt;i&gt;onRelease&lt;/i&gt;&amp;nbsp;events as well as the &lt;i&gt;onDragOut&lt;/i&gt;&amp;nbsp;event. Afterall, the UI should stop rewinding once your fingers leave the button! Let's hijack these events and replace it with our own handler object.&lt;br /&gt;
This can be done via &lt;i&gt;MovieClip.prototype.&lt;/i&gt;EVENT which lets you add methods to the default &lt;i&gt;MovieClip&lt;/i&gt; class.&lt;br /&gt;
&lt;pre class="lang-as"&gt;var LongClickHandler:Object = {};

MovieClip.prototype.addProperty( "onPress",
                                 function ():Function {
                                     return LongClickHandler.onPress;
                                 },
                                 function ( func:Function ):Void {
                                     this.onPress_ = func;
                                 } );

MovieClip.prototype.addProperty( "onRelease",
                                 function ():Function {
                                     return LongClickHandler.onRelease;
                                 },
                                 function ( func:Function ):Void {
                                     this.onRelease_ = func;
                                 } );

MovieClip.prototype.addProperty( "onDragOut",
                                 function ():Function {
                                     return LongClickHandler.onDragOut;
                                 },
                                 function ( func:Function ):Void {
                                     this.onDragOut_ = func;
                                 } );
&lt;/pre&gt;This code basically creates a proxy for the mentioned events, making ActionScript go through our own methods first (LongClickHandler.EVENT). Compatibility is kept by putting all user-defined functions to the side (onPress_) so that we can run them after our own handler is done.&lt;br /&gt;
&lt;br /&gt;
We can now add those onLongClick and onShortClick events:&lt;br /&gt;
&lt;pre class="lang-as"&gt;MovieClip.prototype.addProperty( "onLongClick",
                                 function ():Function {
                                     return this.LongClick.func_long;
                                 },
                                 function ( func:Function ):Void {
                                     LongClickHandler.Init.call( this );
                                     this.LongClick.func_long = func;
                                 } );

MovieClip.prototype.addProperty( "onShortClick",
                                 function ():Function {
                                     return this.LongClick.func_short;
                                 },
                                 function ( func:Function ):Void {
                                     LongClickHandler.Init.call( this );
                                     this.LongClick.func_short = func;
                                 } );&lt;/pre&gt;These methods cache the functions which we set to them, and initialises the MovieClip's Long Click handler.&lt;br /&gt;
&lt;br /&gt;
Let's start writing the handler now.&lt;br /&gt;
&lt;pre class="lang-as"&gt;LongClickHandler.Init = function ( func ):Void {
    // NOTE: this == MovieClip
    if ( this.LongClick != undefined ) return;

    this.LongClick = {};
    this.LongClick.mc = this;
    this.LongClick.onEnterFrame = LongClickHandler.onEnterFrame;
}
&lt;/pre&gt;We cache some data into a new &lt;i&gt;Object&lt;/i&gt; which we need to use to listen to the &lt;i&gt;onEnterFrame&lt;/i&gt; event. We also register the &lt;i&gt;onEnterFrame&lt;/i&gt; event that we will write for our &lt;i&gt;LongClickHandler&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
We now write the proxy function for the event &lt;i&gt;onPress&lt;/i&gt; which lets us start the Long Click handling.&lt;br /&gt;
&lt;pre class="lang-as"&gt;LongClickHandler.onPress = function ():Void {
    // NOTE: this == MovieClip
    if ( this.LongClick.func_long ) {
        this.LongClick.start_t = getTimer();
        MovieClip.addListener( this.LongClick );
    }
    this.onPress_();
}&lt;/pre&gt;As you can see, the handling is initiated only if a function is defined for the long click handling (&lt;i&gt;onLongClick&lt;/i&gt;). If it is defined, a starting ticks value is saved and we start listening to the &lt;i&gt;onEnterFrame&lt;/i&gt; event which fires the function assigned to &lt;i&gt;MovieClip.LongClick.onEnterFrame&lt;/i&gt; which is equal to &lt;i&gt;LongClickHandler.onEnterFrame&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Now let's write the real deal.&lt;br /&gt;
&lt;pre class="lang-as"&gt;// DELAY: Delay until LongClick handling is started
// INTERVAL: Interval at which LongClick should be called
// Both values are in milliseconds
LongClickHandler.DELAY = 350;
LongClickHandler.INTERVAL = 150;

LongClickHandler.onEnterFrame = function ():Void {
    // NOTE: this == MovieClip.LongClick
    // Calculate elapsed time (ms) since onPress
    var dt:Number = getTimer() - this.start_t;

    // this.last_t: last registered LongClick event
    //              exists once
    if ( this.last_t ) {
        var ivl:Number = LongClickHandler.INTERVAL;

        // this.trail_done: tells whether the trail-off for
        //                  the interval has been finished.
        if ( !this.trail_done ) {

            // Calculate trail-off
            var inc:Number = (ivl * 100000 / dt / dt) &amp;gt;&amp;gt; 0;

            // If trail-off changes are less than 10ms,
            // consider it done
            if ( inc &amp;lt; 10 ) this.trail_done = true;

            // Increase interval by trail-off change
            ivl += inc;
        }

        // Calculate elapsed time (ms) since last LongClick
        dt = getTimer() - this.last_t;

        // If greater than calculated interval
        if ( dt &amp;gt;= ivl ) {

            // Remember this time
            this.last_t = getTimer();

            // Call the function registered to onLongClick
            this.func_long.call( this.mc );
        }
        return;
    }

    // If LongClick not called before, and time elapsed
    // larger than defined DELAY
    else if ( dt &amp;gt; LongClickHandler.DELAY ) {
        this.last_t = getTimer();
        this.func_long.call( this.mc );
    }
}&lt;/pre&gt;As you can see in the chunk of code above, I have coded a 'trail-off' which lets your interval decrease to your target interval defined in &lt;i&gt;LongClickHandler.INTERVAL&lt;/i&gt;. This gives an effect of a speed-up due to the longer duration of pressing-the-button.&lt;br /&gt;
&lt;br /&gt;
We can't perpetually detect LongClicks though and need to end it at some point. The following code does that as well as adding onShortClick handling:&lt;br /&gt;
&lt;pre class="lang-as"&gt;LongClickHandler.cleanUp = function ():Void {
    // NOTE: this == MovieClip
    delete this.LongClick.last_t;
    delete this.LongClick.trail_done;
    MovieClip.removeListener( this.LongClick );
}

LongClickHandler.onRelease = function ():Void {
    // NOTE: this == MovieClip
    if ( !this.LongClick.last_t ) this.LongClick.func_short();
    LongClickHandler.cleanUp.call( this );
    this.onRelease_();
}

LongClickHandler.onDragOut = function ():Void {
    // NOTE: this == MovieClip
    LongClickHandler.cleanUp.call( this );
    this.onDragOut_();
}
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Usage&lt;/h2&gt;I have been very rough with explaining how it all works but there's a reason for it. You don't need to know! Like I mentioned before, you simply have to do something like the following to make use of my code (full code provided at the end).&lt;br /&gt;
&lt;pre class="lang-as"&gt;mcPrev.onLongClick = function (Void):Void
{
    ext_fscommand("Rewind");
}

mcPrev.onShortClick = function (Void):Void
{
    ext_fscommand("PreviousTrack");
}
&lt;/pre&gt;&lt;br /&gt;
How convenient is that!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Full Code&lt;/h2&gt;&lt;pre class="lang-as"&gt;var LongClickHandler:Object = {};
LongClickHandler.DELAY = 350;
LongClickHandler.INTERVAL = 150;

LongClickHandler.Init = function ( func ):Void {
    // NOTE: this == MovieClip
    if ( this.LongClick != undefined ) return;

    this.LongClick = {};
    this.LongClick.mc = this;
    this.LongClick.onEnterFrame = LongClickHandler.onEnterFrame;
}

LongClickHandler.cleanUp = function ():Void {
    // NOTE: this == MovieClip
    delete this.LongClick.last_t;
    delete this.LongClick.trail_done;
    MovieClip.removeListener( this.LongClick );
}

LongClickHandler.onEnterFrame = function ():Void {
    // NOTE: this == MovieClip.LongClick
    var dt:Number = getTimer() - this.start_t;
    if ( this.last_t ) {
        var ivl:Number = LongClickHandler.INTERVAL;
        if ( !this.trail_done ) {
            var inc:Number = ( ivl * 100000 / dt / dt ) &amp;gt;&amp;gt; 0;
            if ( inc &amp;lt; 10 ) this.trail_done = true;
            ivl += inc;
        }

        dt = getTimer() - this.last_t;
        if ( dt &amp;gt;= ivl ) {
            this.last_t = getTimer();
            this.func_long.call( this.mc );
        }
        return;
    }
    else if ( dt &amp;gt; LongClickHandler.DELAY ) {
        this.last_t = getTimer();
        this.func_long.call( this.mc );
    }
}


// Replace onPress
LongClickHandler.onPress = function ():Void {
    // NOTE: this == MovieClip
    if ( this.LongClick.func_long ) {
        this.LongClick.start_t = getTimer();
        MovieClip.addListener( this.LongClick );
    }
    this.onPress_();
}

MovieClip.prototype.addProperty( "onPress",
                                 function ():Function {
                                     return LongClickHandler.onPress;
                                 },
                                 function ( func:Function ):Void {
                                     this.onPress_ = func;
                                 } );


// Replace onDragOut
LongClickHandler.onDragOut = function ():Void {
    // NOTE: this == MovieClip
    LongClickHandler.cleanUp.call( this );
    this.onDragOut_();
}

MovieClip.prototype.addProperty( "onDragOut",
                                 function ():Function {
                                     return LongClickHandler.onDragOut;
                                 },
                                 function ( func:Function ):Void {
                                     this.onDragOut_ = func;
                                 } );


// Replace onRelease
LongClickHandler.onRelease = function ():Void {
    // NOTE: this == MovieClip
    if ( !this.LongClick.last_t ) this.LongClick.func_short();
    LongClickHandler.cleanUp.call( this );
    this.onRelease_();
}

MovieClip.prototype.addProperty( "onRelease",
                                 function ():Function {
                                     return LongClickHandler.onRelease;
                                 },
                                 function ( func:Function ):Void {
                                     this.onRelease_ = func;
                                 } );


MovieClip.prototype.addProperty( "onLongClick",
                                 function ():Function {
                                     return this.LongClick.func_long;
                                 },
                                 function ( func:Function ):Void {
                                     LongClickHandler.Init.call( this );
                                     this.LongClick.func_long = func;
                                 } );

MovieClip.prototype.addProperty( "onShortClick",
                                 function ():Function {
                                     return this.LongClick.func_short;
                                 },
                                 function ( func:Function ):Void {
                                     LongClickHandler.Init.call( this );
                                     this.LongClick.func_short = func;
                                 } );
&lt;/pre&gt;&lt;br /&gt;
Please reply below if you need help with understanding the code!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit: This code does not work. &lt;a href="http://www.swook.net/2011/12/as2-long-click-detection-fixed.html"&gt;Click here&lt;/a&gt; for an updated version of the code.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=4JrSusRmRf4:yrWclCjVBIU:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=4JrSusRmRf4:yrWclCjVBIU:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=4JrSusRmRf4:yrWclCjVBIU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=4JrSusRmRf4:yrWclCjVBIU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/4JrSusRmRf4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/1604638202971527550/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/11/as2-long-click-detection.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/1604638202971527550?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/1604638202971527550?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/4JrSusRmRf4/as2-long-click-detection.html" title="AS2 | Long Click Detection" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/11/as2-long-click-detection.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EBRnc7eSp7ImA9WhRREk8.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-8756940378680827761</id><published>2011-11-15T03:22:00.001Z</published><updated>2011-11-25T14:00:57.901Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T14:00:57.901Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ActionScript 2" /><category scheme="http://www.blogger.com/atom/ns#" term="Flash" /><title>AS2 | Object.addProperty</title><content type="html">&lt;b&gt;The&lt;/b&gt; most useful method I have thus far encountered while programming in ActionScript 2.0, is &lt;a href="http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001422.html" target="_blank"&gt;Object.addProperty&lt;/a&gt;. I would like to explain why this is so and how the method works.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Objects (and Arrays)&lt;/h2&gt;In ActionScript, the &lt;i&gt;Object&lt;/i&gt; type/class is used frequently. An &lt;i&gt;Object&lt;/i&gt; is used differently in different situations. In the object-oriented programming sense, &lt;i&gt;Objects&lt;/i&gt; are instances of a &lt;i&gt;Class&lt;/i&gt;. In a very basic sense, &lt;i&gt;Objects&lt;/i&gt;&amp;nbsp;are &lt;i&gt;Arrays&lt;/i&gt; where the indices are named.&lt;br /&gt;
&lt;br /&gt;
In both Arrays and Objects, any data type can be put into a new slot. In an &lt;i&gt;Array&lt;/i&gt;, you must pick a spot based on the available integer index slots while in an &lt;i&gt;Object&lt;/i&gt;, you must specify the &lt;i&gt;String&lt;/i&gt; index.&lt;br /&gt;
&lt;pre class="lang-as"&gt;function Three (Void):Number
{
    return 3;
}

var my_array:Array = [
                       1,                 // Number
                       "Two",             // String
                       Three              // Function
                     ];

var my_object:Object = {
                         one: 1,          // Number
                         two: "Two",      // String
                         three: Three     // Function
                       };&lt;/pre&gt;&lt;br /&gt;
Both arrays and objects are useful in different ways.&lt;br /&gt;
&lt;br /&gt;
Since the integer indices are important for arrays, it is essentially an ordered stack where you can &lt;a href="http://help.adobe.com/en_US/AS2LCR/Flash_10.0/00000745.html#130711"&gt;.push&lt;/a&gt; or &lt;a href="http://help.adobe.com/en_US/AS2LCR/Flash_10.0/00000750.html#131806"&gt;.sort&lt;/a&gt; the elements among other methods. This is very useful for queues for example, where the order of a list is very important.&lt;br /&gt;
&lt;br /&gt;
Objects on the other hand have the advantage that the elements can be referred to very easily.&lt;br /&gt;
&lt;pre class="lang-as"&gt;trace( my_object[ "two" ] );
// Traces "Two"

trace( my_object.two );
// Traces "Two"&lt;/pre&gt;&lt;br /&gt;
As you can see in the example above, you can refer to objects like you do in an array and also as a "." concatenated string where you have some sort of a tree structure starting from the top object. When you use any method in ActionScript, you are using this tree-like structured syntax and this syntax is simply wonderful. At the most basic level, it gives your code a more modular feeling, letting you differentiate between associated bits of code. At a more advanced level, you are able to use the same methods or properties for many different objects, making programming in general easier.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Detecting Variable Changes&lt;/h2&gt;Once you start using &lt;i&gt;Objects&lt;/i&gt;, you will at some point start wondering about this:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;&lt;i&gt;How do I detect when my property is changed?&lt;/i&gt;&lt;/blockquote&gt;Your code is riddled with copy-pasted code and you find that while you have hundreds of lines of code, most of them are repetitive.&lt;br /&gt;
You wonder what you should do and start wishing that you could monitor all of those variables which do the same things after they are set.&lt;br /&gt;
&lt;br /&gt;
Take for example, the setting of a variable:&lt;br /&gt;
&lt;pre class="lang-as"&gt;var myapples:Number = 10;&lt;/pre&gt;&lt;br /&gt;
Whenever you change the number stored in &lt;i&gt;myapples&lt;/i&gt;, you want to set a &lt;i&gt;TextField&lt;/i&gt; called &lt;i&gt;applesnum&lt;/i&gt; to show the number of your apples.&lt;br /&gt;
This is what you would do:&lt;br /&gt;
&lt;pre class="lang-as"&gt;var myapples:Number = 10;
applesnum.text = myapples;&lt;/pre&gt;&lt;br /&gt;
But doing this every single time you set a value to &lt;i&gt;myapples&lt;/i&gt; would make your code messy. This is when you need getters and setters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Object.addProperty&lt;/h2&gt;&lt;pre class="lang-as"&gt;var myapples_:Number;

function setmyapples (num:Number):Void
{
    myapples_ = num;
    applesnum.text = myapples_;
}

function getmyapples (Void):Number
{
    return myapples_;
}

this.addProperty("myapples", getmyapples, setmyapples);
&lt;/pre&gt;The code above seems rather long at first glance, but it allows you to simply do:&lt;br /&gt;
&lt;pre class="lang-as"&gt;myapples = 10;&lt;/pre&gt;and still get the &lt;i&gt;TextField&lt;/i&gt; updating as we need it to. This lets you reduce the amount of code you repeat drastically.&lt;br /&gt;
&lt;br /&gt;
Another way of writing the code above is:&lt;br /&gt;
&lt;pre class="lang-as"&gt;var myapples_:Number;

this.addProperty("myapples",
                 function (Void):Number
                 {
                     return myapples_;
                 },
                 function (num:Number):Void
                 {
                     myapples_ = num;
                     applesnum.text = myapples_;
                 } );
&lt;/pre&gt;using un-named functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Usefulness of Object.addProperty()&lt;/h2&gt;Being able to 'detect' changes in the variable is just one way of using &lt;i&gt;Object.addProperty&lt;/i&gt; and the method is truly useful for many different purposes.&lt;br /&gt;
For example, if you are writing a music interface in ActionScript 2, and wish to set the volume, you will most likely have to use a method similar to this:&lt;br /&gt;
&lt;pre class="lang-as"&gt;function getVolume ():Number {
    return ext_fscommand("GetVolume");
}

function setVolume ( newvol:Number ):Void {
    ext_fscommand("SetVolume", newvol);
}&lt;/pre&gt;Sometimes though, you'd want to do something like:&lt;br /&gt;
&lt;pre class="lang-as"&gt;var vol:Number = getVolume();
vol++;
setVolume(vol);&lt;/pre&gt;&lt;br /&gt;
If you use the following code, everything is so much neater and elegant:&lt;br /&gt;
&lt;pre class="lang-as"&gt;this.addProperty( "volume",
                  function ():Number {
                      return ext_fscommand("GetVolume");
                  },
                  function ( newvol:Number ):Void {
                      ext_fscommand("SetVolume", newvol);
                  }&lt;/pre&gt;this lets you do:&lt;br /&gt;
&lt;pre class="lang-as"&gt;volume++;&lt;/pre&gt;&lt;br /&gt;
So, a bit of effort ends up letting you save a significant amount of time!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=UOWrtZXymMM:PFQWh9fuj_c:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=UOWrtZXymMM:PFQWh9fuj_c:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=UOWrtZXymMM:PFQWh9fuj_c:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=UOWrtZXymMM:PFQWh9fuj_c:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/UOWrtZXymMM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/8756940378680827761/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/11/as2-objectaddproperty.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/8756940378680827761?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/8756940378680827761?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/UOWrtZXymMM/as2-objectaddproperty.html" title="AS2 | Object.addProperty" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/11/as2-objectaddproperty.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QMSHozeSp7ImA9WhRVFkU.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-93281644358619293</id><published>2011-11-10T07:30:00.000Z</published><updated>2012-01-16T04:49:49.481Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-16T04:49:49.481Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Skyrim" /><category scheme="http://www.blogger.com/atom/ns#" term="Gaming" /><category scheme="http://www.blogger.com/atom/ns#" term="The Matrix" /><category scheme="http://www.blogger.com/atom/ns#" term="MMO" /><title>Skyrim and musings about putting The Matrix in an MMO</title><content type="html">&lt;b&gt;Note:&lt;/b&gt; These are just the musings of an idiot. If you find the ideas ridiculous, please pass by.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Skyrim&lt;/h2&gt;I am by no means a gamer.&lt;br /&gt;
&lt;br /&gt;
Yes, I have played a few games and have enjoyed them as well. However, I have never gone too far into any game. Any game, at some point in time, bores me and I was wondering why this could be.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.bethsoft.com/eng/index.php?cn=ukeng"&gt;Bethesda Softworks&lt;/a&gt;' &lt;a href="http://www.elderscrolls.com/"&gt;Skyrim&lt;/a&gt; is being publicly released tomorrow (aka &lt;a href="http://en.wikipedia.org/wiki/Pepero#Pepero_Day"&gt;Korea's Peppero Day&lt;/a&gt;). Skyrim has been one of the most awaited games of the year and Bethesda was able to generate lots of hype about this new release. The hype is well deserved though since their previous release of Elder Scrolls, Oblivion, was a truly amazing game.&lt;br /&gt;
&lt;br /&gt;
Though I have not played Oblivion and Morrowind long enough, these are the few properties which I personally think, puts the Elder Scrolls series (as well as the Fallout series) apart from all other games:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Truly immersive play - Players are able to make decisions which have lasting effect. These lasting effects can change the landscape, your relationship with every other character in the game, the destiny of the world and more. Simply put, &lt;b&gt;you&lt;/b&gt;&amp;nbsp;matter, as a player, to the world of the Elder Scrolls.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Multi-ended plot - Due to the previous point, the plot changes in hundreds of different ways for each player and leads to a different ending every time.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Massive landscape - The landscape allows players to play in 'sandbox mode' whereby side-quests can be done and all sorts of skills honed. If you were to aim for the completion of the plot, it would take around 10 hours (with difficulty adjusted), but if you were to play through Oblivion at a moderate pace, pursuing a moderate amount of side-quests, it would take you at least 200 hours.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-qHV9hf9cCDY/TrtrczJaBMI/AAAAAAAAAF8/0E6LIjOvrjw/s1600/Skyrim_DragonSpire.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/-qHV9hf9cCDY/TrtrczJaBMI/AAAAAAAAAF8/0E6LIjOvrjw/s200/Skyrim_DragonSpire.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Skyrim brings in several aspects which have put gamers on their toes, waiting anxiously.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Dragons&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Okay okay, that's not all of course. The graphics are better and there are all sorts of skills and the world's more beautiful etc., but above all, the dragons represent best what's exciting about Skyrim.&lt;br /&gt;
&lt;br /&gt;
Unlike traditional NPCs (Non-Player Characters), these dragons are not scripted. The dragons fly in and destroy villages randomly causing the player distress in the most unexpected places. Other hostile NPC mobs are also done in this way, letting you have a more lively world. No doubt, I would expect the game to be rather resource intensive.&amp;nbsp;The idea is truly awesome but it is still limited to your single player world.&lt;br /&gt;
&lt;br /&gt;
I started wondering about what it would be like, if an MMO could exist where what you do actually matters, like in the Elder Scrolls series. &lt;a href="http://www.guildwars2.com/en/"&gt;Guild Wars 2&lt;/a&gt; is a pioneer in this aspect. Ever since I viewed the &lt;a href="http://www.youtube.com/watch?v=35BPhT-KI1E"&gt;GW2 Manifesto Trailer&lt;/a&gt;, I have been looking forward to trying the game out. The most exciting idea is what I stated earlier: a world where every single thing done by a player affects the world as a whole. They tagged this a 'dynamic world' and this, would truly bring about the most immersive gaming experience known to man.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Designing a MMO&lt;/h2&gt;This is all rosy and up till now I have not mentioned anything new. Now I'll let you into my train of thoughts...&lt;br /&gt;
&lt;br /&gt;
Designing games is great but there is a much standardised procedure for MMOs and it is difficult for new directions to be adopted in game development. This is because there are just too many elements to a game and each element takes a colossal amount of work and time to be done. There's the whole artworks bit which alone takes up many man hours. Then there's the music which is a key part of gameplay. There's also the story writing which has to be altered all the time as it affects and gets affected by all of the other elements. There's the promotion as games do not work without players, as well as working on maintaining your previous games' fans who make up for a large percentage of your new game's publicity and purchases.&lt;br /&gt;
All of the elements mentioned so far are non-technical and where the works of the technical hermits go, more complications arise. Modern games are required to be attractive and realistic. This pushes for the need for a realistic and high performance Physics engine, as well as a high performance graphics engine which are worth years and years of work. Then there's the game interface design and coding, the multiplayer networking support, the website for all extra-game features such as trading and usage of markets, and one of the most important bits: the carrying out of the plot, which requires the coding of all NPCs, towns, quests, items, and more.&lt;br /&gt;
&lt;br /&gt;
The previous paragraph is not even the whole scene!&lt;br /&gt;
&lt;br /&gt;
As you can witness, creating a modern game is definitely a challenging job. I would like to shift my focus on a few elements and look back to a movie which I greatly enjoyed watching, The Matrix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Matrix&lt;/h2&gt;I shouldn't need to explain what The Matrix is about and why it was such a success. If you would like to know more about The Matrix Trilogy, visit the &lt;a href="http://en.wikipedia.org/wiki/The_Matrix"&gt;wiki article&lt;/a&gt;. As we all know, The Matrix which is shown in the movie, is a system which the machines built to harvest our body's energy with heat being named as the main source (&lt;a href="http://www.sciforums.com/Matrix-and-the-third-law-of-thermodynamics-t-36955.html"&gt;ridiculous&lt;/a&gt;, but not the point). Apart from being a human farm, The Matrix is also a system into which humans are 'plugged' into, allowing them to live a virtual life with others which are plugged in. The Matrix decides what happens in the world but those that are 'plugged in', including not only the humans but programs as well, are able to make lasting changes to the world, much like our real world.&lt;br /&gt;
&lt;br /&gt;
I was wondering what it would be like if The Matrix was applied to game design. A sandbox world with some basic terrain, such as the Earth could be created and the players would be logged into the world and allowed to make changes to it. Now of course, the available tools, the culture, the settlements and many other elements of the world must be created to provide a completed starting world. But I would like to focus more on the act of 'plugging in' here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Matrix in MMOs&lt;/h2&gt;MMO games work in the following way. You download most of the necessary graphics and quest details then log into the world where there are scripted entities standing around (NPCs), urging you to do the most random acts. The act of the NPCs are dealt by the server but the movements and actions of your own character is controlled by yourself. Since the only control you have is on your own player, the control over the NPCs, time, weather and such are done by a central governor. Players are in a way, 'plugged in' to the world which is run by this governor. This one governor has many tasks to deal with including full control over NPCs.&lt;br /&gt;
&lt;br /&gt;
In the perspective of The Matrix, NPCs are merely programs. They can think and act freely but are restricted by a set of laws of Physics which is defined by the architect. Some programs however, are able to break through these set of rules and seize control over elements of the world. This, I believe is how a MMO world could be constructed.&lt;br /&gt;
&lt;br /&gt;
A central governor would still be necessary, but NPCs would be 'plugged in'. They would calculate their own actions and reactions which are limited by a set of rules set down by the governor. Their acts would be conveyed to the governor, who would in turn broadcast it to selected other NPCs and players who are affected. One would be able to produce a very modular game architecture in this way.&lt;br /&gt;
&lt;br /&gt;
Selecting a game server to connect to would be completely un-necessary. You would merely connect to different in-game regional nodes and your actions would be processed individually by entities which are affected. One central server or cluster would not need to calculate the Physics of several thousand NPCs, but would instead tell the NPCs about interactions which the NPC should register and react to.&lt;br /&gt;
&lt;br /&gt;
It isn't just NPCs where this Matrix idea can be implemented. Trees could also be put into a separate server and/or process where each individual tree is told the flow of air around it. The tree would the only need to tell the players in the vicinity which way it is swaying. An orc could roll down the hill, getting damaged in various spots while dropping some gear. The player and governor would not need to calculate any part of this process since the orc would determine what happens on its own, in an isolated process/server, basing all calculations on the rules set out by the governor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Last Words&lt;/h2&gt;I may, of course, be stating what is already being done. I am in no way knowledgeable of NPC architecture and how MMOs work under-the-hood. It is still interesting however, to consider what could potentially be possible if NPCs could be dealt in a similar way as human players are dealt with. Yes, we do possess intelligence and AI has a long way to go. However, even simple intelligence, when implemented to each element of a MMO world in an isolated manner, would bring about a much more lively and interesting world for gamers to play in.&lt;br /&gt;
&lt;br /&gt;
I do realise that this is not an easy task in reality and the capital required to run a large enough cluster of servers for a small enough world would make the implementation infeasible in many ways. One can still wonder what possibilities there are though...&lt;br /&gt;
&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=W1ISWgKcCa8:FwXDYNmjMmc:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=W1ISWgKcCa8:FwXDYNmjMmc:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=W1ISWgKcCa8:FwXDYNmjMmc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=W1ISWgKcCa8:FwXDYNmjMmc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/W1ISWgKcCa8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/93281644358619293/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/11/skyrim-and-musings-about-putting-matrix.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/93281644358619293?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/93281644358619293?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/W1ISWgKcCa8/skyrim-and-musings-about-putting-matrix.html" title="Skyrim and musings about putting The Matrix in an MMO" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-qHV9hf9cCDY/TrtrczJaBMI/AAAAAAAAAF8/0E6LIjOvrjw/s72-c/Skyrim_DragonSpire.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://www.swook.net/2011/11/skyrim-and-musings-about-putting-matrix.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUBQXY4eSp7ImA9WhRSGUs.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-4026399938297344973</id><published>2011-11-04T05:50:00.000Z</published><updated>2011-11-22T12:17:30.831Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-22T12:17:30.831Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="UCI Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="UCI" /><title>Benefits of a Custom UCI Launcher</title><content type="html">In my &lt;a href="http://www.swook.net/2011/11/cowons-flash-uci-structure.html"&gt;previous post&lt;/a&gt; concerning the way UCIs are implemented in Cowon's mp4 players, I touched upon the potential of the UCI launcher movie (or rather, the shortcomings). I would like to discuss more about what the launcher does and would like to introduce to you what one could do to improve your Cowon experience.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Jlh0oZXDNMM/TrNb_VLLgII/AAAAAAAAAFQ/J89DAVf4NhE/s1600/j3ui.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="191" src="http://3.bp.blogspot.com/-Jlh0oZXDNMM/TrNb_VLLgII/AAAAAAAAAFQ/J89DAVf4NhE/s400/j3ui.jpg" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;The different default UCIs of the Cowon J3, served to you by the launcher (Image courtesy of Cowon)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
As you probably are aware of by now, a&amp;nbsp;&lt;b&gt;launcher.swf&lt;/b&gt;&amp;nbsp;file located in \&lt;i&gt;\System\Flash UI\&lt;/i&gt;&amp;nbsp;allows you to load a custom launcher. The launcher loads your UCIs for you and also lets you change between UCIs.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-MN25cgG27D0/TrNbf9XSXKI/AAAAAAAAAFI/RCWW-xoQm2c/s1600/bgchoose.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="106" src="http://3.bp.blogspot.com/-MN25cgG27D0/TrNbf9XSXKI/AAAAAAAAAFI/RCWW-xoQm2c/s200/bgchoose.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
An additional hidden feature is the changing of the wallpaper, which could be misunderstood as being done by the firmware.&lt;br /&gt;
The wallpaper choosing menu for the picture UI for the Cowon J3 is shown on the right, marked with a red box.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A few functions are shown as being available via Cowon's sample UCI sources. These functions deal with detecting key inputs (buttons on your player), scroll `TextField`s, set popup `MovieClip`s and all sorts of jazz.&lt;br /&gt;
There are however many many undocumented functions available via the launcher which one can only find out by decoding the default &lt;i&gt;launcher.swf&lt;/i&gt; which requires quite a few steps.&lt;br /&gt;
By writing a custom launcher, the minimal benefit would be that these functionalities would be exposed for new UCIs to make use of. This would increase UCI development speed and allow for less coding and more design.&lt;br /&gt;
&lt;br /&gt;
"Surely though", you're thinking, "those few things aren't worth a blog post?".&lt;br /&gt;
&lt;br /&gt;
Well of course not.&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;br /&gt;
&lt;embed height="240" src="http://cdn.swook.net/Demo/launcher_transition.swf" style="float: left; margin: 0em 1em;" width="136"&gt;&lt;/embed&gt;Yes, to the left of this chunk of text, you are seeing the next generation of UCI switching. This demo flash movie is unfortunately not a reality yet and is simply a mockup. However, I hope that it shows you what could be done effectively.&lt;br /&gt;
&lt;br /&gt;
There are a total of 7 transition effects on display of which about 2 are repeats. This is because the moving left/right up/down would depend on the 'level' of the UCI. (ie. mainmenu UCIs would be of a 'higher' level and would move left/up.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hopefully, this small clip has got you excited. "What else? Tell me more!" I hear you shout.&lt;br /&gt;
&lt;br /&gt;
Apart from giving you a smoother experience between UCIs, a modified launcher can also provide some shared elements such as a shared header bar for the player status, a shared notification system, a shared settings interface and more.&lt;br /&gt;
You would also get a significant boost in UCI loading. This is because UCIs coded with the launcher's framework would be able to skip the time-consuming steps of checking states.&lt;br /&gt;
&lt;br /&gt;
In the perspective of a developer, you would have a vast array of simple methods to use without worry of performance loss. You would also receive more tools as the launcher receives added features. Widget sets could be shared across different UCIs as well. Simply put, you can do &lt;b&gt;anything&lt;/b&gt;&amp;nbsp;more easily and quickly.&lt;br /&gt;
What does this mean for users? More UCIs, More Choice, a Better Experience.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now... getting that launcher is something we'd want to get onto doing right?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;If you wish to take a look at the source for the mockup movie, &lt;a href="http://cdn.swook.net/Demo/launcher_transition.zip"&gt;download it here&lt;/a&gt;.&lt;/span&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=LPdbaixreg8:P91CMrWzXN4:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=LPdbaixreg8:P91CMrWzXN4:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=LPdbaixreg8:P91CMrWzXN4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=LPdbaixreg8:P91CMrWzXN4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/LPdbaixreg8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/4026399938297344973/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/11/benefits-of-custom-uci-launcher.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/4026399938297344973?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/4026399938297344973?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/LPdbaixreg8/benefits-of-custom-uci-launcher.html" title="Benefits of a Custom UCI Launcher" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-Jlh0oZXDNMM/TrNb_VLLgII/AAAAAAAAAFQ/J89DAVf4NhE/s72-c/j3ui.jpg" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://www.swook.net/2011/11/benefits-of-custom-uci-launcher.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUCRno4cCp7ImA9WhRSGUs.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-1965411317656331042</id><published>2011-11-02T10:13:00.000Z</published><updated>2011-11-22T12:17:47.438Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-22T12:17:47.438Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cowon" /><category scheme="http://www.blogger.com/atom/ns#" term="UCI Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="UCI" /><category scheme="http://www.blogger.com/atom/ns#" term="Flash" /><title>Cowon's Flash UCI Structure</title><content type="html">As mentioned in &lt;a href="http://www.swook.net/2011/10/cowon-and-uci-design.html"&gt;my previous post&lt;/a&gt; about Cowon's support for UCIs and the need for a UCI framework, users of Cowon's mp4 players can apply community-made custom user interfaces to their players with a few easy steps. Designing those interfaces requires a lot of work, however.&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-5ydFNY7yZoo/TrEDhWUMlUI/AAAAAAAAAE4/BVzgCF6W-rY/s1600/cowonfilestructure.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="179" src="http://2.bp.blogspot.com/-5ydFNY7yZoo/TrEDhWUMlUI/AAAAAAAAAE4/BVzgCF6W-rY/s320/cowonfilestructure.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Cowon's UCI File Structure&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
If you have used any of the UCIs, or CCUIs (Community-Created User Interfaces) as I like to say, you will know that you can usually install your own UCIs by simply dropping a few &lt;i&gt;.swf&lt;/i&gt;&amp;nbsp;files into the folder, &lt;i&gt;System/Flash UI/&lt;/i&gt;&amp;nbsp;and that the UCI settings can usually be found in &lt;i&gt;System/Flash UI/SOL/&lt;/i&gt;&amp;nbsp;as files ending with the extension, &lt;i&gt;.sol&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
If you have been around for a while, you may also know about the existence of &lt;i&gt;launchers&lt;/i&gt;&amp;nbsp;which are named as &lt;i&gt;launcher.swf&lt;/i&gt;&amp;nbsp;and placed in &lt;i&gt;System/Flash UI/&lt;/i&gt;. However, you may not know what they do precisely and I'll try to explain that in this post.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
&lt;hr /&gt;
&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-QzqIs9nqZTM/TrEFb6IRSeI/AAAAAAAAAFA/NXWQiWy3Xko/s1600/cowonsystemstructure.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="169" src="http://4.bp.blogspot.com/-QzqIs9nqZTM/TrEFb6IRSeI/AAAAAAAAAFA/NXWQiWy3Xko/s320/cowonsystemstructure.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A diagram omnipresent in Cowon's UCI guides&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
The Graphical User Interface (GUI) system for UCI-supported Cowon devices are structured in the way shown in the diagram to the left.&lt;br /&gt;
&lt;br /&gt;
There's the 'real code' done in C, which does all of the important jobs such as making the music play - making sure that your player does what it should.&lt;br /&gt;
&lt;br /&gt;
Then there's the bit which deals with user input and what the user gets to see on his/her screen, which is done by the Flash Engine.&lt;br /&gt;
&lt;br /&gt;
Then on top of that flash engine, you find several flash movies running which help you communicate with the actual machine, letting you control playback, display brightness, etc.&lt;br /&gt;
&lt;br /&gt;
The smart thing which Cowon did, was to let users create their own flash movies to use as their own custom interfaces. The silly bit they did was to provide their source code in an incomprehensibly confusing and unstructured format, making the learning curve very steep for aspiring UCI developers.&lt;br /&gt;
&lt;br /&gt;
Another smart thing that Cowon has done, is to split the flash level into two bits. The launcher flash movie and the UI movies. The splitting on its own cannot be called the smartest thing done by man, but by putting the 'launcher' as a flash movie, they allowed themselves to code more quickly and unintentionally gave power to the users to change the way their UIs are loaded and handled. The silly thing about this is that there is no documentation about writing a launcher, and the source cannot be obtained without decoding the &lt;i&gt;launcher.swf&lt;/i&gt; which sits in the firmware update resource binary. This is why there have not been any custom launchers so far, apart from a few which only had their framerates tweaked.&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;br /&gt;
All this &lt;i&gt;launcher&lt;/i&gt; and &lt;i&gt;UI&lt;/i&gt; jibber jabber is probably boring you out of your mind. What I was trying to tell you about is the way to view how the UI is dealt with in these players.&lt;br /&gt;
&lt;br /&gt;
To put it in simple terms, there's a massive machine which we cannot see the inside of called the 'Low Level' code. Then there's another machine which talks to the massive 'Low Level code machine' called the 'Flash Engine'. The flash engine has a screen attached to it and when you switch the player on, the 'Low Level code machine' hums waking the 'Flash Engine' up. Then the 'Flash Engine' hums and loads up &lt;i&gt;launcher.swf&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
From then on, the launcher is the one dealing with you, the user, directly.&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;br /&gt;
In the end, every so-called UCI becomes a full-screen widget which the launcher loads and unloads.&lt;br /&gt;
&lt;br /&gt;
"So what?", you ask me.&lt;br /&gt;
&lt;br /&gt;
Well... you see, when people write their UCIs, they have to write it as if it's a standalone application. They write code which talks to the flash engine directly and every UCI ends up having to do a few things inevitably:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Check the state of the player by calling a gazillion commands to make sure you're showing it right.&lt;/li&gt;
&lt;li&gt;Write a billion functions and methods which are used by everyone anyway.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
"But... what about the launcher??"&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Well it sits there... loads and unloads UCIs... and it also has a few functions which Cowon's UCIs use. Yeah it could know everything and save the hassle of no. 1 by telling the UCIs what it should display when it loads up, but it just sits there like it should, y'know.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
"Well uhm... I suppose that's what it should do. It's called a &lt;i&gt;launcher&lt;/i&gt;&amp;nbsp;afterall..."&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=ccd0OpR0waY:FYO1l1zi8ik:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=ccd0OpR0waY:FYO1l1zi8ik:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=ccd0OpR0waY:FYO1l1zi8ik:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=ccd0OpR0waY:FYO1l1zi8ik:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/ccd0OpR0waY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/1965411317656331042/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/11/cowons-flash-uci-structure.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/1965411317656331042?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/1965411317656331042?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/ccd0OpR0waY/cowons-flash-uci-structure.html" title="Cowon's Flash UCI Structure" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-5ydFNY7yZoo/TrEDhWUMlUI/AAAAAAAAAE4/BVzgCF6W-rY/s72-c/cowonfilestructure.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://www.swook.net/2011/11/cowons-flash-uci-structure.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AMR3w_cSp7ImA9WhRREk8.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-6314546641166128446</id><published>2011-10-31T08:57:00.000Z</published><updated>2011-11-25T14:03:06.249Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T14:03:06.249Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="synclient" /><category scheme="http://www.blogger.com/atom/ns#" term="Synaptics" /><title>Linux | Tweak and save your Synaptics Settings</title><content type="html">Those who use a &lt;a href="http://linux.die.net/man/5/synaptics"&gt;Synaptics touchpad&lt;/a&gt; on Linux may experience some problems. Most likely, you will not be able to access any of those &lt;i&gt;advanced&lt;/i&gt;&amp;nbsp;features such as emulating two finger scrolling. Recently, support was added so that you can choose that option but the more detailed settings of minimum finger pressure (EmulateTwoFingerMinZ) and the minimum touch detection width for two finger emulation (EmulateTwoFingerMinW) for example cannot be changed.&lt;br /&gt;
&lt;br /&gt;
The fore-mentioned settings are just a couple settings &lt;a href="http://www.x.org/archive/X11R7.5/doc/man/man4/synaptics.4.html#toc3"&gt;among many&lt;/a&gt; which should be tweaked for optimal computing comfort, which all Linux users strive to achieve. The road towards this &lt;a href="https://wiki.archlinux.org/index.php/Touchpad_Synaptics#Configuration"&gt;can vary&lt;/a&gt; and there are solutions which are easier than others. I'd like to explain to you, the easy solution.&lt;br /&gt;
&lt;br /&gt;
The easy solution is to use &lt;i style="font-weight: bold;"&gt;&lt;a href="http://linux.die.net/man/1/synclient"&gt;synclient&lt;/a&gt;&lt;/i&gt;, a programme which lets you edit Synaptics settings on the fly. synclient has the advantage of being ridiculously easy to use and the disadvantage of not making your changes persistent (permanent). I have written a script to solve this problem.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;synclient Settings Saver&lt;/h2&gt;Enter the &lt;b&gt;&lt;a href="https://github.com/swook/synclient-settings-saver"&gt;synclient Settings Saver&lt;/a&gt;&lt;/b&gt;, a script which saves your synclient settings and applies it on startup.&lt;br /&gt;
The following are the steps needed to use this script.&lt;br /&gt;
&lt;br /&gt;
First, install synclient if you have not done so:&lt;br /&gt;
&lt;pre class="lang-sh"&gt;sudo apt-get install synclient&lt;/pre&gt;&lt;br /&gt;
View your current settings with:&lt;br /&gt;
&lt;pre class="lang-sh"&gt;synclient -l&lt;/pre&gt;&lt;br /&gt;
and edit your settings with:&lt;br /&gt;
&lt;pre class="lang-sh"&gt;synclient &amp;lt;setting&amp;gt;=&amp;lt;value&amp;gt;&lt;/pre&gt;&lt;br /&gt;
If you want to change the value of &lt;b&gt;MinSpeed&lt;/b&gt; to &lt;b&gt;0.1&lt;/b&gt; for example, do:&lt;br /&gt;
&lt;pre class="lang-sh"&gt;synclient MinSpeed=0.1&lt;/pre&gt;&lt;br /&gt;
Once you're happy with your settings, go to your favourite folder and &lt;a href="https://raw.github.com/swook/synclient-settings-saver/master/update-synclient-settings.sh"&gt;download and run my script&lt;/a&gt; using:&lt;br /&gt;
&lt;pre class="lang-sh"&gt;wget https://raw.github.com/swook/synclient-settings-saver/master/update-synclient-settings.sh
bash update-synclient-settings.sh&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
From now on, your settings will be applied when you login to your Linux session.&lt;br /&gt;
If you ever make any changes via synclient, run my script again.&lt;br /&gt;
For a detailed set of descriptions for the available options, visit &lt;a href="http://www.x.org/archive/X11R7.5/doc/man/man4/synaptics.4.html#toc3"&gt;this site&lt;/a&gt;.&lt;br /&gt;
If you have doubts about my script, view the source at &lt;a href="https://github.com/swook/synclient-settings-saver"&gt;GitHub&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Happy two-finger-scrolling!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=348oUmGALz8:4Ev2wUA1pjo:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=348oUmGALz8:4Ev2wUA1pjo:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=348oUmGALz8:4Ev2wUA1pjo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=348oUmGALz8:4Ev2wUA1pjo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/348oUmGALz8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/6314546641166128446/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/10/linux-tweak-and-save-your-synaptics.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/6314546641166128446?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/6314546641166128446?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/348oUmGALz8/linux-tweak-and-save-your-synaptics.html" title="Linux | Tweak and save your Synaptics Settings" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/10/linux-tweak-and-save-your-synaptics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUDQXg9eSp7ImA9WhdaGUo.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-3442140665904872357</id><published>2011-10-30T10:00:00.000Z</published><updated>2011-10-30T11:14:30.661Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-30T11:14:30.661Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Human" /><category scheme="http://www.blogger.com/atom/ns#" term="Books" /><category scheme="http://www.blogger.com/atom/ns#" term="Others" /><category scheme="http://www.blogger.com/atom/ns#" term="HHGTTG" /><title>Being Human</title><content type="html">I've been reading through a trilogy called &lt;a href="http://en.wikipedia.org/wiki/The_Hitchhiker's_Guide_to_the_Galaxy"&gt;The Hitchhiker's Guide to the Galaxy&lt;/a&gt;. Seeing how it is a must-read for all budding Physics applicants for UK universities, I am a few years late in reading the books and it really shows that I was in some ways rather unprepared for my course.&lt;br /&gt;
&lt;br /&gt;
While a bit late, reading these few books by &lt;a href="http://en.wikipedia.org/wiki/Douglas_Adams"&gt;Douglas Adams&lt;/a&gt;&amp;nbsp;has truly been a remarkably enjoyable experience. I do not want to reveal any spoilers so I won't go into specifics but would rather like to talk about some musings I had while thinking about the series.&lt;br /&gt;
&lt;br /&gt;
I have yet to finish the 5-books trilogy and have gone up to almost finishing the third book, &lt;i&gt;Life, The Universe and Everything&lt;/i&gt;, but I have still been able to grasp what usually seems to happen. There is a man called Arthur Dent, a Beltegeusean hitch-hiker named Henry Ford, a pompous two-headed man called Zaphod Beeblebrox who happens to be Ford's cousin, and a few other characters who somehow end up working towards saving the whole universe while having no idea at all about what and why they are doing what they are doing. The books are riddled with obvious and implicit humour and there are often times where I just cannot stop smiling. The smiling is often caused by the odd acts the characters put on. They are all rather selfish and often desert each other, they also have very strong opinions causing them to fight and mess things up, and most of them are very nonchalant about most of the odd situations they are put in. But apart from all of these odd behaviours, the most commonly used bit of humour is how these main characters, when meeting and being threatened by enemies, respond by posing some seemingly obvious logic questions, with the targeted enemy becoming instantly confused.&lt;br /&gt;
&lt;br /&gt;
While the traits of all of the characters in the series is most likely set up to make the story most enjoyable, when you think twice about them, you will notice that us human beings share all if not most of their traits. We merely hide them well (or we think so). Selfishness, laziness, idiocy, and while not mentioned often, comradeship, love and such are all portrayed by the participating organisms of the series. Since the book is written for us human beings to read and relate to, all aliens and humans act like humans. I say this lightly, but what do we mean when we say 'human'?&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-nBQcuYggUqA/TqwhAk1FU5I/AAAAAAAAAEw/MptMjxZ2Dlc/s1600/apeman.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="133" src="http://1.bp.blogspot.com/-nBQcuYggUqA/TqwhAk1FU5I/AAAAAAAAAEw/MptMjxZ2Dlc/s200/apeman.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
The word &lt;b&gt;human&lt;/b&gt;&amp;nbsp;is used in many different words, situations and context. There's the word &lt;b&gt;humanity&lt;/b&gt;&amp;nbsp;which refers to the human species. It is however also used in exclamations such as: &lt;i&gt;Oh the humanity!&lt;/i&gt;&amp;nbsp;where it is used in a similar meaning to &lt;b&gt;humane&lt;/b&gt;, which is often understood as having compassion. There's also &lt;b&gt;humanoid&lt;/b&gt;, a word used often in &lt;i&gt;The Hitchhiker's Guide to the Galaxy&lt;/i&gt;&amp;nbsp;to describe organisms which have human-like physical features. There's also the popular word &lt;b&gt;superhuman&lt;/b&gt;&amp;nbsp;which refers to fictional beings which have spectacular powers (those should really be called &lt;b&gt;extra-human&lt;/b&gt;&amp;nbsp;since the &lt;i&gt;super&lt;/i&gt;&amp;nbsp;in &lt;i&gt;superhuman&lt;/i&gt;&amp;nbsp;does not work like &lt;i&gt;super&lt;/i&gt;&amp;nbsp;does in &lt;i&gt;supersonic&lt;/i&gt;&amp;nbsp;since supersonic refers to speeds greater than the speed of sound while superhuman refers to beings which are not necessarily greater or better than others.).&lt;br /&gt;
&lt;br /&gt;
What is &lt;b&gt;being human&lt;/b&gt;&amp;nbsp;then? I hear you say that it is tightly related to &lt;b&gt;being humane&lt;/b&gt;. Then what's &lt;b&gt;being humane&lt;/b&gt;? Oh you're telling me something again... ah so it's &lt;b&gt;having human traits&lt;/b&gt;? So what are &lt;b&gt;human traits&lt;/b&gt;? Compassion only? No, not at all, human traits must include so much more! We often encourage 'good' acts by promoting acts of love and selflessness but as we all know people are very evil in general. Surely, with so many evil people around, being 'bad' must also be part of standard human traits?&lt;br /&gt;
&lt;br /&gt;
"But this is just rubbish!", I hear you say, "surely you must accept the commonly accepted meaning of &lt;b&gt;being human&lt;/b&gt;&amp;nbsp;which refers to being a loving, caring, compassionate person? Surely by such extreme generalisations you are clearly making ANYTHING human!". Well I see what you mean. If my argument was to carry on, any living and thinking creature could be human. The flaw in this rebuttal however, is that we do not yet know if there are creatures which have our human traits as a subset of their own traits. We do not know also, that all of our traits combined are the only possible traits available for all thinking creatures. I hear you choke at my mention of &lt;i&gt;thinking creatures&lt;/i&gt;&amp;nbsp;but that's a debate for another time...&lt;br /&gt;
&lt;br /&gt;
As for the matter at hand of defining what a human is, I believe that it is impossible to continue further. Afterall, we do not know much about ourselves. It is also impossible to enforce any different meaning onto the connotations of &lt;b&gt;being human&lt;/b&gt;&amp;nbsp;when it is the most abused reason for condemning the bad guys: those who perform inhuman behaviours to the disadvantage of others. There are also thousands of the so-called traits which I could list and the flaw with doing so would be that it would be almost every emotion or property we have ever thought of. In the end, all words which we use and know come from us!&lt;br /&gt;
&lt;br /&gt;
To stop the endless loop of confusion, I must stop this post here right now.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=Fnp424Aj3-8:mtirv_KjNg8:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=Fnp424Aj3-8:mtirv_KjNg8:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=Fnp424Aj3-8:mtirv_KjNg8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=Fnp424Aj3-8:mtirv_KjNg8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/Fnp424Aj3-8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/3442140665904872357/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/10/being-human.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/3442140665904872357?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/3442140665904872357?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/Fnp424Aj3-8/being-human.html" title="Being Human" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-nBQcuYggUqA/TqwhAk1FU5I/AAAAAAAAAEw/MptMjxZ2Dlc/s72-c/apeman.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/10/being-human.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQMQXY8cSp7ImA9WhRSGUs.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-346990620824245046</id><published>2011-10-26T11:00:00.000+01:00</published><updated>2011-11-22T12:19:40.879Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-22T12:19:40.879Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Blogger" /><category scheme="http://www.blogger.com/atom/ns#" term="HTTP" /><category scheme="http://www.blogger.com/atom/ns#" term="Missing Files Host" /><title>[Blogger's Missing Files Host's Missing Characters]</title><content type="html">Previously, while talking about the &lt;a href="http://www.swook.net/2011/10/blogger-374-vps-speedy-mirror-cdn-bliss.html"&gt;setting up of this blog&lt;/a&gt;, I mentioned how Blogger's "Missing Files Host" feature was of great appeal.&lt;br /&gt;
&lt;br /&gt;
It is wonderful really since it lets you seemingly 'host' files on your blog while actually being able to keep it elsewhere. It lets you upload files in your preferred method then lets you share links which seemingly originate from your blog. This helps you drive traffic to your blog and also gives the reader a more integrated feeling. Coupled with CDN, it is just wonderful.&lt;br /&gt;
&lt;br /&gt;
There are quite a few massive caveats however.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;






302 Redirect&lt;/h2&gt;
What Blogger does is that it coughs up the HTTP status code 302 when you request a file which does not exist on yourblog.blogspot.com. This code used to be called "Moved Temporarily" and is &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.3"&gt;now called "Found"&lt;/a&gt;. What does this mean?&lt;br /&gt;
&lt;br /&gt;
What search engines will do when they encounter this code is that they will discard the 'link' 99% of the time. They are right in doing so though! Afterall, this link is temporary right? Surely the importance of a temporary link is not very high! The owner of the link probably wants it hidden.&lt;br /&gt;
&lt;br /&gt;
The problem this causes is that you cannot have content hosted in your 'Missing Files Host' 'linked' to your blog. When I say 'link' I mean, linked in the search engine database ecosystem and this is the only linking which is really valid.&lt;br /&gt;
&lt;br /&gt;
Is this truly a terrible problem? Not really if you are only serving files for people to download... but yes if you are trying to serve content. For example, a pdf file with your research paper should be connected tightly with your blog post announcing that paper.&lt;br /&gt;
&lt;br /&gt;
I do understand the thought behind using a 302 redirect. Let's assume for a moment that Blogger uses code &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2"&gt;&lt;span id="goog_821095313"&gt;&lt;/span&gt;301 (Moved Permanently)&lt;span id="goog_821095314"&gt;&lt;/span&gt;&lt;/a&gt; to serve the 'missing files'. A user could possibly upload a file named &lt;b&gt;My-Diary&lt;/b&gt;&amp;nbsp;into a directory called &lt;b&gt;2011/10&lt;/b&gt;&amp;nbsp;in their missing files host. Once someone tries to access that file, the browser will receive the HTTP status code, 301. The browser remembers that all requests for &lt;b&gt;http://blog.tld/2011/10/My-Diary&lt;/b&gt; should be redirected to the missing files host. A few days later, the user writes a post called &lt;b&gt;My Diary&lt;/b&gt;&amp;nbsp;which can be accessed via&amp;nbsp;&lt;b&gt;http://blog.tld/2011/10/My-Diary&lt;/b&gt;. Uh-oh... the post does not show up since the browser continues to redirect you to the file called &lt;b&gt;My-Diary&lt;/b&gt;!&lt;br /&gt;
&lt;br /&gt;
However, I believe that this is really not a big problem. Surely the software can simply return different status codes for the different requests? If a requested file is or could be part of Blogger, return a 302. If a request URL has nothing to do with Blogger, return 301! Simple! Just a simple file extension check even, would help with the situation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;





Missing Files Redirection cannot deal with strange characters&lt;/h2&gt;
What? I hear you wonder.&lt;br /&gt;
&lt;br /&gt;
Yes, not all files can be part of this wonderful scheme called "Missing Files Host". For some reason, Blogger's redirection code has flaws! If I have a file named &lt;b&gt;!2#$![].zip&lt;/b&gt;, I would very much like it redirected but no, Blogger throws an error.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ukbIsKIFHng/Tqe4kbbHm9I/AAAAAAAAACI/k4nnwWyF-_U/s1600/badrequest400.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-ukbIsKIFHng/Tqe4kbbHm9I/AAAAAAAAACI/k4nnwWyF-_U/s1600/badrequest400.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;The page shown when accessing &lt;a href="http://www.swook.net/lunar/Metro/[j3]metro_2_5.zip"&gt;http://www.swook.net/lunar/Metro/[j3]metro_2_5.zip&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
This error can be confirmed since trying to access the same file, renamed to &lt;b&gt;j3_metro_2_5.zip&lt;/b&gt;&amp;nbsp;worked perfectly.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1"&gt;Error 400&lt;/a&gt; is stated as being:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.&lt;/blockquote&gt;
So yes, basically, Blogger cannot handle the URL!&lt;br /&gt;
Why shouldn't it though?&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=5VffNsctvVA:6eeQPsgbUf4:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=5VffNsctvVA:6eeQPsgbUf4:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=5VffNsctvVA:6eeQPsgbUf4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=5VffNsctvVA:6eeQPsgbUf4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/5VffNsctvVA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/346990620824245046/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/10/bloggers-missing-files-hosts-missing.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/346990620824245046?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/346990620824245046?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/5VffNsctvVA/bloggers-missing-files-hosts-missing.html" title="[Blogger's Missing Files Host's Missing Characters]" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-ukbIsKIFHng/Tqe4kbbHm9I/AAAAAAAAACI/k4nnwWyF-_U/s72-c/badrequest400.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/10/bloggers-missing-files-hosts-missing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcBRHg7eyp7ImA9WhRUFks.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-1700113876480329816</id><published>2011-10-24T11:00:00.000+01:00</published><updated>2012-01-27T10:27:35.603Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-27T10:27:35.603Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Oneiric Ocelot" /><category scheme="http://www.blogger.com/atom/ns#" term="NTFS" /><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>Slow NTFS-3G with Oneiric</title><content type="html">This is a short post to inform anyone if &lt;a href="http://en.wikipedia.org/wiki/NTFS-3G"&gt;ntfs-3g&lt;/a&gt; I/O has been painfully slow after &lt;a href="http://www.swook.net/2011/10/upgrading-to-oneiric-ocelot.html"&gt;upgrading to Oneiric Ocelot&lt;/a&gt; (Ubuntu 11.10).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
I have always relied rather heavily on the NTFS filesystem. This is because I am not 100% free from using Windows. While Windows is rather annoying to use, some programs such as Microsoft Office simply do not work on Linux. To keep the environment as similar as possible, I have always mounted my Windows partition and have used ntfs-3g, a NTFS driver for Linux to access my 'shared' files.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My &lt;i&gt;$HOME/Desktop/&lt;/i&gt; folder for instance, is &lt;a href="http://en.wikipedia.org/wiki/Symbolic_link"&gt;symlinked&lt;/a&gt; to &lt;i&gt;/mnt/windows/Users/Wookie/Desktop/&lt;/i&gt; so that my desktop can contain the same files on both *buntu and Windows. Now I do admit that this is not in any way an ideal method of doing what I wish to do, and I should really be using rsync for a safer 'syncing'. This has worked thus far though so I felt that I could keep it as it is.&lt;br /&gt;
&lt;br /&gt;
The problem arose when I noticed after almost a full week of Oneiric, that all of my browser downloads (which were downloading to &lt;i&gt;$HOME/Desktop/&lt;/i&gt;) were painfully slow. I was getting around 50kBps when I would usually get 500kBps. My write speed was somehow incredibly slow (read speeds were fine). It turned out that the problem was with ntfs-3g.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I tried the following:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;chkdsk via Windows&lt;/li&gt;
&lt;li&gt;Disk Defragmenter for all NTFS partitions&lt;/li&gt;
&lt;li&gt;Many hours of Googling for similar cases&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Not one of my Google results showed terrible write speeds with good read speeds. I did fortunately, find this &lt;a href="http://forums.gentoo.org/viewtopic-t-760625-start-0.html"&gt;forum post&lt;/a&gt; from the Gentoo Forums. It was here that I found a link to&amp;nbsp;&lt;a href="http://www.ntfs-3g.org/support.html#slow"&gt;http://www.ntfs-3g.org/support.html#slow&lt;/a&gt;&amp;nbsp;which was invalid. A quick Google got me the correct link:&amp;nbsp;&lt;a href="http://www.tuxera.com/community/ntfs-3g-faq/#slow"&gt;http://www.tuxera.com/community/ntfs-3g-faq/#slow&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
One of the suggested problems was the usage of the &lt;b&gt;sync&lt;/b&gt;&amp;nbsp;option while loading the partition. As can be seen in my &lt;a href="http://www.swook.net/2011/10/upgrading-to-oneiric-ocelot.html"&gt;Oneiric Update post&lt;/a&gt;, I had used the option, &lt;b&gt;sync&lt;/b&gt;&amp;nbsp;in my ntfs partition entry for &lt;i&gt;/etc/fstab&lt;/i&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class="lang-txt"&gt;/dev/sda2    /mnt/windows    ntfs-3g    sync,rw,user,auto,exec,utf8,uid=1000,gid=100    0    2&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Changing the entry to:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class="lang-txt"&gt;/dev/sda2    /mnt/windows    ntfs-3g    rw,user,auto,exec,utf8,uid=1000,gid=100    0    2
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
and re-mounting the partition with:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class="lang-sh"&gt;sudo umount /mnt/windows
sudo mount /mnt/windows&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
fixed the problem.&amp;nbsp;I was getting fast speeds of around 40MBps again!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You may be wondering why this has happened with an upgrade. This is because ntfs-3g introduced the 'sync' option only in a recent update! It is mentioned in the &lt;a href="http://www.tuxera.com/community/release-history/"&gt;changelog&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="lang-txt"&gt;STABLE Version 2011.1.15 (January 23, 2011)
        New: implemented the ‘sync’ mount option.&lt;/pre&gt;
&lt;br /&gt;
So silly me had been using a ghost option without realising it.&lt;br /&gt;
Just to make everything clearer, let me tell you about the sync option itself. The Linux &lt;a href="http://linux.die.net/man/8/mount"&gt;man page for &lt;i&gt;mount&lt;/i&gt;&lt;/a&gt;&amp;nbsp;tells us this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="lang-txt"&gt;sync
    All I/O to the file system should be done synchronously. In case of media with limited number of write cycles (e.g. some flash drives) "sync" may cause life-cycle shortening.&lt;/pre&gt;
&lt;br /&gt;
So there we go, it's a matter of how often 'write'-ing occurs and obviously, writing speeds in general would decrease if every single byte had to be written immediately (instead of in chunks). As Tuxera's support page mentions: "do not use &lt;b&gt;sync&lt;/b&gt;&amp;nbsp;unless you have a good reason".&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=DX63KTBZOwA:o9D3q8sZ1Yc:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=DX63KTBZOwA:o9D3q8sZ1Yc:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=DX63KTBZOwA:o9D3q8sZ1Yc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=DX63KTBZOwA:o9D3q8sZ1Yc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/DX63KTBZOwA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/1700113876480329816/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/10/slow-ntfs-3g-with-oneiric.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/1700113876480329816?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/1700113876480329816?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/DX63KTBZOwA/slow-ntfs-3g-with-oneiric.html" title="Slow NTFS-3G with Oneiric" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://www.swook.net/2011/10/slow-ntfs-3g-with-oneiric.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMCSH8-fCp7ImA9WhRSGUs.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-408980742481508546</id><published>2011-10-19T12:57:00.001+01:00</published><updated>2011-11-22T12:21:09.154Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-22T12:21:09.154Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CDN" /><category scheme="http://www.blogger.com/atom/ns#" term="Blogger" /><category scheme="http://www.blogger.com/atom/ns#" term="VPS" /><category scheme="http://www.blogger.com/atom/ns#" term="Missing Files Host" /><title>Blogger + $3.74 VPS + Speedy Mirror CDN = Bliss</title><content type="html">&lt;br /&gt;
When I set about to get this blog ready, I had a few decisions to make.&lt;br /&gt;
I'd like to explain why I have made the decisions I have made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;









Own Hosting vs Blogging Service&lt;/h2&gt;
First off, I had to decide between own-hosting and service hosting. What do I mean by those terms? Simply put, this was whether I wanted to host the blog software with my own hardware/software or rely on a company for the maintenance of my blog.&lt;br /&gt;
I had previously tried hosting my own&amp;nbsp;&lt;a href="http://www.wordpress.org/"&gt;Wordpress blog&lt;/a&gt;&amp;nbsp;and while maintenance was not too much of an issue and I was very happy, I quickly noticed that with greater freedom, I had the hassle of having too many choices. Among the many things I had to care about were:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Web server performance (inclusive of PHP performance)&lt;/b&gt;&amp;nbsp;- Does my blog load up quickly enough? Does it cause too much load?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Reliability&lt;/b&gt;&amp;nbsp;- Let's set up backups every hour just in case I need them. My server could burn, the hard drive could corrupt, anything could happen and the worst will always happen to my blog.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I found myself messing about with plugins and setting half of the time, adding this and that then eventually stripping most plugins out to increase performance.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
With the previous experience in mind (as well as previous forum hosting etc), I decided that I wanted my blog to be hassle-free. Sure, setting up and tweaking web servers is fun. It's fun bragging about my knowledge in&amp;nbsp;&lt;a href="http://news.ycombinator.com/item?id=518885"&gt;Nginx vs. Apache&lt;/a&gt;&amp;nbsp;and similar topics as well as boasting how my system is relatively fast compared to someone else's billion-dollar setup. However, the point of having a blog is to blog! There are literally hundreds of companies out there, asking you to jump into their arms for hassle free blogging. There were a few options I had yet again.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://assets.tumblr.com/images/logo.png?alpha&amp;amp;6" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://assets.tumblr.com/images/logo.png?alpha&amp;amp;6" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://www.tumblr.com/"&gt;&lt;b&gt;Tumblr&lt;/b&gt;&lt;/a&gt;, I had tried out very briefly in its early days but I was soon frustrated by the lack of functionality and extreme emphasis on looks. Yes, this was not too much of an issue since afterall, the content and delivery of content is of utmost importance right?&lt;br /&gt;
Sadly, Tumblr failed to satisfy in those aspects.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://4.bp.blogspot.com/-RnLUleEQ0vs/Tp6rAsD_uUI/AAAAAAAAAB0/Bf4N1JsRF6M/s1600/tumblroff.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="160" src="http://4.bp.blogspot.com/-RnLUleEQ0vs/Tp6rAsD_uUI/AAAAAAAAAB0/Bf4N1JsRF6M/s320/tumblroff.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="font-size: 11px;"&gt;This message could be seen almost daily&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
The above image was routine for my Tumblr blog and I quickly got fed up. I was not too much of a fan of the&amp;nbsp;&lt;a href="http://snapdragonconsultants.com/year-in-review/tumblr-v-twitter-micro-blogging-v-micro-messaging/"&gt;Twitter-like blogging system&lt;/a&gt;&amp;nbsp;as well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://s.wp.com/wp-content/themes/h4/i/logo-h-rgb.png?m=1308937825g" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="50" src="http://s.wp.com/wp-content/themes/h4/i/logo-h-rgb.png?m=1308937825g" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;a href="http://www.wordpress.com/"&gt;Wordpress.com&lt;/a&gt;&lt;/b&gt;&amp;nbsp;was a likely choice after Tumblr. They seemed to be doing things well and with their&amp;nbsp;&lt;a href="http://fatalerror.wordpress.com/2008/04/14/goodbye-litespeed-hello-nginx-wordpresscom/"&gt;hopping onto Nginx&lt;/a&gt;&amp;nbsp;(my webserver of choice), I had more of a reason to move in&amp;nbsp;right-away. There were a few hurdles and it did not seem likely that they would to be fixed or removed in the&amp;nbsp;foreseeable&amp;nbsp;future.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Custom domain support is&amp;nbsp;&lt;a href="http://en.support.wordpress.com/domain-mapping/register-domain/" style="font-weight: bold;"&gt;not free&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Content is not deployed via&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Content_delivery_network"&gt;CDN&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Caching configuration, backups etc is still user-side.&lt;/li&gt;
&lt;li&gt;Wordpress is coded in PHP (elaborated on later).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
You may be wondering: "You're getting it for free, you can't ask for too much!". It turns out I can.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://www.blogger.com/img/new-ui/blogger-logo-small.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://www.blogger.com/img/new-ui/blogger-logo-small.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;a href="http://www.blogger.com/"&gt;Blogger&lt;/a&gt;&lt;/b&gt;&amp;nbsp;is what I ended up going with. Being Google hosted meant that my blog would be maintained (for free) by the most skilled professionals and maintenance would be done well since publishers (bloggers) bring in revenue via AdSense. It also meant that my blog would be served as speedily as possible via Google's network of servers which far outperform any CDN service.&lt;br /&gt;
&lt;br /&gt;
Another decision-making fact was that Blogger is coded by Google. This means that the software consists mainly of C++ and Python in the back-end. Having stayed with a friend who is a Python fanatic as well as a Google intern, I had been affected and had started caring about the language used to write back-end softwares. (Not that I will be able to poke through the source-code.)&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;









$3.74 VPS + Speedy Mirror CDN&lt;/h2&gt;
While setting my Blogger blog up with my personal domain, I noticed an interesting feature which only Google engineers would be kind enough to include, a "missing files host". This feature basically allows one to have files hosted on the blog domain as Blogger will redirect requests to the&amp;nbsp;&lt;i&gt;missing files host&lt;/i&gt;&amp;nbsp;if the requested static file does not exist on the blog.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://4.bp.blogspot.com/-Tp8EGPLts48/Tp61avlc98I/AAAAAAAAAB8/P0mCAYUkh0k/s1600/missingfileshost.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="176" src="http://4.bp.blogspot.com/-Tp8EGPLts48/Tp61avlc98I/AAAAAAAAAB8/P0mCAYUkh0k/s400/missingfileshost.jpg" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="font-size: 11px;"&gt;Currently not working in the new interface, to set a missing files host you must switch to the old interface&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
While setting this feature up required me to switch away from the new glittering interface, I was impressed by the fact that it was being offered and was also glad since it was exactly what I had hoped for but not looked for. If I had wanted an equivalent feature, I would have had to setup a&amp;nbsp;&lt;a href="http://wiki.nginx.org/HttpCoreModule#try_files"&gt;try_files entry&lt;/a&gt;&amp;nbsp;in my Nginx server, making people go through my small VPS in Chicago in order to access my site.&lt;br /&gt;
&lt;br /&gt;
With one of the few 1gbps bandwidth budget VPSes provided by&amp;nbsp;&lt;a href="http://host90.com/"&gt;host90.com&lt;/a&gt;&amp;nbsp;serving my files, I could have all the features of a 'perfect' setup with a monthly cost of $3.74! (It had to be 1gbps bandwidth. No, I do not have a few million requests per second but yes, do I obsess about performance...)&lt;br /&gt;
&lt;br /&gt;
While thinking about ways to increase performance, I decided that I needed a good CDN service. This was because most of my latency was coming from the&amp;nbsp;&lt;a href="http://alexgorbatchev.com/SyntaxHighlighter/"&gt;SyntaxHighlighter&lt;/a&gt;&amp;nbsp;files hosted on my VPS that I was using to highlight code as I did in my&amp;nbsp;&lt;a href="http://www.swook.net/2011/10/upgrading-to-oneiric-ocelot.html"&gt;Oneiric Ocelot upgrade experience post&lt;/a&gt;. A brief search gave me quite a few CDN services I could make use of but many were costly for a small blog like mine.&lt;br /&gt;
&lt;br /&gt;
The service I settled for,&amp;nbsp;&lt;a href="https://www.speedymirror.com/"&gt;Speedy Mirror&lt;/a&gt;&amp;nbsp;provides 5GB of free CDN traffic for new users and lets you top-up for reasonable prices. I decided to settle for Speedy Mirror as I concluded that the free traffic would not compromise their performance. This is because of their reasonably priced upgrades. A few clicks with their simple interface and I was set. I had the following setup:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Missing Files Host - http://cdn.swook.net/&lt;/li&gt;
&lt;li&gt;http://files.swook.net/ serving my files from my VPS&lt;/li&gt;
&lt;li&gt;A CNAME entry for cdn.swook.net pointing towards swookfiles.speedymirror.com.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;









The Future&lt;/h2&gt;
Most likely, I will find some aspect of my blog that I do not quite like but for now, with a monthly operating cost of $3.74 (ignoring domain, future CDN costs) I cannot be more content.&lt;br /&gt;
&lt;br /&gt;
If you are just starting a blog like myself, I recommend my current setup. You do not even need a VPS actually, you could go with a free webhost such as&amp;nbsp;&lt;a href="http://000webhost.com/"&gt;000webhost.com&lt;/a&gt;&amp;nbsp;or&amp;nbsp;&lt;a href="http://x10hosting.com/"&gt;x10hosting&lt;/a&gt;&amp;nbsp;since your CDN is the one serving files and will do so swiftly (apart from the first 'Pull'er who has to wait for the CDN to pull files from the origin server). What I am saying is that you can have one of the fastest blogs in the world with minimal or no cost.&lt;br /&gt;
&lt;br /&gt;
I guess the next step will be to populate this blog with as much content as possible.&lt;br /&gt;
Happy Blogging!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=MaxDrzoPc1U:g1ROp8owdcw:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=MaxDrzoPc1U:g1ROp8owdcw:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=MaxDrzoPc1U:g1ROp8owdcw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=MaxDrzoPc1U:g1ROp8owdcw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/MaxDrzoPc1U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/408980742481508546/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/10/blogger-374-vps-speedy-mirror-cdn-bliss.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/408980742481508546?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/408980742481508546?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/MaxDrzoPc1U/blogger-374-vps-speedy-mirror-cdn-bliss.html" title="Blogger + $3.74 VPS + Speedy Mirror CDN = Bliss" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-RnLUleEQ0vs/Tp6rAsD_uUI/AAAAAAAAAB0/Bf4N1JsRF6M/s72-c/tumblroff.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/10/blogger-374-vps-speedy-mirror-cdn-bliss.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcERnw6eip7ImA9WhRREk4.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-5963460463665046565</id><published>2011-10-16T11:30:00.000+01:00</published><updated>2011-11-25T14:06:47.212Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T14:06:47.212Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Oneiric Ocelot" /><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>Upgrading to Oneiric Ocelot</title><content type="html">The long awaited Ubuntu 11.10 (codename 'Oneiric Ocelot') was out a few days ago. I say 'long awaited' but to be honest, I was not looking forward to it at all. Being a Kubuntu user, Ubuntu releases do not mean too much to me as functionalities with KDE are mostly decided by KDE itself and Kubuntu does a very good job at keeping KDE as vanilla as possible.&lt;br /&gt;
&lt;br /&gt;
Still, I wanted to try out the new and polished &lt;a href="http://unity.ubuntu.com/"&gt;Unity&lt;/a&gt; as well as Gnome3 with an upgrade to 11.10 (from 11.04). &lt;strike&gt;I found out later that Gnome 3 is only available via &lt;a href="http://www.ubuntugeek.com/how-to-install-gnome3-on-ubuntu-11-04-nattyubuntu-10-10-maverick.html"&gt;PPA&lt;/a&gt; (shame on you Canonical)&lt;/strike&gt; but nevertheless, upgrading is always fun... or not.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Upgrading&lt;/h2&gt;When upgrading to a new release of *ubuntu, one must consult the upgrade page. The upgrade page is very helpful in telling you to run 'update manager'. If you are using Kubuntu, as I am doing so, make sure to get the instructions for Kubuntu! Run kpackagekit. (It really does not matter but it's nicer to view a qt4-ed window with your upgrade progressing than a fudgy gtk widget set which feels alien)&lt;br /&gt;
&lt;br /&gt;
There is an alternate way to doing this upgrade via the commandline:&lt;br /&gt;
&lt;pre class="lang-sh"&gt;sudo apt-get update
  sudo do-release-upgrade&lt;/pre&gt;This lets you view the upgrade progress in a neater way.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Problem 1: 'E:Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.'&lt;/h2&gt;My first hurdle occurred pretty quickly. I was greeted by KPackageKit with the error stated in the heading above every time I tried the upgrade. I poked about &lt;i&gt;/var/log&lt;/i&gt; and found a directory called &lt;i&gt;/var/log/dist-upgrade&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
My &lt;i&gt;main.log&lt;/i&gt;&amp;nbsp;contained the following last lines:&lt;br /&gt;
&lt;pre class="lang-txt"&gt;ERROR Dist-upgrade failed: 'E:Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.'&lt;/pre&gt;while my &lt;i&gt;apt.log&lt;/i&gt; had the following lines among many:&lt;br /&gt;
&lt;pre class="lang-txt"&gt;...
  Holding Back cpp:i386 rather than change cpp-4.6:i386
  Holding Back virtualbox-dkms:amd64 rather than change dkms:amd64
  Holding Back libmtp-common:amd64 rather than change libmtp8:amd64
  Holding Back nspluginwrapper:amd64 rather than change nspluginviewer:amd64
  Holding Back libmtp-runtime:amd64 rather than change libmtp-common:amd64
  Holding Back libmtp9:amd64 rather than change libmtp-common:amd64
  Holding Back banshee:amd64 rather than change libmtp9:amd64
  Holding Back banshee-extension-soundmenu:amd64 rather than change banshee:amd64
  Holding Back nspluginwrapper:amd64 rather than change nspluginviewer:amd64
  Holding Back banshee-extensions-common:amd64 rather than change banshee:amd64
  Holding Back banshee-extension-awn:amd64 rather than change banshee-extensions-common:amd64
  Holding Back banshee-extension-ubuntuonemusicstore:amd64 rather than change banshee:amd64
  Holding Back nspluginwrapper:amd64 rather than change nspluginviewer:amd64
  ...&lt;/pre&gt;&lt;br /&gt;
To be honest, I had no idea what was going on and I promptly Googled and was welcomed with many posts on &lt;a href="http://ubuntuforums.org/"&gt;ubuntuforums.org&lt;/a&gt;. Naturally, I started panicking since I had removed several PPAs without &lt;i&gt;ppa-purge&lt;/i&gt;-ing them and my system was starting to look like it had no way of fixing itself.&lt;br /&gt;
&lt;br /&gt;
The following steps fixed my situation:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Remove all files from &lt;i&gt;/etc/apt/sources.list.d/.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Remove all third-party repository entries in &lt;i&gt;/etc/apt/sources.list&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;Remove &lt;i&gt;ia32-libs&lt;/i&gt;&lt;/li&gt;
&lt;/ol&gt;Yes, remove ia32-libs! This may be a specific issue for me since I was being rather liberal with my PPA entries but as this was my solution and no solution was available online, I'd like to share it. Here's the magic recipe:&lt;br /&gt;
&lt;pre class="lang-sh"&gt;sudo apt-get remove ia32-libs
sudo apt-get update
sudo do-release-upgrade&lt;/pre&gt;&lt;br /&gt;
Ta-dah! Your upgrade proceeds (painfully slowly for a few hours).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;        Problem 2: KDE and fglrx disappeared&lt;/h2&gt;I was rather puzzled when on reboot, I could not choose KDE from the lightdm screen! I told myself, "This should be a trivial issue, let's try Unity out in the meanwhile!". Try Unity I did but when I logged onto Unity by choosing 'Ubuntu' from lightdm, I was greeted with a desktop consisting of a full-screen nautilus window lacking all toolbars and titlebars as well as Unity itself! The best I could do was to run the terminal automagically via the still functional hotkeys and logout of nautilus-hell.&lt;br /&gt;
&lt;br /&gt;
This was when I realised that I had forgotten one important rule: &lt;b&gt;Always blame fglrx&lt;/b&gt;. A few commands and I was back on track with Unity and KDE working.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="lang-sh"&gt;sudo apt-get install fglrx kubuntu-desktop&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Problem 3: Windows partitions&lt;/h2&gt;My next reboot to check fglrx is working surprised me. My Windows partitions were refusing to mount correctly!&lt;br /&gt;
&lt;pre class="lang-txt"&gt;fsck: Error 2 while executing fsck.ntfs-3g for /dev/sda2
mountall: fsck /mnt/windows [328] terminated with status 8&lt;/pre&gt;&lt;br /&gt;
"Oh god", I thought, "now my NTFS partitions must be somehow messed up. I rebooted promptly to Windows 7 and tried to schedule a chkdsk to check and fix errors for my Windows partitions. For some reason that failed but I really was not in the mood to deal with Windows 7. I simply assumed that the partitions were fine since they were fine just before they were loaded the last time I booted my laptop.&lt;br /&gt;
&lt;br /&gt;
The obvious next step was to check &lt;i&gt;/etc/fstab&lt;/i&gt;, my personalised recipe for mounting partitions. The following were the troublesome entries:&lt;br /&gt;
&lt;pre class="lang-txt"&gt;/dev/sda2    /mnt/windows    ntfs    sync,rw,user,auto,exec,utf8,uid=1000,gid=100    0    2&lt;/pre&gt;&lt;br /&gt;
Go on, take a look and tell me what's wrong. That's right, I did not read the manual for fstab properly when I set that up! Take a look at the following from &lt;i&gt;man fstab&lt;/i&gt;:&lt;br /&gt;
&lt;blockquote&gt;&lt;blockquote&gt;&amp;nbsp;The sixth field (fs_passno).&lt;/blockquote&gt;&lt;blockquote&gt;&amp;nbsp; This field is used by the fsck(8) program to determine the order in which filesystem checks are done at reboot time. &amp;nbsp;The root &amp;nbsp;filesystem &amp;nbsp;should &amp;nbsp;be &amp;nbsp;specified&amp;nbsp;with a fs_passno of 1, and other filesystems should have a fs_passno of 2. &amp;nbsp;Filesystems within a drive will be checked sequentially, but filesystems on different&amp;nbsp;drives will be checked at the same time to utilize parallelism available in the hardware. &amp;nbsp;If the sixth field is not present or zero, a value of zero is returned&amp;nbsp;and fsck will assume that the filesystem does not need to be checked.&lt;/blockquote&gt;&lt;/blockquote&gt;&amp;nbsp;That's right folks, silly me had written 2 thinking it would not matter since his other entries worked fine with 2 as the pass number! The pass number of 2 must not be used for ntfs file systems since fsck.ntfs does not exist! The previous version of ubuntu had somehow not had a problem with this issue.&lt;br /&gt;
&lt;br /&gt;
Fixing the entry to the following did the trick:&lt;br /&gt;
&lt;pre class="lang-txt"&gt;/dev/sda2    /mnt/windows    ntfs    sync,rw,user,auto,exec,utf8,uid=1000,gid=100    0    0&lt;/pre&gt;&lt;br /&gt;
Hopefully someone will find this post useful, otherwise it shall go down in my history as a 4-hour period full of annoyances. Do share your experiences with upgrading to Oneiric as well!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=aHtRVhsVNCk:e9o2PI5rs8w:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=aHtRVhsVNCk:e9o2PI5rs8w:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=aHtRVhsVNCk:e9o2PI5rs8w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=aHtRVhsVNCk:e9o2PI5rs8w:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/aHtRVhsVNCk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/5963460463665046565/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/10/upgrading-to-oneiric-ocelot.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/5963460463665046565?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/5963460463665046565?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/aHtRVhsVNCk/upgrading-to-oneiric-ocelot.html" title="Upgrading to Oneiric Ocelot" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.swook.net/2011/10/upgrading-to-oneiric-ocelot.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIHQ3k7fSp7ImA9WhRSGUs.&quot;"><id>tag:blogger.com,1999:blog-5400967990754377209.post-7193088898854434733</id><published>2011-10-12T07:10:00.002+01:00</published><updated>2011-11-22T12:22:12.705Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-22T12:22:12.705Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cowon" /><category scheme="http://www.blogger.com/atom/ns#" term="UCI Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="UCI" /><category scheme="http://www.blogger.com/atom/ns#" term="Flash" /><title>Cowon and UCI design</title><content type="html">&lt;div style="display: none; text-align: center;"&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;b&gt;한글을 보고 싶으신 분은, 영문 위에 마우스를 올려 놓으십시오.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span title="코원은 의심의 여지없이 제가 가장 선호하는 PMP와 mp4 제조사입니다. iAUDIO 4가 인기리에 판매되고 있을 때에 저는 코원에 대하여 처음 들었습니다만, 그 이후로 한번도 실망한 적이 없습니다. 친구의 영향으로 저는 첫번째 mp3인 iAUDIO G3을 구입했는데, 아직도 종종 쓰곤 합니다. D2와 J3를 그 다음 몇 해간 구입을 했는데, 아래의 이유들 덕분에 어떠한 어려움도 없이 쉽게 구매를 결정할 수 있었습니다."&gt;&lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Cowon"&gt;Cowon&lt;/a&gt;&lt;/b&gt; is without doubt my favourite PMP and mp4 player manufacturer. The company has not disappointed even once since the first time I heard of them which was back when the &lt;a href="http://en.wikipedia.org/wiki/IAUDIO#iAUDIO_4" style="font-weight: normal;"&gt;iAUDIO 4&lt;/a&gt; was selling furiously well. Having been influenced heavily by a friend, I got the Cowon G3, my first mp3 player which I still keep and use from time to time. Acquiring the D2 and J3 in the following years did not require any difficult decisions as can be seen from my reasoning below.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-muXlkMkL7aI/TpQ6_APOfJI/AAAAAAAAABc/FhW_6SrOtOs/s1600/iAUDIOF1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-muXlkMkL7aI/TpQ6_APOfJI/AAAAAAAAABc/FhW_6SrOtOs/s1600/iAUDIOF1.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;span title="iAUDIO F1 - 이 신가하게 생긴 mp3는, F1 자동차를 컨셉으로 하여 2x3.5mm 잭을 배기구로 하고, 속도계 GUI를 자랑했습니다."&gt;iAUDIO F1 - This intriguingly designed mp3 player sported a F1 car design with  2x3.5mm jacks as exhausts and a speedometer GUI.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span title="코원이 제작한 기기들은 다른 mp3 제조사들과는 차별화된 몇 가지의 스펙의 차이가 있습니다:"&gt;Devices which were made by Cowon have always had a common set of specification differences to all other mp3 manufacturers:&lt;/span&gt;&lt;/div&gt;
&lt;div title="- 우수하고 정직한 전지 수명
- 우수한 음질
- 거의 모든 (오디오) 코덱의 지원
- 튼튼한 디자인
- 높은 가격"&gt;
&lt;ul&gt;
&lt;li&gt;Superior and honest battery life&lt;/li&gt;
&lt;li&gt;Good sound quality&lt;/li&gt;
&lt;li&gt;Support for almost any (audio) codec&lt;/li&gt;
&lt;li&gt;Durable design&lt;/li&gt;
&lt;li&gt;High pricing&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div title="코원 기기들의 높은 품질은, 코원을 한국의 mp4 제조 강자로 떠오르게 하였고, anythingbutipod 커뮤니티와 같은 예에서 볼 수 있듯이 대외적으로도 인정을 받을 수 있게 하였다. 현재, 60만명이나 되는 회원을 보유한 코원 기기 전용 카페도 있습니다. 5000만 정도의 인구가 사는 작은 나라 치고는 무척 큰 수치이지요. 해외에 iAudiophile이라는 코원 전용 커뮤니티도 매우 활발하게 유지되고 있으며, 디자이너와 modder들의 최신 콘텐트를 공유하고 있습니다."&gt;
The high quality has since made Cowon the leading company in mp4 manufacturing in Korea and has allowed Cowon to have a certain amount of international recognition as well as love from non-iPod communities such as &lt;a href="http://anythingbutipod.com/"&gt;anythingbutipod&lt;/a&gt;. Currently there exists a 'cafe' or forum dedicated to Cowon's MP4 players boasting a member count of about 600,000 Korean users. For a small country with a population of approximately 50 million, this number is staggeringly large. There also is a dedicated overseas community known as &lt;a href="http://iaudiophile.net/"&gt;iAudiophile.net&lt;/a&gt; maintained by fans of Cowon's products featuring the latest content from modders and designers as well as casual users.&lt;/div&gt;
&lt;br /&gt;
&lt;div title="코원의 모든 기기들은 음질과 내구성이 매우 뛰어나기 때문에, 코원이 iPod 외의 모든 경쟁품들을 따돌릴 수 있게 하였지만, 때때로 지적을 받는 부분이 있습니다. 이 결점은 User Created Interfaces (UCIs)로 인해 아주 멋있게 보완이 되었습니다."&gt;
While the build and sound quality of all Cowon devices are great and have catapulted the company above most other non-iPod competitors, there is one aspect which has been criticised from time to time, the graphical user interface. This has been dealt with skilfully by the introduction of User Created Interfaces (UCIs).&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2 title="UCI의 출현"&gt;
The introduction of UCIs&lt;/h2&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-z6Lwin2fpl4/TpUksJnyMQI/AAAAAAAAABk/nb7G-KAkD4g/s1600/D2screen2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-z6Lwin2fpl4/TpUksJnyMQI/AAAAAAAAABk/nb7G-KAkD4g/s320/D2screen2.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;" title="Fishfutter가 제작한 '해킹된' iTouch라는 테마"&gt;A 'hacked' user theme named 'iTouch' by Fishfutter&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div title="UCI는 코원의 D2의 출시와 함께 처음 도입되었습니다. 이는 엄청나게 성공적인 일이었고, 코원의 콘테스트들에 힘입어서 갖가지 UCI들이 여기저기서 튀어 나왔습니다."&gt;
UCIs were first introduced for the Cowon D2. It was a proper success and user created flash interfaces sprung out everywhere aided indirectly by Cowon's own UCI contest. The UCI implementation was somewhat lacking. There were only a handful of FS commands which could be called, the backend was seriously outdated and thus used Flash 7 which relies on &lt;a href="http://en.wikipedia.org/wiki/ActionScript#ActionScript_2.0"&gt;Actionscript 2.0&lt;/a&gt; but has less features than Flash 8. Even more frustrating was the lack of persistent data storage support and music indexing support which skilled UCI developers circumvented in various ways. The music UI was the only customisable UI as well and the only other way to change the look of the overall UI was to 'hack' a resources binary into the player with substituted images.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-N2iVmgKH9-s/TpUmIFt4QYI/AAAAAAAAABs/QxQbtw_-lAc/s1600/sense.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="220" src="http://2.bp.blogspot.com/-N2iVmgKH9-s/TpUmIFt4QYI/AAAAAAAAABs/QxQbtw_-lAc/s320/sense.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Sense by Kizune, a Music UCI for the S9, J3, X7 - One of the most popular UCIs in existence currently&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
The release of the Cowon S9 brought about many changes to the UCI front. Full UCI support for every bit of the player was supported with documentation. Persistent storage via FS commands and shared objects was supported and the number of FS commands was increased many folds to allow for a 'Full UCI support'. This meant that one could now edit EQs, change every single setting and create whole new widget sets by simply knowing how to design and code using Adobe Flash. This was not without woes however. UCIs tended to take up more memory and therefore were slower than the stock UIs. Interfacing with the firmware was still done via raw FS commands and code sharing was not common at all in the communities which meant that some UIs were less optimised and therefore slower to load and run.&lt;br /&gt;
&lt;br /&gt;
For the users this did not matter at all and many Cowon product users thereafter (J3, X7, i9 and now the i10) could make use of the many attractive user interfaces which many skilled flash developers were churning out. The UCIs truly helped towards extending the feeling of 'hype' for the users' new players and added a certain freshness to the players for every UCI release. By handing UI design choice to their users, Cowon had been able to shift the load of updating and satisfying users to the community, at least partially.&lt;br /&gt;
&lt;br /&gt;
The developers however had to face the frustration of careful and tedious optimisations. This was because the only tool Cowon had provided was the list of FS commands, a short guide about the software structure, and some badly written sample UIs. Some readers may be questioning how I am referring to the UCI samples as 'badly written' since the stock UIs run well. This is because the UCI samples do not get updated and the code is barely legible and is not object-oriented.&lt;br /&gt;
&lt;br /&gt;
The way I see it, UCI designers, and I repeat, designers, should not have to deal with tedious optimisations as well as direct usage of FS commands. Even today, most designers are having to use Cowon's sample UCIs to create their versions by modifying the code. The usage of raw FS commands which can be found in every bit of the code often requires that one truly understand when a certain call should occur and which values should be updated. Often this is not the most simple matter, requiring hours and hours of plugging and unplugging the mp4 players while modifying and re-arranging code. Since the code is not object-oriented and non-modular, one always finds himself/herself getting rather confused with bits of code ending up here and there.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
UCI Framework&lt;/h2&gt;
The solution I have for this problem is the introduction of a so-called 'UCI Framework'. I envision a set of actionscript scripts which can be #include-ed in a modular fashion to enable access to objects and methods which allow UCI designers to simply flick the switch without any worry or hassle. One would not need to worry about how the repeated usage of certain FS commands would impact their UI's performance. Statistics and values of certain settings should not have to be retrieved from slow FS command calls directly but would be cached and updated internally. Designers would do what they can do best, designing and writing code for lavish effects aimed both towards ease of use and visual appeal.&lt;br /&gt;
&lt;br /&gt;
Now I admit that I am in no way an experienced Actionscript 2.0 developer, nor have I been part of creating truly complicated UCIs. However, I have encountered numerous situations of frustration which I hope future designers will not have to deal with. Also, there are many skilled developers who are still toiling daily without any incentive for the better experience of the users. These developers have the know-how and experience with dealing with Cowon's players in the most efficient manner.&lt;br /&gt;
&lt;br /&gt;
The acronym UCI is commonly mis-interpreted as standing for 'User Created Interface'. In the most strict sense, this is definitely true and Cowon itself has introduced the term years ago. I would however like to use a new acronym, 'CCUI', 'Community Created User Interface'. Of course, 'UCI' is an easier acronym to use and is definitely what all users will identify custom flash interfaces as. My point is not that the acronym should be changed, but that the approach to UCI design should be changed. Code should be shared between developers as well as know-how. Afterall, surely this would allow for more designers to actually 'design' various interfaces instead of giving up after months of hard labour. Would open-source contributions prevent your own UI from gaining more popularity? Would spending time on helping the knowledge and skill-level of the general developer community rise affect you, the experienced UCI developer negatively? I think not. There may be style differences and there may be philosophy differences but surely getting the annoying and tedious bits out of the way would let you do what you can do best?&lt;br /&gt;
&lt;br /&gt;
For the reasons I have mentioned above, I would like to propose a community-created effort to code a UCI framework for current and future Cowon flash interfaces. I myself will be aiming to release a basic version for all developers to make use of and edit in the following months hoping to spring off a truly community created base for designers who would gladly not deal with the efficiency problems. A post will be written in the future to outline the features and philosophy of the framework to aid the understanding of anyone who is interested in using or working on the framework. The general aim is to be able to provide simple control based on objects as well as some heuristics for features such as device identification and millisecond seek positions.&lt;br /&gt;
&lt;br /&gt;
In the meanwhile, if any of you flash developers have any suggestions or ideas, please do comment below (you do not need to login) and express interest.&lt;br /&gt;
&lt;br /&gt;
(While I claim to know much about what I have written here, I really do not so please feel free to correct me on various bits and pieces!)&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=z536NCRzRPU:J_t29jtJJc4:TEnoju37e50"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?i=z536NCRzRPU:J_t29jtJJc4:TEnoju37e50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=z536NCRzRPU:J_t29jtJJc4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWookBook?a=z536NCRzRPU:J_t29jtJJc4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWookBook?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWookBook/~4/z536NCRzRPU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.swook.net/feeds/7193088898854434733/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.swook.net/2011/10/cowon-and-uci-design.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/7193088898854434733?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5400967990754377209/posts/default/7193088898854434733?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWookBook/~3/z536NCRzRPU/cowon-and-uci-design.html" title="Cowon and UCI design" /><author><name>Seon-Wook Park</name><uri>https://plus.google.com/104903917274863991821</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-BW7qJkFoH5g/AAAAAAAAAAI/AAAAAAAAAL4/d1tVVh4zxJM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-muXlkMkL7aI/TpQ6_APOfJI/AAAAAAAAABc/FhW_6SrOtOs/s72-c/iAUDIOF1.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.swook.net/2011/10/cowon-and-uci-design.html</feedburner:origLink></entry></feed>
