Posts by Toby

My Thoughts on the iPad

iPad
I've followed engadget's live blog, seen the keynote video, listened to Tom and Molly talk about it, even read others' opinions on engadgetgdgt and twitter, etc etc. I guess you could say I am pretty excited. 

The tech savy(engadget, gdgt, BOL, etc) are in general underwhelmed or disappointed. Below are some of the complaints I have heard:
  • No Webcam or microphone - which pretty much rules out using Skype on it, which would have been a great killer app at this form factor. I think they will add these to the iPad in the future. Update: actually, there IS a built-in microphone, so at least you can make audio calls with Skype.
  • Still No Flash Support - you cannot seriously claim it has the best web browsing experience when it doesn't support Flash! Apple has not allowed Flash to run on the iPhone all this time. Now that they are doing the  same with the iPad - which with it's larger screen you would think would be much better suited to run Flash apps, and add to it the fact that Flash has never ran great on Macs, it's becoming obvious that this is political. Apple wants to fight a format war with Adobe. Why would you need flash when you can buy great apps from the app store and buy TV shows and movies from iTunes? On the other hand, I can also see the concern that almost all of the flash apps out there(possibly with the exception of Flash ads) just aren't designed for the touch screen, and having users run them on the iPhone or the iPad degrades the user experience and therefore could hurt the products' reputation. Apple's PR, however, is going with: "it could rapidly drain battery life", which I think is probably in reality 3rd or 4th down on their list of concerns.
  • No multiple tasks/apps/windows - this is a pretty big one: given the iPad's screen real estate, it seems artificially limiting to not allow multiple apps to be running in separate windows. I believe the iPad will eventually have this feature. How the UI will turn out will be interesting to see. 
  • The App Store Sucks - Apple prevents certain types of applications from entering its App Store. One example is programming language interpreters; another is any app that Apple views as overstepping their core apps' boundaries. Given that the iPad is even more of a computer than the iPhone, these limitations may become even more glaring.
  • I just don't see the need - "I already have a laptop and a smartphone, there just isn't any more room for yet another device!" I think that at the moment the iPad is more exciting for developers than consumers, but that will change.

All the negatives are well and good, but I overlook all of them, because, from my point of view, the iPad - and what it will lead to - is much bigger. All of the tablet computers I've seen in stores in the past - HP's, Fujitsu's, etc: they all suck. These computer manufacturers created tablet computers but installed on them an Operating System which is design from the ground up for use with a mouse and a keyboard. They figured: "A tablet computer has a stylus. We can use it as a pointing device in the same way that a mouse is a pointing device. We just hook up the stylus driver to control the pointer, and boom! We got ourselves a tablet Operating System! Brilliant!" This is understandable, because it is the nature of software engineers to want to build solutions that solve as many problems as possible - and Windows is a very very big solution indeed. However, this tendency also causes brilliant people to routinely produce crap. The tablet form factor is more versatile than the mouse, and can be much more natural to use from a UI standpoint, but dumbing it down and retrofitting it to an inferior UI paradigm caused it to be marginal. Yes, you could use a tablet to draw, sign documents, take notes, etc, but when it came to interacting with the UI elements, it was usually very kludgy. 

iPad is the first tablet I've seen that comes close to realizing the potential of the tablet form factor. Why? It's all about the software, stupid! The software that come with the iPad were designed and written  specifically for the large multi-touch screen device. This is to take nothing away from the amazing hardware. Multi-touch was ground breaking when it first surfaced. When the iPad comes to market, it will be the single best showcase of multi-touch technology. But, the software is what brings it all together, and you can tell Apple put a lot of time and effort into the software. Okay, enough of my rambling. What am I really trying to say? 

iPad marks a historical step towards our liberation from mouse pointers and a paradigm shift in computer technology.

I hereby reiterate my prediction that in 5 to 10 years, mice will be on the way to extinction.
Posted by Toby 11 days ago about apple, fourcast, gadgets, ipad, tablet and tech (0 comments)

