Posts about javascript

JSON with Special Characters fails in IE

If you try to eval a JSON string that has special characters in it(non-ascii, or chr > 127), it will error out. The other browsers work fine.
Posted by Toby about 1 year ago about crossbrowser, ie, javascript, json and programming (0 comments)

Trying to Index Strings in IE

'abc'[0]
gets you undefined in IE. The correct way is to do 'abc'.charAt(0).
Posted by Toby about 1 year ago about crossbrowser, ie, javascript and programming (0 comments)

Prototype Inheritence in Python

One of Toby's favorite pastimes is to take concepts from one language and realize it in another. In this episode: Toby implements Javascript-style prototype inheritence in Python.

One thing that is super cool about Javascript is the fact that objects are just maps. Not only can you add attributes dynamically at any point, you can also add methods dynamically. In Python, you can add methods dynamically, but normally you'd have to add it into the class. But there are cases when you don't want to bother making a class. This inspired me to see how far I can go in making Python behave more like Javascript.

Introducing prototype.py

prototype.py lets you write code in Python with Javascript-style prototype inheritence semantics. If you are not familiar with prototype inheritence, just read on for now. I will link to some resources at the end. Now, let's see how to use this bad boy. First you import the module:
>>> from prototype import *
To create a constructor(we don't really have classes anymore), you write a function with the @constructor decorator:
>>> @constructor
... def Person(this, first, last):
...   this.firstName = first
...   this.lastName = last
...
>>> Person
<constructor 'Person'>
I am going to use this rather than self and camelCase rather than under_scores for prototype-style code, because, well...Dorothy, we are not in Kansas anymore.

Now you can do:
>>> bird = Person('Charlie', 'Parker')
>>> bird.firstName
'Charlie'
>>> bird.lastName
'Parker'
You can add attributes to the object just like in normal Python. But unlike in normal Python, which would raise an AttributeError when trying to access non-existent attributes, in prototype-land it merely returns None:
>>> print bird.age
None
You can dynamically add a method to the instance just by tagging on a function:
>>> def sing(this):
...   print '%s sings!!' % this.lastName
...
>>> bird.sing = sing
>>> bird.sing()
Parker sings!!
This affects only the bird instance. If you want the method to be added to all instances of Person however, you can add it to the prototype of Person.
>>> Person.prototype.sing = sing
>>> monk = Person('Thelonious', 'Monk')
>>> monk.sing()
Monk sings!!
This works because Person.prototype is the prototype of the monk instance. In code, this means:
>>> monk.__proto__ == Person.prototype
True
When the sing attribute is not found on the monk instance itself, it will follow the __proto__ reference and look it up in its prototype, which is also referred to as its parent. We can manipulate the parent link:
>>> monkJr = Person('T.S.', 'Monk')
>>> monkJr.__proto__ = monk
so that now monkJr inherits all of monk's attributes:
>>> monk.hair = 'black and curly'
>>> monkJr.hair
'black and curly'
The following are some other properties demonstrating the prototype inheritence model:
>>> assert monkJr.constructor == monk.constructor == Person
>>> assert Object.prototype.constructor == Object
>>> assert Person.prototype.constructor == Person
>>> assert Person.prototype.__proto__ == Object.prototype
If this seems confusing, remember that in prototype-land, there are two kinds of things: constructors and instances. The prototype of a constructor is nothing more than an instance of the type that the constructor represents. A new instance returned from calling a constructor will have its parent set to the prototype of the constructor.

Things You Can't Do in Javascript, i.e. the 1+1>2 Effect

Python is a more powerful and flexible language than Javascript, so, why am I dumbbing it down to Javascript's level? To show that I am not trying to do that at all, let me point out that there are at least a couple of really cool things you can do with prototype.py that you can't with Javascript, simply due to the fact that it is in Python.

The first thing is properties. With prototype.py, you can add properties to objects like so:
>>> def getName(this):
...   return '%s %s' % (this.firstName, this.lastName)
...
>>> Person.prototype.name = property(getName)
>>> bird.name
'Charlie Parker'
You can also specify setters and deleters in the way you'd expect:
>>> def setName(this, name):
...   first, last = name.split(' ')
...   this.firstName = first
...   this.lastName = last
...
>>> def deleteName(this):
...   del this.firstName
...   del this.lastName
...
>>> Person.prototype.name = property(getName, setName, deleteName)
>>> bird.name = 'Dizzy Gillespie'
>>> bird.name
'Dizzy Gillespie'
>>> del bird.name
>>> bird.name
'None None'

The second thing is named parameters, keyword parameters and optional parameters. Let's just do an example with keyword parameters. Let's say I just wanted a way to easily create ad-hoc objects as key-value pairs, I could write:
>>> @constructor
... def Data(this, **kwargs):
...   for key in kwargs.keys():
...     setattr(this, key, kwargs[key])
...
Which lets me write:
>>> project = Data(project='prototype.py', language='python')
But, I could also define methods and properties in this way:
>>> file = Data(fileName='prototype.py', fileExt=property(getExt)
                    read=read, write=write)
Sweet!

A Note About the Implementation

The implementation of prototype.py is only about 60 lines of Python at time of writing, would have gone down to 40 without property support. The code can be found here. 

A big discovery that enabled me to do this was the new module. It allowed me to take a function and make it into an instance method by binding it to an object:
method = new.instancemethod(function, object)

Another note is that I made the design decision that for methods, I chose to store the unbound function rather than the bound method in the __dict__ of the object. I would then bind the function on the fly when it's asked for. This made it very easily to inherit methods because you don't have to worry that the method is really bound to the parent rather than the instance in question.

Further Reading About Prototype Inheritence

If you want to learn more about prototype inheritence, try:
Posted by Toby about 1 year ago about javascript, programming, prototype and python (4 comments)

Null in 10 Languages

  • Java, Javascript, C#: null
  • Ruby, Smalltalk, Lisp, OCaml: nil
  • Lisp: ()
  • Python: None
  • Haskell: Nothing
  • C: 0
Posted by Toby about 1 year ago about c, c#, haskell, java, javascript, lisp, ocaml, programming, python, ruby and smalltalk (0 comments)

Modifying Core Types in ActionScript 3 Using the Prototype Object

ActionScript 3 has a Javascript lineage. It was essentially a fork of Ecmascript. Plus, the Adobe team has worked hard on making the language a proper superset of the Ecmascript specification. This is why although ActionScript 3 was a major architechtural change from 2, and as a result became much more like Java than Javascript, it still has support for the prototype object

When I learned about the prototype object, it was a fresh air from traditional class-based OOP. Studying cool libraries like prototype.js made me realize that the prototype model makes javascript far more flexible than some other strictly class-based OO languages.

One of the cool things you can do with the prototype object in javascript is modify the core classes of the language, like Array, String, and Date. You can do this in ActionScript 3 too, for it conforms to Ecmascript 4. For example, let's say you want to write the collect function for arrays a la ruby. You would do:
Array.prototype.collect = function(f){
  var ret = [];
  for each(var it in this) ret.push(f(it));
  return ret;
}
There you see me using the nice  for each syntax. But, this is going to break the behavior of the array, because now the collect function is going to show up in the enumeration in the for each loops. We don't want that, so to fix that we are going to set the collect attribute of Array.prototype to not be enumerable:
Array.prototype.setPropertyIsEnumerable('collect', false);
This allows you to write the following code:
[1,2,3].collect(function(i){ return i * 2; });
// result would be [2,4,6]
It's kinda tedious to have to setPropertyIsEnumerable for every time we add a function to an existing type, so I wrote a convience function:
function addMethodsTo(cls:Class, methods){
    for (var name:String in methods){
        cls.prototype[name] = methods[name];
        cls.prototype.setPropertyIsEnumerable(name, false);
    }
}
Which you can use like so:
addMethodsTo(Array, {
    collect: function(f){
        var ret = [];
        for each(var it in this) ret.push(f(it));
        return ret;
    },
    anotherMethod: function(){
        ...
    },
    ...
});
This is sort of like the style prototype.js uses for extending/creating classes.

A Word of Caution

Before you consider going further with this, I must advice you to think twice before using this technique(however, I hope you do decide to use it afterwards ;). There are several caveats:
  1. The prototype-based style is a second-class citizen in the world of ActionScript 3 and Flex. The Adobe team as well as the community seem to be much more committed to the class-based approach. I will describe some of the rough edges below.
  2. You will give up compile time type checking for the portions of your code that use this style.
  3. Prototype inheritence is handled by a completely different mechanism than class-based inheritence in the Flash VM and is not as performant.

Where to put this Code?

You saw the code example above, but, where do you put it? Since I decided to use a helper function(addMethodsTo), the code cannot be directly pasted inside the class scope of a class unless the addMethodsTo function is declared to be static(you can only make a method call directly inside class scope if it is a class method). As, a general solution, I'd rather the code be portable. So it should be includable in both class and function scope, and also, I'd like it not to pollute any namespaces.

My current solution is to put this bit of code inside an anonymous function which immediately gets executed:
// contents of includes/Array.as
(function(){
    include 'addMethodsTo.as';
    addMethodsTo(Array, {
        collect: function(f){
            var ret = [];
            for each(var it in this) ret.push(f(it));
            return ret;
        }
    });
})();
The addMethodTo function is pulled into a separate file to be easily includable else where.
So, with this, I would do the following to include this Array functionality:
include 'includes/Array.as';
Head over to Github for the complete structure of the files.

These methods are added during runtime - at exactly the time the above line of included code is executed, and not a moment before. I like to do the include at the top level of the application, this way the entire program has immediate access to the new methods. Oh, and when I said entire program, I do mean the entire program - not just the files that happen to include the file. Well, this is good and bad. This means if you create components that use the array extensions you've created without explicitly including it(you've included it at the entry point of your program), then you have created an invisible dependency. If you try to take the component and use it in a different project without the array extensions, it will not work. Of course, you could also make the dependency explicit by including the file everywhere you are using them, but 1) that's kinda tedious/repetitious, and 2) there's nothing enforcing you to do this.

