Finally: Singletons, the Mootools way

Jan 18 2010 Published by Eneko Alonso under uncategorized

I have been using for a while the “new new Class” syntax to create singletons on the projects I am working on. This is for many reasons, but specially because I didn’t like other solutions like Class.Mutators, Class.Oclude or extending a plain object with $extend().

Now, after discussing a little bit on the Mootools email list about what was the best way to create singletons, I have created Class.Singleton so we can create singletons the Mootools way. Here is how it works:

  1. var MySingleton = new Class.Singleton({
  2.     initialize: function(){
  3.         // code here
  4.     },
  5.     method1: function(){
  6.         // code here
  7.     },
  8.     method2: function(){
  9.         // code here
  10.     }
  11. });

Using inheritance, mixins, etc

Class.Singleton works like defining any other Mootools class using Class(), so we can have inheritance, mixins, etc.

  1. var BaseClass = new Class({
  2.     initialize: function() {
  3.         // Initialization code here
  4.         console.log('BaseClass initialized.');
  5.     },
  6.     method1: function() {
  7.         // some code
  8.     }
  9. });
  10.  
  11. var MySingleton = new Class.Singleton({
  12.     Extends: BaseClass,
  13.     initialize: function() {
  14.         this.parent();
  15.         console.log('MySingleton singleton initialized.');
  16.     },
  17.     method1: function() {
  18.         this.parent();
  19.         // more code
  20.     }
  21. });

Hope you like it!

Repository url: http://github.com/eneko/Class.Singleton

No responses yet

Setters & Getters on Mootools classes

Jul 20 2009 Published by Eneko Alonso under uncategorized

Although I haven’t need them for my classes, I thought it would be very cool to have the possibility to use them. Setters and Getters are very popular in modern programming languages, since they let you do some actions when a member/property of an object is being accessed or modified. Setters and Getters are native on Javascript objects.

  1. // Setter on plain JS
  2. var b = {
  3.   saveCount: 0,
  4.   set count (c) {
  5.     console.log('Setting count (B):' + c);
  6.     this.saveCount = c;
  7.   },
  8.   get count () {
  9.     console.log('count is being accessed (B)');
  10.     return this.saveCount;
  11.   }
  12. }
  13. b.count = 5;
  14. console.log("Count (B): " + b.count);

Well, Mootools objects created using Class do not support that syntax. Fortunately, we can use the __defineSetter__ and __defineGetter__ functions:

  1. // Setter in Mootools
  2. var A = new Class({
  3.   saveCount: 0,
  4.   initialize: function() {
  5.     this.__defineSetter__("count", this.setCount);
  6.     this.__defineGetter__("count", this.getCount);
  7.   },
  8.   setCount: function(c) {
  9.     console.log('Setting count(A):' + c);
  10.     this.saveCount = c;
  11.   },
  12.   getCount: function() {
  13.     console.log('count is being accessed (A)');
  14.     return this.saveCount;
  15.   }
  16. });
  17.  
  18. var a = new A();
  19. a.count = 5;
  20. console.log("Count(A): " + a.count);

Nice, uh?

No responses yet

Sending messages between Javascript objects

Apr 23 2009 Published by Eneko Alonso under uncategorized

When applications (or websites) get pretty big, it usually happens that a lot of different objects or classes interact with each other or, even worst, depend on each other to achieve the site functionality.

A simple example could be a Tabs manager class, which controls a set of tabs in the page. Sometimes, the content in this tabs is sensitive to when the tabs are shown or hidden. At this point you have three options: either the Tabs class needs to know about the content or you create a set of callback functions or you use custom events. Still, for every one of these options you are going to need variables referencing the instances of your classes (this is: var myTabs = new Tabs())

Personally, I don’t like having global variables for the objects I create. I think the code gets very messy and complicated.

So, after dealing with all these issues at work day after day I thought it would be very cool to have a messaging system between my classes, the same way other languages like Cocoa do (in a more simpler way, at least for now).

Sending messages between classes

Wouldn’t it be nice if the Tabs class would send a message every time a new tab is selected? Wouldn’t it be nice if the objects that are going to reside inside those tabs could listen to that message and update accordingly?