Simulating a Tablet Using the Touchpad

Chinese Handwriting
I came across OS X's Chinese Trackpad Handwriting input method the other day, and was really impressed. Once you activate the handwriting mode(hotkey: Ctrl-Shift-Space), the mouse pointer disappears, and you can use write your chinese character on your trackpad using your finger. The UI looks like this:

Handwriting UI

What's interesting to me is the buttons on the left and right of the character recognition area. It took me a while to figure out how to use them at first, but after some experimentation, I figured it out: basically, the pretty gray box corresponds to your trackpad, and so to press a button on the upper left corner, you would tap the area in the upper left corner of your trackpad, and so on and so forth. It is very intuitive really. I would even say brilliant. Essentially, the trackpad has been made to work just like the Vistablet or any of the tablet accessories you can get from the Apple store these days. 

Which got me thinking, how far can we take this? Can we use this to say...draw? A couple of google searches later, I discovered the Inklet from Ten One Design. The Inklet is an application, which is primarily used with a stylus you can buy from the same company called the Pogo Sketch. 

Pogo Sketch Stylus

The Pogo Sketch is a pressure sensitive stylus that works with the Apple trackpads as well as the iphone and ipod touch. With Inklet and the Pogo Sketch together, you basically have the features of Vistablet. Here's their demo using Photoshop:

Embedded Content


Brilliant, brilliant stuff. Another why-didn't-I-think-of-that moment for me. The lesson from all of this is that, at least for the new Macs, you can do a lot more with the trackpad than you thought(or at least I thought). For some types of applications, it may make sense to completely do away with the mouse pointer and use a tablet-style interface instead, and we can do this NOW! (Yes, now - three days before the imminent release of the Apple Tablet). Tablet doubters, just you wait, tablets will be the way of the future. In 5-10 years(oh this could be another Fourcast prediction), the mice could be heading towards extinction. Just you wait.
Posted by Toby 15 days ago about fourcast, gadgets, tablet, tech and touchpad (0 comments)

Working From the Future

This is my second FourCast style prediction. It is the "long term" prediction.

In the year 2110, 80%> of the earth's workers will work remotely.  Even physical tasks like surgery, construction, or mechanical repair: you can do by logging into a robot remotely and controlling in via a VR-type interface. Moreover, many of the reasons for needing to get out of the house have been eliminated, among them:
  • groceries - groceries will be delivered to your fridge. You will order them online - usually on a display on your fridge, or just by talking to it and the groceries will be delivered within a couple of hours.
  • social activities - 80% > of social activities will be done via virtual worlds like Second-Life. So you can connect with all of your friends no matter where they are or where you are.

The implications of this are:
  • Because people are not tied to the location where they work, they can be traveling on a day-to-day basis and still not miss a day of work: tourism flourishes.
  • By the same logic, people can live where they want to live, not where they have to live, therefore, they move their residence from place to place in a much higher frequency. People who love traveling live in RVs permanently.
  • The real estate market will sky rocket, because there will be a large influx of potential buyers from all over the world.
  • Most jobs will be short-term contracts because for whom you work is no longer tied to where you live, and so there's less of a need for stability and also you have a much larger pool of openings to choose from.
  • There will be one global currency to facilitate workers and employers in different countries to do business with one another.
  • There will only be 2 or 3 languages in common use throughout the world, and the majority of the people know at least 2 of them.
  • 90% of dating will happen virtually. Meeting IRL will be considered a major step in a relationship.
Posted by Toby about 1 month ago about fourcast and tech (0 comments)

The Future of TV

I've been enjoying Tom and Scott's FourCast Podcast and decided that I would make my own predictions in the FourCast style. This post is my first prediction and will be the short term prediction. Here goes:

In the year 2020, TV will work completely wirelessly. Devices like Apple TV, Roku, Boxee Box, etc. will be merged into the TV itself. HDMI, DVI, Component inputs are only optional features and will be seen as outdated or niche. Apple Inc. will have the best selling TV which will have not a single hole or button on it. TV programming will be IP based and a la carte. TV shows will be delivered via a framework/standard like RSS but which allows for streaming, ad placement as well as paid shows in the form of a la carte or subscription. TV networks have a much smaller role and their main purpose will be to getting advertisers for shows. Google/YouTube will become the biggest TV network and will use ad-sense to place ads for shows anyone can make. Other competing networks will crop up and some of the old TV networks will move to this model but will not over take YouTube. TV channels will become a concept distinct from TV networks, and will be collections of shows/videos created by the TV networks or individual users(kinda like playlists). 
Posted by Toby about 1 month ago about fourcast and tech (0 comments)

Flex Compiler Slower on 64bit Mode Java on Snow Leopard

Ever since I upgraded to Snow Leopard, the my flex apps seemed to compile slower. Today, I finally had enough and took a look into this problem. First, there was the weirdness with Java on Mac in that even though the compiler is a command line application(non-GUI), it creates a application menu. I cracked open the mxmlc script, and added:
-Djava.awt.headless=true
to VMARGS. This solved that issue, but didn't make it compile much faster.
Then, after a bit of fiddling around, it turned out that putting java into 32bit mode:
-d32
fixed the problem! The difference was significant. I tested this in 2 different apps. For App 1, it took 45 seconds to compile on 64bit mode, only 9 seconds on 32bit mode. For App 2, it took 30 seconds on 64bit mode, only 7 seconds on 32bit mode. So, mxmlc performs 4-5 times slower on 64bit java than 32bit, java. Why would this be the case, I have no idea. If anyone has an idea, I'd love to be enlightened. If you come across this problem, the fix is to open up mxmlc, and edit the line that says:
VMARGS="-Xmx1024m -Dsun.io.useCanonCaches=false"
and change it to:
VMARGS="-Xmx1024m -Dsun.io.useCanonCaches=false -Djava.awt.headless=true -d32"
I hope that helps someone.
Posted by Toby 2 months ago about flex and programming (0 comments)

Taking an Average in CouchDB

More fun with CouchDB, this time taking an average of something:
// map
function(doc){
    emit(null, doc.info.size) // in place of doc.info.size, you'd put whatever
                               // value you want averaged here
}
// reduce
function(keys, values, rereduce) {
    if (!rereduce){
        var length = values.length
        return [sum(values) / length, length]
    }else{
        var length = sum(values.map(function(v){return v[1]}))
        var avg = sum(values.map(function(v){
            return v[0] * (v[1] / length)
            }))
        return [avg, length]
    }
}
The end result will be 2 values, the first is the average, the second is the total number of values that we took an average of. Phew! Who woulda thought taking an average would be so involved!
Posted by Toby 4 months ago about couchdb, javascript and programming (0 comments)

Retrieve The Top N Tags in CouchDB

I am reading up on how map/reduce works in CouchDB, think I am getting the hang of it now, thanks to this great tool. I tried the "Retrieve the top N tags" example on this page. It didn't work for me at all. So I wrote my own as an exercise. Here's my code:
// the map function
function(doc){
    for(var i in doc.tags)
    {
        emit(null, doc.tags[i]);
    }
}

// the reduce function
function(key, values, rereduce){
    var hash = {}
    if (!rereduce){
        for (var i in values){
            var tag = values[i]
            hash[tag] = (hash[tag] || 0) + 1
        }
    }else{
        for (var i in values){
            var topN = values[i]
            for (var i in topN){
                var pair = topN[i]
                var tag = pair[0]
                hash[tag] = (hash[tag] || 0) + pair[1]
            }
        }
    }
    var all = []
    for (var key in hash)
        all.push([key, hash[key]])
    return all.sort(function(one, other){
        return other[1] - one[1]
    }).slice(0, 3)
}
The approach I took was different one from the one from the example page, but I believe it to be the more correct one: rather than returning the results keyed by the tag in the map step, I would emit every occurrence of every tag instead. Then in the reduce step, I would calculate the aggregation values grouped by tag using a hash, transform it into an array, sort it, and choose the top 3. For the rereduce case, I would combine a set of top 3 choices and then again pick the top 3 among them.
Posted by Toby 4 months ago about couchdb, javascript and programming (0 comments)