Pitfalls and Gotchas

As I mentioned, the prototype-based programming style is a second-class citizen in the ActionScript 3 world, and so, its use is not particularly well supported. First of all, the compiler does not recognize any of the methods added via the prototype mechanism, and thus cannot perform static type checking on them. But what is funny is the way the compiler copes with this - it depends...on the type in question. For Arrays, the compiler simply allows all method calls - you can call any method on an array, even if it doesn't exist, the compiler won't complain. So, for a call like:
[1, 2, 3].collect(...);
The compiler won't even say a word. But for Dates, it gives a warning message. This:
new Date().format()
would trigger this warning:
Warning: format is not a recognized method of the dynamic class Date.
But, for strings, it's a different story still:
'one, two, three'.csv2Array()
compiler says:
Error: Call to a possibly undefined method csv2Array through a 
    reference with static type String.
And the same thing with numbers:
(2).minutes().ago()
compiler says:
Error: Call to a possibly undefined method minutes through a 
    reference with static type int.
The work around for strings and numbers is to upcast it to an Object:
Object('one, two, three').csv2Array();
Object(2).minutes().ago();
or if you just have an untyped variable, it'll work just fine:
var x = 2;
x.minutes().ago();
See the full code example here, and the demo here.

What about runtime error handling? So let's see what happens if you don't include the extensions and run the code. When I took out the array extension methods, the runtime dutifully throw me the:
TypeError: Error #1006: collect is not a function.
This is good, just what I would expect. For Date, it works the same way. Now let's try taking out the string extensions:
TypeError: Error #1006: value is not a function.
Uhh, what? Not really sure what you mean. And as you would expect, it works like this for Number as well.