To do this, I created a Base class and a Register, where my objects will register automatically upon instantiation (thanks to the Base class).

  1. var InstanceRegister = new Class({
  2.   instances: [],
  3.   addInstance: function(object) {
  4.     this.instances.push(object);
  5.   },
  6.   broadcastMessage: function(msg) {
  7.     $A(this.instances).each(function(item, index) {
  8.       item.processMessage(msg);
  9.     });
  10.   }
  11. });
  12. var Register = new InstanceRegister();
  13.  
  14. var Base = new Class({
  15.   ClassName: 'Base',
  16.   Implements: Options,
  17.   initialize: function(options) {
  18.     this.setOptions(options);
  19.     Register.addInstance(this);
  20.   },
  21.   processMessage: function(msg) {
  22.     console.log(this.ClassName, ' msg received: ');
  23.     console.dir(msg);
  24.   },
  25.   sendMessage: function(msg) {
  26.     Register.broadcastMessage(msg);
  27.   }
  28. });

As you can see, the register is just an array of Instances. Yes, Register is a global object, but it will be the only one we will need. Meanwhile, the Base class adds the new instance to the Register automatically. For convenience, the Base class has a sendMessage method. Also, for convenience, I like to add a ClassName property to all my classes in case I need it later for logging, instance class type identification, etc.

Now, thanks to MooTools, we can create our classes and make them inherit from Base. We can override the processMessages method and act accordingly:

  1. var Tabs = new Class({
  2.  ClassName: 'Tabs',
  3.  Extends: Base,
  4.  …
  5.  activateTab: function(tab) {
  6.   …
  7.   this.sendMessage({msg:'tabActivated', data:tab});
  8.  }
  9. });
  10.  
  11. var VideoPlayer = new Class({
  12.  ClassName: 'VideoPlayer',
  13.  Extends: Base,
  14.  …
  15.  processMessage: function(msg) {
  16.   if (msg.msg == 'tabActivated' && msg.data = 'video-tab') {
  17.    // Play video
  18.   }
  19.  }
  20. });

The beautifulness of this code resides, as I mentioned before, in the absence of any object references. Tabs doesn’t know anything about the VideoPlayer class nor any other object listening to the messages. And the VideoPlayer doesn’t know anything about the Tabs class either. It only knows about the message it has to listen to. No object references, no methods, no callbacks.

Pay attention now. This is the best part! Whenever we instance our classes, no matter how many times we do, we don’t need variable references anymore:

  1. new Tabs();
  2. new VideoPlayer();

Nice, uh?

Since I implemented this class I use it a lot on every project at work. It makes my life easier, keeping my classes simple and independent from each other. It’s even better. We have got to a point where we have integrated this feature with our Flash components, so these send messages to the Register when needed and any JS object listening reacts to them as needed.

By doing this, even being unidirectional (Flash to JS only), we have achieved something great: from now on, our Flash objects don’t need to know anything about our JS objects at all. Just send a message to the register and done.

At any point, even from Firebug, you can send a message to the Register. This is very nice, even for debugging:

  1. Register.broadcastMessage({msg:'hello',data:'world'});

A listener class

I found it is very nice, while in development, to have a Listener class debugging any message received. This way I don’t need to add a console.log call on all my classes to output received messages. The Listener will do it for me:

  1. var Listener = new Class({
  2.  Extends: Base,
  3.  initialize: function() {
  4.   this.parent();
  5.   this.ignoreMessages = false;
  6.  },
  7.  processMessage: function(msg) {
  8.   if (msg.msg == 'stopListener') this.ignoreMessages = true;
  9.   if (msg.msg == 'startListener') this.ignoreMessages = false;
  10.   if (this.ignoreMessages) return;
  11.   console.log('Listener: msg received:');
  12.   console.dir(msg);
  13.  }
  14. });
  15. new Listener();

Even you can control the Listener by sending custom messages to it! Awesome!

Could this be achieved with custom events?

