July 2007 - Posts

Playing around with JavaScript global object

I am not sure if this is of any use or not.  While playing around with trying to find a more elegant syntax for my LINQ-like querying code, I accidentally bumped into this topic.

Say... I want to be able to write something like:

var peoples = [ ... ]; 

function from() {
    // do something with the arguments passed here...

from (a, in, peoples)

This will never work since "a" is undefined and "in" is a JavaScript keyword.  What I wanted to do is cache the arguments that were passed to the "from" function into a local buffer so I can do something with it later inside the function.

There are several problems here that are related to JavaScript global object.

Problem 1: 'a' is undefined will be thrown when the "from" function is called.  Now, how can we possibly remedy this?  Well, we can declare "a" as a global variable and assigned something to it (does not matter what), but that's kind of weird.  Is it possible to inject "a" into global on the fly?  Well, yes, somewhat.  You can use try and catch block and detect the "'a" is undefined" error that was thrown and have the catch block inject the missing variable as a global variable.

Example:

try {
    from(a, inside, people);
} catch(e) {
    var m = e.message.match(/^'(.+)' is undefined$/);
    if  (m) {
        this[m[1]] = {};
    }
}

Well, this will inject variable 'a' into the global object (this). If you need a proof for this, just output 'a' somewhere after the above code. (i.e. WScript.Echo(a)). Unfortunately, this route does not take me to where I want since once the error is caught the function will never complete the call anyway.  Hmm...

Problem 2: Ignoring the 'in' Syntax error, the second thing that bugs me is how to get the function parameter variable name (in this example, I want to be able to get the name of the people object (which is "people").  So, how can you reflect over Javascript global object to get this value?

After a little experimentation, I finally found the answer.  Take a look at the code below:

function GetGlobalObjectName(aGlobalMember) {
    var global = this; //when the function is called as a function, "this" will point to global object

    for (var object in global) {
        if (global[object] === aGlobalMember) {
           return object;
         }
    }
    return null;
}

now I can modify my "from" function as follow:

function from() {
    for (var x = 0, a = arguments, k = a.length; x < k; x++) {
        var v = a[x];
        if (typeof(v) === "object") {
           WScript.Echo(GetGlobalObjectName(v);
        }
    }
}

Now I can pass any object to my "from" function and if it detects that the argument type is "object" it will get the name of that object as defined in the global.  Afterward I can use that name string to do whatever I want.  In this example, perhaps use it to construct dynamic JavaScript statement from all the arguments being passed and do an eval() on it.

Hmm... with all these problems, I doubt I can get the syntax structure to anywhere close to C# LINQ... alternatively, mixing string into the function call might work, but that's just messy Sad.

from("a", "in", people).  Hmm...

frankly I like the current syntax that I have, minus the orderby array part that is still in string.

from(people).where(function(n) { n.Age > 19 && n.Age < 31) }).select(function(n) { return { FullName : n.FirstName + " " + n.LastName }; });

To me that seems a little bit a elegant than mixing string substitutions into the function argument. 

I don't anticipate that I'll get anywhere far with this in regard of finding a more elegant way to write my query syntax, but this is sure is one fun trip into JavaScript internals.  I learnt something new today Smile.  It's all good.

 

Share this post: | | | |
Posted by Jimmy Chandra | with no comments
Filed under:

Effective Use of Commuting Time

One thing I hate about Jakarta is its traffic. Driving from home to the office, vice versa, usually take me about 1 hour or more depending on the traffic on average. For a while, I survived the trip by listening to radio stations, playing Pocket Sudoku or reading e-books on Windows Mobile device.  But sometimes, the radio stations do not broadcast anything that is suitable to my taste.  Reading or playing Sudoku / any game while driving is just too much of a distraction and really only doable while waiting in line on the traffic light stops, especially when you don't have a driver Big Smile.  Listening to CD quickly become a boring thing since you know you already heard the song for x amount of times before.  So what am I to do? Confused Isn't there a better way to commute that at least can be useful in the long run?

I knew for a long time I wanted to download podcasts relating to development / IT stuffs and listen to them while commuting.  About two months ago I finally upgraded my faithful Nokia 6600 with a Sony Ericsson K800i equipped with 1 GB of memory and starting from that day forward, I got my wish.  I downloaded a bunch of podcasts from DotNetRocks, HanselMinutes, etc. and they always accompany me wherever I travel now. Wink  I know, I know, I can do better w/ an iPod, but the cellphone works just fine for my need, beside I don't have to carry lots of gadgets.

How about you?  What do you do while you are commuting to make it better? 

Share this post: | | | |
Posted by Jimmy Chandra | 4 comment(s)
Filed under: ,

Javascript LINQ-like Querying?

Just coding for coding sake, I decided to try implement a LINQ-like query in JavaScript.  And the result is as follow:

/*
 *
 * Javascript LINQ-like query proof of concept 
 * Jimmy Chandra - 16 July 2007 
 */
 
/* 
 * Quicksort implementation for JavaScript Array (based on  
 * http://en.literateprograms.org/Quicksort_(JavaScript)), 
 * modified to pass a function delegate for the comparison function. 
 */
 
Array.prototype.swap = function(i, j) {
    var a = this,
        t = a[i];
    a[i] = a[j];
    a[j] = t;
}
 
function partition(a, s, e, p, l) {
    var v = a[p],
        t = s,
        i;
    
    a.swap(p, e - 1);
    
    for (i = s; i < e - 1; i++) {
        if (l(a[i], v)) {
            a.swap(t, i);
            t++;
        }
    }
    
    a.swap(e - 1, t);
    
    return t;
}
 
function qsort(a, s, e, l) {
    var p;
    if (e - 1 > s) {
        p = s + Math.floor((e - s) / 2);
        p = partition(a, s, e, p, l);
        
        qsort(a, s, p, l);
        qsort(a, p + 1, e, l);
    }
}
 
Array.prototype.quicksort = function (l) {
    qsort(this, 0, this.length, l);
}
 
 
/*
 * JavaScript LINQ-like query engine sample implementation 
 */
 
function _each(o, l, a) {
    var r = [],
        m = o.length,
        i;
        
    if (l) {
        for (i = 0; i < m; i++) {
            if (l(o[i])) {
                a(r, o, i);
            }
        }
    } else {
        for (i = 0; i < m; i++) {
            a(r, o, i);
        }
    }
    return r;
}
 
function from(o) {
    return new _from(o);
}
 
function _from(o) {
    this.items = o;
}
 
_from.prototype.where = function(l) {
    return new _where(
        _each(this.items, l, 
            function(r, o, i) {
                r.push(o[i]);
            }));
}
 
function _select(l) {
    return _each(this.items, l, 
        function(r, o, i) {
            r.push(l(o[i]));
        });
}
 
_from.prototype.select = _select;
 
function _where(o) {
    this.items = o;
}
 
_where.prototype.select = _select;
 
_where.prototype.orderby = function(a) {
    var f,
        k = a.length,
        r = _each(this.items, null,
            function(r, o, i) {
                r.push(o[i]);
            });
            
    if (k === 1 && a[0] === "") {
        f = function(i, j) { 
                return i <= j; 
            };
    } else {
        f = function(i, j) {
                var l = "",
                    r = "";
                    
                for (var n = 0; n < k; n++) {
                    l += i[a[n]];
                    r += j[a[n]];
                }
                
                return l <= r;
            };
    }
    
    r.quicksort(f);
    
    return new _orderby(r);
}
 
function _orderby(o) {
    this.items = o;
}
 
_orderby.prototype.select = _select;
 
/*
 * Javascript LINQ-like querying example 
 */
 
var numbers = [17, 6, 12, 14, 20, 13, 10];
var b = from (numbers).
        where (function(n) { return n > 9 && n < 20; }).
        orderby ([ "" ]).
        select (function(n) { return n; });
        
for (var x = 0, l = b.length; x < l; x++) {
    WScript.Echo(b[x]);
}
 
var peoples = [
    { FirstName : "John", LastName : "Doe", Age : 29 },
    { FirstName : "Jane", LastName : "Doe", Age : 33 },
    { FirstName : "Mary", LastName : "White", Age : 31 },
    { FirstName : "Barry", LastName : "White", Age : 31 },
    { FirstName : "Kevin", LastName : "Black", Age : 31 },
    { FirstName : "Anna", LastName : "Smith", Age : 1 }];
    
var p = from (peoples).
        where (function(n) { return n.LastName === "Doe" || n.LastName === "White"; }).
        orderby([ "Age", "LastName", "FirstName" ]).
        select(function(n) { return { FullName : n.FirstName + " " + n.LastName, Age : n.Age }; });
        
for (var x = 0, l = p.length; x < l; x++) {
    WScript.Echo(p[x].FullName + ":" + p[x].Age);
}

To test it, cut and paste the code into a text file, name it whatever you want with .js extension and run it from command prompt by typing cscript the_filename_here.js.  Fun :)

Share this post: | | | |
Posted by Jimmy Chandra | 3 comment(s)
Filed under:

Vista - Windows Meeting Space is Awesome!!

I was scheduled to give a talk about JavaScript to my team members today.  I reserved the meeting room that has the smartboard and ceiling mounted projector a couple week before the meeting.  Poor me, the company CEO bumped me out of the nice meeting room due to a business critical meeting that he have to conduct on the same period.  So, what am I to do....

Well, let see, I had a couple of options.

  1. Find another meeting room (which is out of the question since there isn't any other meeting room that is free for that period)
  2. Use the common area that has a whiteboard and give hands out to attendants (well, sucks, I have prepared some nice demo, etc. that will really need to be run from a computer, don't want to do this).
  3. Use VNC or similar remote viewing application and have my team member join that session. (Hmm... this sound promising, let's go with this)

After fidgeting around with RealVNC for some time and unabled to make it run properly, I decided to find an alternative way to do this.  And at that moment I remembered Vista has a built in meeting application called Windows Meeting Space.  Although we haven't fully migrated to Vista environment in our company, some of us (2 at this time, me and another developer) have already migrated to Vista. 

So, I started up Meeting Space on my laptop (which also has Vista on it), fired up another session on my desktop machine and asked the other developer (whose workstation is right across my table and separated a little by walking area that can fit 3 rows of chairs).  I invited my desktop and the other guy to the meeting that I started from the laptop and started the Desktop sharing session and Walla!... I have an impromptu meeting hall with 2 17" LCD to show my demo to the attendants.  Driving the presentation and demo from my laptop while the attendants watched the two screens (whichever closer to them) just made the session work.  I love it.

I know, I know.  This is not the best setup.  Maybe next time when all the developers are already migrated to Vista.  They can stay on their own PC and join the meeting from there which is going to be cooler.

 In any case, thank you Microsoft for the Vista Meeting Space.  It's awesome!!

One happy Vista user.

 

Share this post: | | | |
Posted by Jimmy Chandra | with no comments
Filed under: , ,