I have also seen cases where the runtime simply completely muffles an error when there's an undefined method being tried as someone documented here. But I am not able to reproduce this just now. Also on another note, the error stacktrace from the flash player(debug version) is not very helpful because although it gives the call stack, there are no line numbers. I am sure that you'd get a better experience using Flex Builder, however.

I think that about wraps it up. Although extending core types is fun, powerful, and elegent, it's also full of holes and flying scissors everywhere. Are you ready to jump into this brave new world?

A message to the Adobe Flex/ActionScript team: I implore you to put more effort into the prototype-based side of the language. It allows for many possibilities which its class-based counterpart cannot offer. I don't dislike the class-based approach. I think the two each have their own strengths and weakness. Which is why I love this hybrid aspect of ActionScript 3 which allows me to use either style in the same environment. I believe that if the prototype-based aspect of ActionScript were to improve and get more exposure, it would not only become a better language, but also a more wide spread language.
Posted by Toby about 1 year ago about actionscript, flex, javascript, programming and prototype (11 comments)

Using the Flex-Ajax Bridge

The Flex-Ajax Bridge is a little javascript library bundled with the Flex SDK that allows you to use javascript to drive your Flex app. It can be really handy for debugging or experimentation when you use it with Firebug's console. For complete setup up instructions, see here. You do need to modify your Flex code to get the bridge to work. It's just a one-liner though.