With Mootools, creating custom events is piece of cake. But from what I understand, custom events work only inside the object that is firing them. This is, if object A fires an event ‘customEvent’, you can only listen to it if you add a callback function when you instantiate that class:

  1. var A = new Class({
  2.   Implements: Events,
  3.   initialize: function() {
  4.     document.body.addEvent('click', function() {
  5.       console.log('A: body clicked');
  6.       this.fireEvent('bodyClicked', [this]);
  7.     }.bind(this));
  8.   }
  9. });
  10.  
  11. var B = new Class({
  12.   doSomething: function() {
  13.     console.log('B: doing something…');
  14.   }
  15. });
  16.  
  17. new A({
  18.   onBodyClicked: function() {
  19.     // Tell B to do something (you need a reference to B!)
  20.   }
  21. });
  22. new B(); // Will never do something

Ideally, B should be able to listen to the bodyClicked event without passing any info when A is instantiated. But if I’m not mistaken, this is not possible.

Revised version

I decided that it would be cool to have the Messenger as something my classes could implement, instead of inherit from (Base). Also, it would be good if one object could register for a specific message only, which would improve performance too.

  1. var NotificationServiceCenter = new Class({
  2.  instances: {},
  3.  addObserver: function(msg, instance) {
  4.   if (!this.instances[msg]) {
  5.    this.instances[msg] = [];
  6.   }
  7.   this.instances[msg].push(instance);
  8.  },
  9.  broadcastMessage: function(msg, data) {
  10.   if (this.instances[msg]) {
  11.    $A(this.instances[msg]).each(function(item, index) {
  12.     item.processMessage(msg, data);
  13.    });
  14.   }
  15.  }
  16. });
  17. var NotificationService = new NotificationServiceCenter();
  18.  
  19. var Messenger = new Class({
  20.  addMsgEvent: function(msg) {
  21.   NotificationService.addObserver(msg, this);
  22.  },
  23.  sendMessage: function(msg, data) {
  24.   NotificationService.broadcastMessage(msg, data);
  25.  },
  26.  processMessage: function(msg, data) {
  27.   // For implementation on the final Class
  28.  }
  29. });
  30.  
  31. var A = new Class({
  32.  Implements: Messenger,
  33.  initialize: function() {
  34.   document.body.addEvent('click', function(){
  35.    console.log('A: document body clicked');
  36.    this.sendMessage('documentbodyclicked', 'Hello world!');
  37.   }.bind(this));
  38.  }
  39. });
  40.  
  41. var B = new Class({
  42.  Implements: Messenger,
  43.  initialize: function() {
  44.   this.addMsgEvent('documentbodyclicked');
  45.  },
  46.  processMessage: function(msg, data) {
  47.   console.log('B: msg received: ', data);
  48.  }
  49. });
  50.  
  51. new A();
  52. new B();

Here you go!

2 responses so far

Setting up timers and intervals inside JS objects

Apr 07 2009 Published by Eneko Alonso under uncategorized

It may seem trivial but it has its tricky point. Usually, in procedural Javascript (this is, non object oriented programming), timers are set up passing the callback function on a string:

  1. function hello() {
  2.   alert("hello");
  3. }
  4. // Will execute hello() after 10 seconds
  5. setTimeout('hello()', 10000);

For this code to work, hello() has to be a global function (actually a function of the window object). Otherwise, when the timer times out, it won’t find it.

When writing object oriented code, one would like to call a function inside the object itself, not a global function. We can achieve this passing an anonymous function to the setTimeout function that calls our function:

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     setTimeout(function() { this.hello(); }, 10000); // This wont work
  4.   },
  5.   hello: function() {
  6.     alert("hello");
  7.   }
  8. });

The previous code wont work, since this inside the anonymous function points to the window object and not to our instance of MyClass. We solve this using the bind function provided by Mootools:

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     setTimeout(function() { this.hello(); }.bind(this), 10000);
  4.   },
  5.   hello: function() {
  6.     alert("hello");
  7.   }
  8. });

This code will work fine, but it still has a big problem. If we wanted to access any member or function of our instance inside the hello() function, it wouldn’t work. This is because when the timer times out, the context of our instance is lost. Inside the hello() function, this will point to the window object.

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     this.text = 'hello';
  4.     setTimeout(function() { this.hello(); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text); // This wont work
  8.   }
  9. });

There are multiple ways to solve this issue but my favorite is to use the function call() of the function object. This function let’s you pass an object while calling your function that will become this inside it.

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     this.text = 'hello';
  4.     setTimeout(function() { this.hello.call(this); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text);
  8.   }
  9. });