Adding Real Properties to FABridge

Although FABridge is a nice tool, it's got its shortcomings. I am going to fix one of them now, namely that it doesn't give you real properties, but uses Java's getter setter convention instead. In 3 out 4 browsers, the __defineSetter__ and __defineGetter__ methods are already usable, so why not take advantage? It's really easy as it turned out. Change the addPropertyToType method to:
    addPropertyToType: function(ty, propName)
    {
        var c = propName.charAt(0);
        var setterName;
        var getterName;
        if(c >= "a" && c <= "z")
        {
            getterName = "get" + c.toUpperCase() + propName.substr(1);
            setterName = "set" + c.toUpperCase() + propName.substr(1);
        }
        else
        {
            getterName = "get" + propName;
            setterName = "set" + propName;
        }
        function setter(val)
        {
            this.bridge.setPropertyInAS(this.fb_instance_id, propName, val);
        }
        ty[setterName] = setter;
        function getter()
        {
            return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName));
        }
        ty[getterName] = getter;
        if (ty.__defineGetter__)
            ty.__defineGetter__(propName, getter);
        if (ty.__defineSetter__)
            ty.__defineSetter__(propName, setter);
    },
 And..., voila! You got yourself real properties. Now instead of writing:
app.getTextBox()
You will be much happier writting:
app.textBox
On non-sucky browsers that is.
Posted by Toby 4 months ago about flex, javascript and programming (0 comments)

Typed Deserialization with JSON

JSON is nice, but if you use it extensively, you go against the OO style of object modeling, which says that behaviors should be attached to objects themselves. Even if you are not an OO bigot, the OO way is sometimes just far more convenient and structures your code better, IMHO. Given my past work with JYaml, it can't be that hard to read in some JSON and directly deserialize it into a typed object can it?

Say you have a Person type:
function Person(name){
    this.name = name
}
Person.prototype.sayHi = function(){
    return "Hi! I am " + this.name
}
You create an instance called tommy:
> tommy = new Person('Tommy')
> tommy.sayHi()
Hi! I am Tommy
With a little magic from a toJson function that I whipped up:
> tommyJson = toJson(tommy)
> tommyJson
{__proto__: Person.prototype, name: "Tommy"}
tommyJson is now a string representation of tommy. You can see that it sets the special __proto__ link to Person.prototype, which will do its magic when it's deserialized. Now let's deserialize it back:
> tommyCopy = fromJson(tommyJson)
> tommyCopy.sayHi()
Hi! I am Tommy
> tommyCopy.constructor
function Person(name){
    this.name = name;
}
> tommyCopy === tommy
false
As you can see, the deserialized object tommyCopy is not just a plain object literal, but has all of the behaviors of Person.

The code for toJson and fromJson is so small I don't even bother putting it on github, so I'll just post it here(You may need ecma5array if you want to run it on a sucky browser):
function toJson(obj){
    function keys(o){
        var ret = []
        for (var key in o){
            var val = o[key]
            if (o.hasOwnProperty(key)) // exclude attributes in the parent
                ret.push(key)
        }
        return ret
    }
    function quote(str){
        return '"' + str + '"'
    }
    if (obj === null || obj === undefined)
        return String(obj)
    else if (obj.constructor === String)
        return quote(obj)
    else if (obj.constructor === Array)
        return '[' + obj.map(toJson).join(', ') + ']'
    else if (obj.constructor === Object)
        return '{' + keys(obj).map(function(key){return key + ': ' + toJson(obj[key])}).join(', ') + '}'
    else if (obj.constructor && obj.constructor.name)
        return '{' + ['__proto__: ' + obj.constructor.name + '.prototype'].concat(
            keys(obj).map(function(key){return key + ': ' + toJson(obj[key])})).join(', ') + '}'
    else
        return String(obj)
}
function fromJson(str){
    return eval('(' + str + ')')
}