To use it, first you get a reference to your flex app:
app = FABridge.flash.root()
To get a component by ID, you would do something like:
app.get('myDataGrid')
To find out the type of the component:
app.get('myDataGrid').typeName
You can call the methods of the component as you would in normal ActionScript. To access the component's properties though, you need to use the Java getter/setter convention:
app.get('myDataGrid').getSelectedItems()
This isn't so nice. Ideally, a seamless experience would allow you to write:
app.myDataGrid.selectedItems
I guess this is where the weakness of Javascript is coming through. There's no language support for properties(like those in ActionScript, C# Python, etc.) and also no way to do method interception(method_missing in ruby). But I digress.
To instantiate an object of a class in Flex-land, you'd do something like:
sprite = FABridge.example.create("flash.display.Sprite");
This would call the default constructor. I am not sure how you'd call a constructor with arguments, probably just add on the arguments to create()?
A really cool and useful thing you can do is pass functions as event handlers to into Flex-land. Try this:
app.get('myButton').addEventListener('click', function(e){
    console.log('button clicked!');
});
Now go click that button...cool, heh?

Anyway...in conclusion, the Flex-Ajax Bridge is really nice...especially when combined with Firebug.
Posted by Toby about 1 year ago about firebug, flex, javascript and programming (0 comments)

jQuery Style BDD

I have been warming up to the jQuery style of using method chaining. Then I thought: why are most unit test frameworks class based? There's no reason why we can't do it in the jQuery style...
Something like this:
  $.describe('Bowling')
    .beforeEach(function(){
      this.bowling = new Bowling();
    })
    .should('score 0 for gutter game', function(){
      for (var i = 0; i < 20; i++) this.bowling.hit(i);
      this.bowling.score.shouldEqual(0);
    })
    .should('accumulate score', function(){
      this.bowling.hit(20);
      this.bowling.hit(10);
      this.bowling.score.shouldEqual(30);
    });
I am liking this syntax. The full bowling example is here. I guess I'll call this jquery.bdd. I just started using git/github btw. This is one of my first projects on it. Fork me. Fork me please.
Posted by Toby about 1 year ago about bdd, javascript, jquery and programming (8 comments)

Multiline Strings in Javascript