Now we can use this inside the hello() function and everything will work fine, no matter how many instances of MyClass we create.

  1. var MyClass = new Class({
  2.   initialize: function(text) {
  3.     this.text = text;
  4.     setTimeout(function() { this.hello.call(this); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text);
  8.   }
  9. });
  10. new MyClass('hello');
  11. new MyClass('hi there!');
  12. new MyClass('wassup?');

Enjoy :)

2 responses so far

Threads in Javascript

Dec 14 2008 Published by Eneko Alonso under uncategorized

Well, let’s make it clear: There is no way to create actual threads in Javascript. Javascript code runs on a single thread inside the browser. This is, only one line of code is running at a time. In fact, until Google’s Chrome, all pages/tabs opened on a browser where running on the same system thread.

So what is this about Javascript threads? Well, maybe we cannot create them, but we can emulate them. Since Javascript is an event driven language, we can use an Object Oriented approach and create an object that stays ‘alive’ with the use of a timer. Now we only need a way to control that object and to interact with it.

Thread Class

In order to accomplish this functionality I created this Mootools-based Thread class:

  1. Thread = new Class({
  2.   ClassName: 'Thread',
  3.   Implements: [Options, Events],
  4.  
  5.   threadId: '',
  6.   timer: null,
  7.   stopped: true,
  8.  
  9.   options: {
  10.     interval: 1000,
  11.     autostart: false
  12.   },
  13.  
  14.   initialize: function(options) {
  15.     ThreadController.add(this);
  16.     this.setOptions(options);
  17.     if (this.options.autostart) this.start();
  18.   },
  19.  
  20.   start: function() {
  21.     this.stopped = false;
  22.     this.__setTimer();
  23.     this.fireEvent('start', [this]);
  24.   },
  25.  
  26.   stop: function() {
  27.     this.stopped = true;
  28.     this.__stopTimer();
  29.     this.fireEvent('stop', [this]);
  30.   },
  31.  
  32.   setInterval: function(time) {
  33.     this.__stopTimer();
  34.     this.options.interval = time;
  35.     this.__setTimer();
  36.   },
  37.  
  38.   // For inheritance
  39.   beforeExecute: function() {
  40.     this.fireEvent('beforeExecute', [this]);
  41.   },
  42.  
  43.   // For inheritance
  44.   execute: function() {
  45.     this.fireEvent('execute', [this]);
  46.   },
  47.  
  48.   // For inheritance
  49.   afterExecute: function() {
  50.     this.fireEvent('afterExecute', [this]);
  51.   },
  52.  
  53.   /* ————— */
  54.  
  55.   __setTimer: function() {
  56.     if (!this.stopped) {
  57.       this.timer = setTimeout(function(){
  58.         this.__execute(this);
  59.       }.bind(this), this.options.interval);
  60.     }
  61.   },
  62.  
  63.   __stopTimer: function() {
  64.     if (this.timer != null) {
  65.       clearTimeout(this.timer);
  66.       this.timer = null;
  67.     }
  68.   },
  69.  
  70.   /* This function is called from a timer which doesn't
  71.       know about 'this' */
  72.   __execute: function(self) {
  73.     self.beforeExecute();
  74.     self.execute();
  75.     self.afterExecute();
  76.     self.__setTimer();
  77.   }
  78.  
  79. });

Thread Controller

To make my life easier and prevent me from having to declare one variable for every thread I use, I have created a ThreadController object to which every thread created will subscribe. This thread controller will allow us to find threads of a specific class and start/stop them or delete them.

  1. ThreadController = {
  2.   threadCount: 0,
  3.   threads: [],
  4.   add: function(thread) {
  5.     this.threads.push(thread);
  6.     this.threadCount++;
  7.     thread.threadId = 'Thread-' + this.threadCount;
  8.   },
  9.   count: function() {
  10.     return this.threads.length;
  11.   },
  12.   indexOf: function(ClassName) {
  13.     for (var i=0, l=this.threads.length; i<l; i++) {
  14.       if (this.threads[i].ClassName == ClassName) return i;
  15.     };
  16.     return -1;
  17.   },
  18.   remove: function(index) {
  19.     if (index < 0 || index > this.threads.length-1) return;
  20.     var thread = this.threads.splice(index, 1);
  21.     thread[0].stop();
  22.     delete thread[0];
  23.   }
  24. }