Posted by Toby 4 months ago about javascript, programming and prototype (0 comments)

Vector for ActionScript3

I just learned about Vector, it's a typed Array for Actionscript 3, like generics in Java or C#. However, in Actionscript 3, Vector is a one-off: it's the only class that uses the generics syntax, and developers cannot use generics in their own classes. Nevertheless, Vector gives a type-safe alternative to Array and promises big performance gains. Given that it can also give the type of the containing elements at runtime, I can use it now to drive JSON deserialization into objects too.
Posted by Toby 4 months ago about actionscript, flex and programming (0 comments)

Google Chrome Frame to the Rescue!

Bruce Eckel's prediction came true! Chrome is now an IE plugin! There's a lot of talk about it at the moment about security concerns and accessibility, but both of these discussions miss the point. The real story here, is what Google Chrome Frame means for developers. Web developers like me have longed for the following:
  • CSS 3 support
  • Canvas
  • SVG
  • Properties and other advanced features in Javascript
  • HTML 5
  • Not having to develop for a browser that sucks
Now, rather than resorting to campaigns like these, you can instead ask your users to install a plugin - much like with the Flash plugin - that will essentially run Chrome's engine inside IE 6, 7, or 8, and give you all of the benefits in the list above. The average end-user will hardly notice the difference because IE's interface will stay the same, the only things that are different are within the content pane of the browser. Given Flash's ubiquity with its browser plugin install model, it is certainly not unconceivable for Chrome Frame to become wide spread among IE users. Go back a few years: How did Flash gain this level of penetration in the first place? Answer: YouTube! Who owns YouTube now? Oops! Yes, Google could totally drop Flash from YouTube and go HTML 5 only. I doubt they would do that in reality, but that card is there for them, if they want to play it. The more probable Google strategy will be Wave, which, I gather from Google's positioning, will definitely not support IE natively. So, if Wave hits a home run and becomes the next big thing, Chrome Frame - and thus HTML 5 - will become a very viable RIA environment. Heck, some other company could very well come into the picture at this point and develop a killer app in HTML 5 that pushes it over the top also. When we get to that point - and here's me praying - it's bye bye to developing for the IE platform, forever!


Posted by Toby 4 months ago about programming, tech and web (1 comments)

HTTP Server in 5 Lines With Webrick

Usually when I am prototyping a web UI - either in Javascript or Flex, I would just write a static html, because that's the simplest thing that works. But, once in a while, it doesn't work because of the security restrictions that the browser imposes on local files. Maybe you want to use ajax calls(which is sometimes problematic on IE), trying to use the google maps api, or the FABridge, whatever the reason may be. Well, you can get around this problem easily using this ruby script:
require 'webrick'
server = WEBrick::HTTPServer.new :Port => 1234
server.mount "/", WEBrick::HTTPServlet::FileHandler, './'
trap('INT') { server.stop }
server.start
This runs a web server at http://localhost:1234/ which mounts the top level directory to your current directory.

Update: Oops, it's not exactly that easy after all. In order to prevent caching - which you will want to do if you are doing development - you will want to write an extra class. The modified script:
require 'webrick'
class NonCachingFileHandler < WEBrick::HTTPServlet::FileHandler
  def prevent_caching(res)
    res['ETag']          = nil
    res['Last-Modified'] = Time.now + 100**4
    res['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
    res['Pragma']        = 'no-cache'
    res['Expires']       = Time.now - 100**4
  end
  
  def do_GET(req, res)
    super
    prevent_caching(res)
  end

end

server = WEBrick::HTTPServer.new :Port => 1234
server.mount "/", NonCachingFileHandler , './'
trap('INT') { server.stop }
server.start
Not 5 lines anymore, bummer! The code for NonCachingFileHandler was stolen  from unittest_js.
Posted by Toby 4 months ago about html, javascript, programming and ruby (0 comments)