I was looking through the code in facebox.js(a jQuery plugin) and I saw this:
'\
    <div id="facebox" style="display:none;"> \
      <div class="popup"> \
        <table> \
          <tbody> \
            <tr> \
              <td class="tl"/><td class="b"/><td class="tr"/> \
            </tr> \
            <tr> \
              <td class="b"/> \
              <td class="body"> \
                <div class="content"> \
                </div> \
                <div class="footer"> \
                  <a href="#" class="close"> \
                    <img src="/facebox/closelabel.gif" title="close" class="close_image" /> \
                  </a> \
                </div> \
              </td> \
              <td class="b"/> \
            </tr> \
            <tr> \
              <td class="bl"/><td class="b"/><td class="br"/> \
            </tr> \
          </tbody> \
        </table> \
      </div> \
    </div>'

Wow, I am ashamed I didn't know you could do multi-line strings like this earlier!! Although not as nice as multi-line strings in Ruby/Python/Perl, this definitely beats quotes and plus signs.
Posted by Toby about 1 year ago about javascript and programming (0 comments)

Developing in AIR just got a little suckier

I wanted to try putting a javascript console inside an AIR app to aid development. I tried firebug lite, which I've been using a lot to debug IE. When I started up the app and hit F12, the console came up and everything, '1+2' gave 3, so time to rejoice? Not so fast, if you try to type 'window', or 'document', you get this error:
Error: Adobe AIR runtime security violation for JavaScript
 code in the application security sandbox (eval)

So they sandboxed eval and restricted access the dom and any other api that's available. And it's for... security reasons. What does Adobe have against eval? This sucks!
Posted by Toby about 1 year ago about air, javascript and programming (0 comments)

IE Woes: One

Man! Have I been at war with IE lately. I have been holding back a lot of blog posts related to debug IE problems, and I going to start spewing them out now one by one. For the first installment I'll talk about one I encountered these couple of days...

Ever get this IE error?
When you click "Ok", this is what you see:

Ouch! Can this be any more catastrophic?(Yeah, that's my Chandler impression.)

According to this forum post, this happens if you have script tags in your document that's modifying other parts of the dom before the document finishes loading. Umm, okay, but I still had a hard time finding out the exact point this caused the problem. I used the comment-out-code-and-see-if-it-still-breaks-binary-search methodology, and came up with some work arounds which involved delaying the execution of some setup code. But, this catastrophic error came back to haunt be time and time again. Clearly I didn't find the root cause of this error or I wouldn't be committing it repeatedly.

But finally, I found it(I think, well at least one of the root causes). I am using firebug lite in development, which creates iframes and panels in the pages that pops out and in just like firebug. When you call console.log with firebug lite, guess what happens? Yeah, it modifies the console output window - a part of the dom that is outside of where the script tag is. Got rid of those console.log statements and fixed it.

In conclusion, do not do what I did!
Posted by Toby about 1 year ago about crossbrowser, ie, javascript and programming (0 comments)

IE getElementById looks up "name"

Posted by Toby about 1 year ago about crossbrowser, ie, javascript and programming (0 comments)

Dissecting the Prototype Chain

I realized when I was trying to explain the prototype chain to my wife the other day that I didn't get it completely. So I went back to the drawing board and this is the example that I came up with:

function inherit(parent){
    var obj = function(){};
    obj.prototype = parent;
    return new obj();
}

toby = {};
toby.name = 'Toby';
toby.age = 27;
toby.eyeColor = 'brown';
toby.hairColor = 'dark';

console.log(toby);
// Object name=Toby age=27 eyeColor=brown hairColor=dark

emma = inherit(toby);
emma.name = 'Emma';
emma.age = 1

console.log(emma);
// Object name=Emma age=1 eyeColor=brown hairColor=dark

console.log("Toby is Emma's parent: " + 
	(emma.__proto__ == toby));
// true
Posted by Toby about 1 year ago about javascript, programming and prototype (0 comments)