Usage

In order to use the Thread class you can do it in two different ways.

First, you can instantiate threads and use the onStart, onStop, onBeforeExecute, onExecute and onAfterExecute events.

  1. var producer = new Thread({
  2.   onExecute: function(thread) {
  3.     // Do something
  4.   }
  5. }).start();

Or, you can create a subclass and override the start, stop, beforeExecute, Execute and afterExecute methods. I like this option better since it let’s you create your own thread based Objects that you can instantiate later. If you use this option do not forget to call this.parent().

  1. var Producer = new Class({
  2.   ClassName: 'Producer',
  3.   Extends: Thread,
  4.   execute: function() {
  5.     this.parent();
  6.     // Do something
  7.   }
  8. });

Producer / Consumer demo

A good example of Javascript threads interacting with each other is the classic Producer/Consumer problem. A Producer object produces goods at some speed. A Consumer object consumes goods at its own speed. Depending of the speed of producers and consumers and the number of each, more or less goods will be available.

  1. var Producer = new Class({
  2.   ClassName: 'Producer',
  3.   Extends: Thread,
  4.   execute: function() {
  5.     this.parent();
  6.  
  7.     var item = new Element('div');
  8.     item.set('text', ++count).addClass('item');
  9.     item.fade('hide').inject($('container'));
  10.     new Fx.Morph(item, {
  11.       onComplete: function() {
  12.         item.addClass('ready');
  13.       }
  14.     }).start({
  15.       opacity: 1
  16.     });
  17.   }
  18. });
  19.  
  20. var Consumer = new Class({
  21.   ClassName: 'Consumer',
  22.   Extends: Thread,
  23.   execute: function() {
  24.     this.parent();
  25.  
  26.     var item = $('container').getFirst('.ready');
  27.     if (item && item.hasClass('ready')) {
  28.       item.removeClass('ready');
  29.       new Fx.Morph(item, {
  30.         onComplete: function() {
  31.           item.destroy();
  32.         }
  33.       }).start({
  34.         opacity: 0
  35.       });
  36.     }
  37.   }
  38. });
  39.  
  40. new Producer().start();
  41. new Consumer().start();
  42. new Consumer().start();
  43. new Consumer().start();
  44. new Consumer().start();

As you can see, creating new producers and consumers is very easy and they will live and run on their own. Check out this Producer/Cosumer demo with Javascript Threads.

Producer / Consumer demo

Thread Synchronization

Now, guess what? The fact that all these threads are not actual threads plays in our advantage. Since two of this objects cannot execute code at the same time, there is no risk of garbaging the value of a variable while changing it at the same time. For example, if two threads are updating the same DOM element, they will never conflict or crash. But you may still need critical sections if two threads are manipulating the same DOM object, for example. You can use temporary classes on the elements, but that doesn’t guarantee no conflicts.

On the Producer/Consumer demo I am using the class “ready” on goods elements to indicate which ones are ready to be consumed and are not being consumed yet. But if you look at the code carefully, would this class prevent two consumers from consuming the same element? Not really. The problem is than between the time a consumer finds a ready element and the time when marks it as not ready, it is possible than a second consumer has found the same element.

Get the code

Latest version:
http://enekoalonso.com/svn/research/classes/thread.js

No responses yet

MooTools classes with “Smart Start”

Dec 10 2008 Published by Eneko Alonso under uncategorized

A couple of days ago I was talking with my friend Karsten at work about one small but relevant issue we face when building websites: our beautiful MooTools classes cannot interact with elements on the DOM until the DOM has fully loaded. This, which is obvious, sometimes has some impact.

For example, the typical case we face is with tabs. Usually you will see code that hides all tab panels but the first one with CSS classes. But what if your visitor has Javascript disabled? With no Javascript, all tabs should be visible. So we need to hide the tabs with Javascript, but now we face the problem: we cannot alter the elements until the DOM is ready. And that is to late for some browsers like IE6 & IE7 which are not very fast processing Javascript. If we hide the tabs on the initialize method of our class, you will see them on the screen for a split of a second. That is not good.

