Put your message here! Contact me for more information
 
 







 

Archive for the ‘Web Scripting’ Category


 


{{http://alexle.net/wp-content/uploads/2007/06/rails.png }}It’s been a week since I started messing with Ruby on Rails seriously. My current Rails project is rebuilding Wars of Earth, the game that my friend Giao and I started almost a year and a half ago. Since Rails is so flexible and powerful, within a span of a few days (like 5 days), I was able to achieve as much as 2 weeks worth of work compared to the past. Before, as Giao is much better at programming than I am, I asked him do the framework design in PHP (we used Pear’s DB_DataObject, Smarty, and home-grown controller for a MVC architecture.) I did the design (game designs, coming up with ideas, some coding) instead as well as preparing the site in Joomla (check it out [[http://www.warsofearth.com|here]]). Nonetheless, I was getting ready to graduate, and my buddy had to take on freelance work to make some money, I decided to put Wars of Earth aside and focus on what mattered most at the time (mainly job and money). As I have more free time on my own now, I am restarting the Woe project but this time, I am rebuilding it from scratch using Rails. And I don’t think I would go back to PHP for any web-based project if I don’t have to.

The major bottle-neck between Giao and I, as I would boldly claim for any other projects that involved geographically distributed team, was the communications. Giao is still back in Vietnam, and I’m in Chicago. I’m 12 hours behind him. Whatever we needed to do, we put in TOTO tasks and message in our Basecamp site. At the time I haven’t thought too thoroughly about the story and the game play, so we just kept on moving until we hit a problem, then we would sit down and talk. But words can only describe so much. Sometimes what I tried to get across, or what my buddy tried to tell me, just failed to get both of us on the same page. Giao would implemented something and it was not the same as I thought, so we just kept on building, discussing, and sadly, compromising. Moreover, I constantly having more ideas for the project, creating our eternal scope-creep: I just tried to add many features right at once (I was trying to get it right the first time, but of course it was almost impossible)

Now with Rails, things are much different. Rails are so flexible and powerful that what I only need to put down is mostly business logic, not low-level, database accessing code. The syntax of Ruby is much superior to that of Perl (I hated Perl with passion, and still do) and Rails is plainly a joy to use. Suddenly I realize the meaning of the [[http://www.loudthinking.com|blog]] of [[http://www.loudthinking.com/about/|David H. Hasson]], Rails’ creator, “**Loud Thinking**.” With Ruby, you can actually __think out loud__ through your code. Since Ruby’s syntax is so flexible, it allows the user to write the code in an unheard-of conversational way. I can almost read the code as I would read a novel (since reading code requires some imagination and the code is no longer boring in Ruby, so I can’t compare the program with a textbook - that would be too boring don’t you think?). I don’t have to restrain myself to the curly braces of C#/Java/PHP style, instead I can tell the Model to fetch all the record then smash the id’s in to an array with some logic in one line. Something like CharacteUnit.get_all_units().collect{|unit| unit.id unless unit.is_inactive} and of course you can add a lot more to that as you can stack as many operators/methods as possible. Pure programming joy.

One interesting part about Rails is the testing tool: unit test and functional test. I can’t wait until I setup the first functional test for the application to simulate a web user. And of course the best part is: everything comes in an elegant, well-thought, scalability-proven web framework that took you 10 minutes to get started. Suddenly the barrier to entry to mid/ large-scale web projects is dropped significantly (it’s __free__ now, only costs you your opportunity cost). In stead of just WYSIWYG, it’s now **What-You-Think-Is-What-You-Can-Get**, **WYTIWYCG** (weet-tee-wic). Imagination goes wild, how awesome.

Whomever I talk to nowadays, I can’t stop talking non-stop about Ruby on Rails. I feel good sharing it to anyone I know so they can start feeling the same way as I do, as sharing is caring.

I feel good. Do you?

view comments
 


Since I’m learning Ruby on Rails, I feel the need to know the basic syntax of the language. So here is my own primer guide to basic Ruby syntax. The guide was wrote largely based on the [[http://docs.huihoo.com/ruby/ruby-man-1.4/syntax.htmll|original manua]] by Ruby’s author, [[http://en.wikipedia.org/wiki/Yukihiro_Matsumoto|Yukihiro Matsumoto]]

===== Ruby =====
Ruby is case-sensitive. Whitespace characters are space, tab, vertical tab, backspace, carriage return, and form feed. Newlines works as whitespace only when expressions obviously continues to the next line.

==== String literals ====


"remeber to escape \" and \\ #{expression_substituted}" # streng enquoted with doublequote is subjected to expression substitution
'remember to escape \' and \\ #{expression_not_substituted}' # streng enquoted with doublequote is not evaluated
%q!Some string with "double quote" and 'single quote'! # equivalent to '' and don't have to escape double quote or single quote
%Q('Some string with "double quote" and \'single quote\' and back parenthesis \) ') # equivalent to "" and don't have to escape double quote or single quote
%!Some string with "double quote" and 'single quote'! # equivalent to "" and don't have to escape double quote or single quote

==== Expression subtitiion in strings ====

"hello my name is #{$name}" # sub #{$name} with $name

$ and @ variables don’t need to be enclosed within #{}. The # only has special meanings when it’s followed by {,@, and $

==== Regular Expressions ====

%r/STRING/
/regexp/

* **Modifiers**

/regexp/i # case insensitive
/regexp/x # extended expr, no whitespaces and comments are allowed
/regexp/p # POSIX mode, newlines are treated as normal charactor

==== Variables ====

$var # global
@var # instance variable of self
VAR # constant
SomeClass::VAR # constant within a class
var or _var # local variable

=== Pseudo Variables ===
* self
* nil
* true
* false
* __FILE__ : current source file
* __LINE__ : current line

=== Array ===
* [1,2,3]
* %w(foo bar baz): create a new string, space-separated array, equivalient to [”foo”, “bar”, “baz”]

=== Hash ===
* {expr1 => exprA, expr2 => exprB }

===== Method invocation =====
* **method(args1, arg2)**
* **method(*array)** is equivalent to **method(array_member1, array_member2, …)**. The * expands the argument array.)

===== Operators =====

+, -, *, /, %, **, &, |, ^, <<, >>, &&, ||
foo += 5
foo, bar, baz = 1, 2, 3
foo, bar = 1 # foo = 1; bar = nil
foo,*bar = 1, 2, 3 # equivalent to foo = 1; bar = [2, 3] ( the * multiple assignment is used to assign to an array)

===== Control Structure =====
**false** and **nil** are false, everything else are true.
* If statement
if expr [then]
expr...
[elsif expr [then]
expr...]...
[else
expr...]
end

* unless
unless expr [then]
expr...
[else
expr...]
end

=== if and unless modifier ===
* expr1 **if** expr2: if expr2 is true, execute expr1
* expr1 **unless** expr2: if expr2 is false, execute expr1

=== case ===
* case comparison is via the === operator
case expr
[when expr [, expr]...[then]
expr..]..
[else
expr..]
end


case $age
when 0 .. 2
"baby"
when 3 .. 6
"little child"
when 7 .. 12
"child"
when 12 .. 18
# Note: 12 already matched by "child"
"youth"
else
"adult"
end

==== Range ====
* expr1 .. expr2 (similar to awk)
* expr1 … expr2 (similar to sed)

==== Loop ====

while expr [do]
#code here
end

until expr [do]
#code here
end

=== while and until modifier ===

expr1 while expr2 # keep evaluating expr1 while expr2 is true.
expr1 untill expr2 # keep evaluating expr1 until expr2 is true
begin expr1 until expr2 # evaluating expr1 at least 1 time until expr2 is true

==== Iterators ====
* [1,2,3].each do |i| print i*2, “\n” end
* [1,2,3].each{|i| print i*2, “\n”}

==== For (similar to foreach) ====

for lhs... in expr [do]
expr..
end

* Example: for i in [1, 2, 3]
print i*2, "\n"
end

There are 2 special keywords that can be used in the loop body: **next** (jump to next iteration of the inner-most loop) and **redo** (restart the current iteration of the most inner-most loop without checking loop condition)

==== Raising Errors ====
* Raise syntax
raise # raise general exception
raise message_or_exception
raise error_type, message
raise error_type, message, traceback

* Examples
raise "you lose" # raise RuntimeError
# both raises SyntaxError
raise SyntaxError, "invalid syntax"
raise SyntaxError.new("invalid syntax")
raise # re-raise last exception

* $! contains the exception and $@ contains the position in source file.

==== begin block ====
**begin** is different from the uppercase **BEGIN**, which has a totally different meaning

begin
expr1..
[rescue [error_type,..]
expr2..]..
[else
expr3..]
[ensure
expr4..]
end

If exception occurs in **expr1**, **rescue** will execute **expr2**. The matching of **error_type** is done by **kind_of?**. **else** clause has to follow after **rescue** and is executed if no exception occurs in **expr1**. And example:
begin
do_something # exception raised
rescue
# handles error
retry # restart from beginning
end

for i in 1..5
retry if some_condition # restart from i == 1
end

# user defined "until loop"
def UNTIL(cond)
yield
retry if not cond
end

==== BEGIN and END blocks ====

BEGIN {
...
}

BEGIN registers initializing blocks in the appearing order, which will then get executed before any statement in the file. BEGIN has its own internal scope (don’t share local variables with outer scopes) and has to appear at toplevel.


END {
...
}

END register finalizing blocks. END blocks share their local variables. The END statement can only appear at the toplevel. Also you cannot cancel finalize routine registered by END.

==== Class ====

class Classname < SuperClass
expr..
end

class SingleTonClassname << SuperClass
expr..
end

==== Module ====

module Foo
def test
:
end
:
end

==== Method ====
Method has to be defined before it is invoked. It cannot be nested. Method’s return can be defined explicitly with “return”, or implicitly using the last evaluated expression

def fact(n)
if n == 1 then
1
else
n * fact(n-1)
end
end

Method can be declared private inside the function form. If Method is declared outside the class definition, it’s marked private by default. Method declared within class definition is marked public by default.

==== Singleton-method ====

def foo.test
print "this is foo\n"
end

The singleton-method definitions can be nested and are inherited to subclasses. Singleton-method acts as typical class’s method in other OOP languages.

==== alias, undef, and defined? ====

alias method-name method-name
alias global-variable-name global-variable-name

Aliasing numbered global variables is forbidden.

=== undef ===
undef method_name
Used to cancel method definition.

=== defined? ===
defined? expr
If expr is not defined, return false, otherwise return a string describing the kind of expression.

view comments
 

Stock QuoteI’m back from a period of hibernation. Lots of exciting stuff and new things, just barely have enough time to sleep and catch up with all the pending projects that I’ve been crazily taking on. Anyway, today I’d like to share something that maybe useful for someone out there: how to retrieve live stock quote data using Yahoo quote service with ColdFusion.

I was working on a project which originally utilizes the WebServiceX.net’s [[http://www.webservicex.net/stockquote.asmx/GetQuote|StockQuote web service]]. Things were working fine until WebServicex.net is down, as of today, March 22nd, 2007, with a big fat “Service Unavailable”

“Crap!” was what I said to myself. Luckily my work buddy forwarded a [[http://aspalliance.com/articleViewer.aspx?aId=112&pId=#Page2|link]] to an article on how to access the Yahoo Stock Quote service using ASP.NET (C#). Bingo! This was exactly what I needed. Based on the article, I was able to hack out the code using ColdFusion to retrieve stock info in just a few lines of code (or markup since I don’t really consider ColdFusion a real “language”)

===== Yahoo Stock quote CSV service =====
First of all, I didn’t even know if this service ever exists. I don’t really know where the official Yahoo documentations for the Stock Quote CSV service is (anybody knows the link please let me know). More ironically, I used Google to search for tutorials on how to use the Yahoo Stock Quote API. Anyway, this is the URL to request a CSV (comma-separated values) file containing stock information for a particular symbol, in this case, YHOO (I think I do have to give Yahoo some credits for the free service)http://quote.yahoo.com/d/quotes.csv?s=YHOO&f=l1c1v
with
* **s=SYMBOL**: with SYMBOL is the actual stock symbol
* **f=REQUESTED_FORMAT_STRING** where the REQUESTED_FORMAT_STRING is a string of letters representing what fields to be requested. The oder of the letters will be used as the order of the fields in the returned CSV.\\ I messed around and found out about the meaning of the letters used in the **f** parameter. If you want the full information about the symbol, you can use **f=sl1d1t1c1ohgvj1pp2wern** instead.http://quote.yahoo.com/d/quotes.csv?s=YHOO&f=sl1d1t1c1ohgvj1pp2wern Don’t sweat, here comes the explanation for each letter (or letter-digit pair)
* s: the symbol name
* l: last value (or current price). If you use l alone, you will get back a string similar to Mar 22 - 31.26
* l1: (letter l and the number 1) to just get the last value of the symbol
* d: d alone will give you 0, while d1 will return the current date (e.g. 3/22/2007)
* t: t by itself will request the yahoo-generated chart. However, you will get back the chart image with a whole bunch of other HTML garbage, e.g. src=http://chart.yahoo.com/c//y/yhoo.gif" alt="Chart">


* t1: the time of last update, for example 4:00pm.
* c: the change amount. Can either be used as c or c1.
* o: opening value
* h: high value
* g: low value
* v: volume
* j: 52-week low.
* j1: the market cap. This is string like “42.405B” for $42 billion. Man… that can buy **a lot** of hamburger or bowls of phở
* p: after hour price (?)
* p1: (?)
* p2: change percentage e.g. “-0.10%”
* w: 52-week range
* e: EPS (Earning per share)
* r: P/E (Prince/Earning) ratio
* n: Company name

(This list is hand-compiled by me based on my own interpretation. If you find any explanation being inaccurate, please let me know)

===== The Code =====
ColdFusionThe code is pretty simple: we will read from the result the Yahoo CSV service using the tag into a variable. This variable will then contain the comma-separated values list of what we put in for the f parameter. Back to our example, the URL we are requesting is http://quote.yahoo.com/d/quotes.csv?s=YHOO&f=l1c1v, which will return to us a string 31.26,-0.03,13249801. Since the response is in CSV format, we can utilize the ColdFusion List functions like ListLen(), ListGetAt() to access the values.

Here is the CFML code snippet





#stockInfo#




* First, we construct the Yahoo Stock Quote service URL. We are requesting for last price, change amount, and the stock volume.
* Next we use the cfhttp tag to request the url, then grab the content into the cfhttp.FileContent variable and assign to the stockInfo variable. stockInfo will contain something similar to 31.26,-0.03,13249801
* To get the different values in the list, we use ListGetAt() with the appropriate index. And remember, indices of Array and List in ColdFusion start at 1, not 0.

That’s it!

===== Final Remarks =====
I hope you will find this useful. Thanks to Yahoo for providing a free stock quote service. I know I can **abuse** this CSV service as much as possible before getting banned because it’s Yahoo. Any services other than those of Yahoo, Google, Microsoft, I will probably have some guilty thoughts before doing anthing. But it’s Yahoo so I really don’t have no guilt abusing it. Just kidding though. I do appreciate the free (as in free beer) stock quote service.

===== References =====
* Bromberg, Peter, PhD. [[http://www.eggheadcafe.com/articles/20010404.asp|Build a C# Stock Quote WebService and Client using the WebService Behavior HTC (Part I)]]
* Perry, Jason. [[http://aspalliance.com/articleViewer.aspx?aId=112&pId=#Page2|Building a Yahoo stock quote ticker]]

view comments
 


Until recently I have decided to setup a local SVN repository on my computer, which runs Windows XP pro. Setting up SVN with Apache is the best way to access a SVN repository but the thing is, my computer has also IIS installed for ASP.NET development. Normally I have XAMPP installed and have to switch start/ stop Apache and IIS manually whenever I need to do something in either ASP.NET or PHP. To clarify, I do have PHP 5.x setup for IIS but Just didn’t bother to fix the session file permission issues of IIS; I’d rather just switch to the working Apache installation instead using the XAMPP control panel.

I started by installing the [[http://svn1clicksetup.tigris.org/|SVN1clickSetup]]. The installation was painless, however, I needed to restart the service to change some configurations. To register svnserve.exe to run as a serice again, I used this full command:


I:\Program Files\Subversion\bin\svnservice -install -d --listen-port 3690 --listen-host 0.0.0.0 -r K:\svnrepos

The -d param enables svnserve to run as a daemon. We specify the list-host of SVNServe.exe to be 0.0.0.0, which means it will bind to any IP available to the system. The -r specifies which folder to serve as the SVN repository. What left was opening up the 3690 port on the router and have the requests for the SVN service on this port routed to my box. Done!

* If you run `svnservice -debug` and see the `RegQueryValueEx failed with error 0, type 1`, it means that SVNService has successfully registered the SVNServe to run as a service. In fact, `RegQueryValueEx failed with error 0` is not an error or a failure.

* In case you have already run the above svnservice to register the SVNserve as a service but still cannot access the repository, you may have to start the SVNService manually by going through Start > Run > services.msc. Find the service called SVNService and start it. Also switch its Startup Type to Automatic so that SVNService is started on start up.

Cheers!

view comments
 


I was working on some javascript stuff for a project and ran into this problem with setInterval(): for IE 6, calling setInterval() to an object’s method results in the wrong scope. In the object’s method, the alfamous **this** keyword now refers to **window**, instead of the conventional “this” as in “**this object**”. So let me give you some more details on this and a free, amazingly simple solution to this head-ache.

**SPOILER:**\\ the solution uses eval(). if you are allergic to eval(), don’t take my advice.\\ **END SPOILER**

===== The code =====
Let’s look at some code and we’ll have a little discusssion. Here’s the psuedo-code for a fictional TimeTicker object, which is supposed to automatically update a “clock” on the screen every second.


/* A. Constructor */
function TimeTicker()
{
/* A.1 - populate internal variable here, like hour, minute, second, etc. */
...

/* A.2 - now we set the timer to periodically update the time value every 999 miliseconds */
this.timer = setInterval( this.updateTime, 999 );
}

/* B. This function is to update the time value somewhere on the screen */
TimeTicker.prototype.updateTime = function ()
{
/* B.1 - compute new value */
...
this.hour = new_hour_value;
this.minute = new_minute_value;
this.second = new_second_value;
...

/* B.2 - now update the screen */
...
}

===== The problem =====
The above psuedo code will sadly **FAIL** in both IE and FF (not because it’s only psuedo-code!), as the ‘’setInterval()” invocation has **totally changed the scope** of the polled function. First of all, let’s look at ”**A.2**” from above. Calling ”this” within the ‘’setInterval()” will change the reference of ”this” to some other object (which I think is ”this” now refers to ”window”.) Hence calling ‘’setInterval( this.updateTime, 999 )” fails in both Firefox and IE 6, as it means that the ‘’setInterval()” will poll the ”window.updateTime()” function every 999 ms. That’s not what we want, and ”window” object could care less about our ”updateTime()” since we suddenly found ourselves in the wrong scope.

===== The Firefox’s Solution =====
For firefox, the fix is a small rewrite of how we would call the polled-function, updateTime(). The setInterval() function in Firefox is improved and we can now pass an extra parameter to it, and that’s exactly what we will do. We pass in the current object’s reference as ”this” to the a proxy function, which in turn makes a call to the updateTime(). I found this solution through [[http://www.klevo.sk/javascript/javascripts-settimeout-and-how-to-use-it-with-your-methods/|Klevo’s blog]], a web developer from Slovakia.

We will have to rewrite ”**A.2**” as follows:


/* A.2 */
this.timer = setInterval ( function( that ) { that.updateTime(); }, 999, this );

What we just did is we create a proxy function, whose only parameter is ”that”, a pointer to another object. Within this proxy function, we can make invoke all of “that”’s methods! Basically we migrate the scope of ”this” as a reference to the current ”TimerTicker” object into the polled proxy function via a pass-by-reference ”that” parameter. Notice the extra 3rd parameter of ‘’setInterval()”: we are passing ”this”, in this case, a reference to the current ”TimeTicker” object, as the only parameter of the newly created proxy function. Since now ”that” is equivalent to ”this”, we can call all methods of TimeTicker object! Beautiful!

===== The Internet Explorer’s Problem =====
While setInterval() in Firefox provide us a way to pass in extra parameters, IE’s version of ‘’setInterval()” is less flexible (and it also did drive me nuts!) Anyway, let’s talk about the mechanism of IE’s ‘’setInterval()”. According to [[http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/setinterval.asp|MSDN’s manual on setInterval()]], the syntax of setInterval() is

”iTimerID” = ”window”.**setInterval(** ”vCode”, ”iMilliSeconds” [, sLanguage])

with ”vCode” is either a reference pointer or a “string that indicates the code to be executed when the specified interval has elapsed”. Since there’s no way we can pass an extra parameter to the polled-function, we cannot pass ”this” as a 3rd parameter of setInterval() as what we just did for Firefox.

If we rewrite the code as this.timer = setInterval ( this.updateTime(), 999);then 2 things are gonna happen: first,” this.updateTime()” is executed right away. It’s equivalent to a direct call to the ”updateTime()” function of the current object, ”TimeTicker”. As we are still in the scope of the current function, hence, ”this” refers to the current ”TimeTicker” object. Secondly, after the 999ms has elapsed, ‘’setInterval()”" will invoke ”this.updateTime()”, and now ”this” refers to ”window” as we are now out of the scope of the ”TimeTicker” object. And of course, ”window.updateTime()” is wrong. So what you see is that your script will work the first time (when this.updateTime() is executed in the correct scope), and then everything fails (when this.updateTime() is excuted by setInterval() in the wrong scope).

And If we write this.timer = setInterval ( this.updateTime, 999);(Notice the missing parenthesis). This will also fails as when this.updateTime is invoked, we are already in the wrong scope, the scope of ”window” object!

On the other hand, if we writethis.timer = setInterval ("this.updateTime()", 999);we are still in the wrong scope when setInterval() invoke the updateTime() method. ”this” still refers to ”window” when the updateTime() function is executed. Notice that we can include the parenthesis “( )” (and potentially other pass-by-value parameters since the method is refered to as a string and it’s not executed right away, but only when being invoiked by ‘’setInterval()”). However, we can’t pass a pointer to the current object in a string!

We’d like to pass a pass-by-reference pointer object to point to the current ”TimeTicker” object but no matter what we do, we cannot seem to do so. But be hold! Our salvation comes from the use of a glorifying global variable, and of course, a dash of ”eval()”, just enough to tame Internet Explorer.

===== The Internet Explorer’s Solution =====
I’d like to include the code for IE here, just read over and we will discuss later.


/* C. global scope object */
var globalScope = new Array();

/* A. Constructor */
function TimeTicker()
{
/* A.0 - An extra unique identifier for the current object */
this.uniqueId = some_text_or_numers;

/* A.1 - populate internal variable here, like hour, minute, second, etc. */
...

/* A.3 - setInterval Fix */
/* A.3.1 - for IE */
if( document.all )
{
/* A.3.1.1 - make a reference to the current object and saved in the global scope array
* to use later to correct the scope.
*/
globalScope[ this.uniqueId ] = this;
setInterval( 'ieIntervalHandler("' + this.uniqueId + '","updateTime")', 999 );
}
else
{
/* A.3.2 - Mozilla */
this.timer = setInterval ( function( that ) { that.updateTime(); }, 999, this );
}
}

And we add an extra function, ”ieIntervalHandler( **id**, **strFunc** )” to the script.

/* D. - Special IE setInterval handler function with scope corrected */
function ieIntervalHandler( id, strFunc )
{
/* D.1 - correct the scope then make the call */
var scope = globalScope[id];
eval( "scope." + strFunc + "()" );
}

All set? Here comes the explanations: First of all, we added a global associative array named globalScope (”**C**”). This associative array is used to store reference to a particle object based on that object’s unique identifier. Confused? Not a problem, just keep on reading.

Let’s read A.0, this is where we set the unique identifier for this ”TimeTicker” object. For this technique to work, each object **must** have a **unique identifier** since the unique identifier is used as the **key** of the global associative array.

Look at ”**A.3.1**”. Here we do a little browser-intelligence. If the browser doesn’t know ”document.all”, which is IE-specific, we use the improved version of ‘’setInterval()” as mentioned in the above Firefox’s solution section. If the browser is indeed IE, at ”**A.3.1.1**”, we store the reference to this ”TimeTicker” object as an element in the globalScope associative array. Then we cheerfully and confidently ‘’setInterval()” the ”ieIntervalHandler()” function (see ”**D.1**”). We do a pass-by-value the unique ID of the current ”TimeTicker” object as the first parameter of ”ieIntervalHandler()”, and ”updateTime” as the name of the method of the same ”TimeTicker” object.

Look at ”**D.1**”. Here we have a 2-line function. First, we get the reference to the particular TimeTicker object, which we already stored in the globalScope associative array back in ”**A.3.1.1**”. Since we are now in the scope of ieIntervalHandler(), our ‘’scope” variable is pointing to the ”TimeTicker” object. With the correct reference to the correct object, now we can make the call to the correct method with a quick, painless ”eval()”eval( "scope." + strFunc + "()" );

What did we just do? We use a global array to store the references so that later on we can get to the right object, even when ieIntervalHandler is invoked by ‘’setInterval()” and the scope now is all over the place — we could care less! Hence we now can solve the wrong scope issue within IE. And guess what, now we can have any object to poll a method of itself! How awesome is that?

===== Memory Issue =====
Since we need to keep polling a function, we need to be careful of not creating more and more objects or functions that the garbage collect will never be able to purge because of a hidden reference somewhere. If you do create a lot of objects that do self-polling using this global associative array technique, when destroying the object, you will probably have to set the element of the globalScope to ”**null**” also, so that there is no further reference to the destroyed object. Also, in ”**A.3.2**”, we do create a new function everytime we’d like to run the timer, this may be a potential memory leaking point on Firefox.

I’d like to leave the quest of battling memory-leak monster to somebody else, but just remeber to watch out for potential weak point where memory leak can happen, especially when your page will be opened for a prolonged preriod of time.

===== Keywords spam =====
This setInterval() and the scope problem is a pretty abstract and hard to describe problem. I just include some potential search keywords here so that other people can by chance find this page. Call it keyword spam, call it shameless-self advertising, I could care less, but if somebody find this helpful, then I call it success :)

setInterval scope loosing, setTimeout, this setInterval wrong scope, javascript setInterval scope, global associative array scope correction, object oriented setInterval, self polling, this polling scope error, internet explorer setInterval fail, firefox setInterval fail, setInterval object.

===== Final remarks =====
Thank you for reading! I hope this helps. And I’d like to wish you a …

Merry Christmas and Happy New Year!

4:13AM, Dec 23, 2006.

view comments