The solution is simple: Use document.write to create the styles needed to hide the tabs as soon as the javascript is processed, this is, before the DOM is loaded. The problem is that we are not creating our classes until the DOM is loaded, so this code has to be placed somewhere else, breaking the encapsulation that object oriented programming gives us.

So we came up with an idea, more or less at the same time: Instantiate our classes with a ‘Smart Start’. This is, our objects will be created before the DOM is ready but will be smart enough to hold the interaction with the elements until that point. This will allow us to do other stuff if we want to, like hiding the tabs other than the first one.

As an example, I have modified this cool CountDown class that David Walsh has just published.

Here is the new code:

  1. var CountDown = new Class({
  2.  
  3.   Implements: [Options,Events],
  4.  
  5.   domReady: false,
  6.   startOnDomReady: false,
  7.   fx: null,
  8.  
  9.   options: {
  10.     element: null,
  11.     start: 10,
  12.     finish: 0,
  13.     startFont: '36px',
  14.     finishFont: '12px',
  15.     onComplete: $$empty,
  16.     duration: 1000
  17.   },
  18.  
  19.   initialize: function(options) {
  20.     this.setOptions(options);
  21.  
  22.     // Smart objects can listen to domready
  23.     window.addEvent('domready',function() {
  24.       this.domReady = true;
  25.       this.options.element = $(this.options.element); // Hook element
  26.       if (this.startOnDomReady) this.start();
  27.     }.bind(this));
  28.   },
  29.  
  30.   start: function() {
  31.     // If DOM is not ready, wait
  32.     if (!this.domReady) {
  33.       this.startOnDomReady = true;
  34.       return;
  35.     }
  36.  
  37.     // Create FX object only once
  38.     this.fx = new Fx.Tween(this.options.element, {
  39.       duration: this.options.duration,
  40.       link: 'ignore',
  41.       onComplete: function() {
  42.         if(this.options.start >= this.options.finish) {
  43.           this.anim();
  44.         } else {
  45.           this.fireEvent('complete');
  46.         }
  47.       }.bind(this)
  48.     });
  49.  
  50.     this.anim();
  51.   },
  52.  
  53.   anim: function() {
  54.     this.options.element.set('text',this.options.start);
  55.     this.fx.start('font-size',this.options.startFont,this.options.finishFont);
  56.   }
  57. });
  58.  
  59. var cd = new CountDown({
  60.   element: 'countdown',
  61.   start: 12,
  62.   finish: 0,
  63.   onComplete: function() {
  64.     this.options.element.set('text','Done! Your special code is: 4065').setStyle('color','#090');
  65.   }
  66. }).start();

As you can see, the object is instantiated as soon as the Javascript is processed but, even with the function start() being called, the object doesn’t start processing until the DOM is ready.

Demo: http://dev.enekoalonso.com/research/moo-countdown-smartstart.php

No responses yet

Very basic $ function to deal with element classes

Dec 04 2008 Published by Eneko Alonso under uncategorized

If you are working with plain Javascript but still want to have some advantajes when dealing with element classes (element.className) you can write a small $ function like this:

  1. var $ = function(element) {
  2.    this.element = element;
  3.    this.getClasses = function() {
  4.      return this.element.className.replace(/\s+/,' ').split(' ');
  5.    }
  6.    this.hasClass = function(className) {
  7.      var classes = this.getClasses();
  8.      return (classes.indexOf(className) > -1);
  9.    }
  10.    this.addClass = function(className) {
  11.      if (!this.hasClass(className)) {
  12.        this.element.className += (this.element.className ? ' ' :'') + className;
  13.      }
  14.    }
  15.    this.removeClass = function(className) {
  16.      if (this.hasClass(className)) {
  17.        var classes = this.getClasses();
  18.        classes.splice(classes.indexOf(className), 1);
  19.        this.element.className = classes.join(' ');
  20.      }
  21.    }
  22.    return this;
  23. }

Then, once you have a variable that contains a DOM element, you can use it like this:

  1.   $(mydomelement).addClass('test');
  2.   if ($(mydomelement).hasClass('test')) alert('element has class test');
  3.   $(mydomelement).removeClass('test');
  4.   var classes = $(mydomelement).getClasses();

This will let you work with elements that have multiple classes very easily.

No responses yet