Roll out your own JavaScript Interfaces
There are times when using a JavaScript library is called for. Building large web applications that use a wide array of utility functions that help aid in developing multi-tiered class systems, advanced UI components, complex event models, and heavy use of DOM scripting helpers. Yep. Those are all great.
However, there are other times when you don’t need all that. And often what we end up doing is just importing a few of our favorite functions as globals, and work off those. But what ends up happening in this case is that we lose the particular style that these libraries offer. For instance, I’d still like to be able to do something like this without a library.
Sample application code
$('foo', 'bar').on('click', function(e) {
$(this).css({
color: 'green',
fontSize: '2em'
}).addClass('active');
});
Starting from scratch
Since we all have a love for the old dollar function introduced by Prototype, we can use that as a base.
Original Prototype $ function
function $() {
var elements = [];
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string')
element = document.getElementById(element);
if (arguments.length == 1)
return element;
elements.push(element);
}
return elements;
}
However, instead of treating this as a normal function, we’ll transform it into a constructor, then assign instance methods. Then of course to achieve chainability, all we have to do is simply return the instance reference. We’ll start off by creating a private interface, then adapt the dollar function to return this private constructor.
Creating the interface
(function() {
// private constructor
function _$(els) {
this.elements = [];
for (var i=0; i<els.length; i++) {
var element = els[i];
if (typeof element == 'string') {
element = document.getElementById(element);
}
this.elements.push(element);
}
return this;
}
_$.prototype = {
each: function(fn) {
for ( var i = 0, len = this.elements.length; i<len; ++i ) {
fn.call(this, this.elements[i]);
}
return this;
},
setStyle: function(prop, val) {
this.each(function(el) {
el.style[prop] = val;
});
return this;
},
addClass: function(className) {
this.each(function(el) {
el.className += ' '+className;
});
return this;
},
on: function(type, fn) {
var listen = function(el) {
if (window.addEventListener) {
el.addEventListener(type, fn, false);
} else if (window.attachEvent) {
el.attachEvent('on'+type, function() {
fn.call(el, window.event);
});
}
};
this.each(function(el) {
listen(el);
});
return this;
},
css: function(o) {
var that = this;
this.each(function(el) {
for (var prop in o) {
console.log(prop);
that.setStyle(prop, o[prop]);
}
});
return this;
}
};
window.$ = function() {
return new _$(arguments);
}
})();
Short and concise! Check out an implementation of this code in action to see how easy it is to start rolling out your own personal interfaces. Cheers.




October 3rd, 2007 at 7:39 pm
You make it look so easy!
October 4th, 2007 at 12:10 am
[...] Roll out your own JavaScript Interfaces [...]
October 4th, 2007 at 12:20 am
I love the console.log(prop) is still in your code. Maybe one should generically implement the console object in this sort of interface ;)
October 4th, 2007 at 12:30 am
@Jon: Because it always has been this easy :)
@Felix: Haha. Good catch, I’m going to leave it in for good measure. It was obviously accidentally left in from when I was debugging the code and making sure everything worked before I posted it. I would usually add in something of this nature to help fix that problem:
October 4th, 2007 at 2:39 am
Way over my head, as usual :)
But that’s my loss. I mean, I get functions, you know function name() {} but when you start wrapping stuff in parenthesizes (function() {})(); I’m lost. ;)
I’ll catch up some day, or maybe switch to being a Project Manager instead, let someone else worry about those things.
It look good though, and works, so great job.
October 4th, 2007 at 4:11 am
Mats: It’s a way of providing scope so as to not pollute the global scope with your variables, and is often referred to as the module pattern.
October 4th, 2007 at 4:55 am
Very nice work!
In the _$(els) function for statement, should els.length be arguments.length instead?
October 4th, 2007 at 5:01 am
Ah … nevermind. I just saw the part where window.$ is setup, in which arguments is passed into the _$ function.
I’ll go try some coffee now :)
October 4th, 2007 at 7:29 am
[...] Ð’ този поÑтинг на ДъÑтин Диаз е опиÑано накратко, как да започнем наша Ñи ÑобÑтвена библиотека, в коÑто да Ñ Ð¸Ð¼Ð° прочутата, магичеÑка Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ $. [...]
October 4th, 2007 at 7:32 am
@ mats
hi
the (function() {} )(); is very easy
i learnd it myself yesterday:D befor that, i was lost like you
but it is very easy
the 1. bracket calles the function at runtime
that means that you don’t need to call it on beginning because it is called by itself
and when you need it later you can then call it….
hope this is correct :)
if not, sorry, but thats that, what i understood
daniel
October 4th, 2007 at 1:19 pm
[...] Roll out your own JavaScript Interfaces How to implement your own $() (tags: javascript object-oriented oo prototype technique) [...]
October 4th, 2007 at 2:19 pm
ok i was false
it is just called at “runtime”
October 5th, 2007 at 8:09 am
A simple and compact implementation of the jQuery, and more accurate, the version 1.2 the same function wrapper and same method name, great, Cheers, I believe you must like the jQuery very much, and too long no see your podcast, episode 16 is great.
October 5th, 2007 at 11:33 am
if i would now like to “reset” the change on an second click, what would i need to do?
October 5th, 2007 at 7:39 pm
[...] Roll out your own JavaScript Interfaces: This is an article I was thrilled to see. Figuring this out was a TODO in the back of mind. Thankfully Dustin explained it concisely, eloquently and thoroughly. [...]
October 7th, 2007 at 1:08 am
you don`t need a closure and _$ to make this.
you can also do a check if this equal to window and if it is create a instance like this:
this technique is used in jQuery so you can use $ instead of new $ or new jQuery every time.
October 7th, 2007 at 12:07 pm
@Uriel, this technique is ‘not’ used in jQuery. Try testing your code ;) That won’t work. You can’t instantiate something you’re applying. As a matter of fact, jQuery is specifically doing this:
October 8th, 2007 at 10:22 am
my bad,this works:
this one is tested :)
what i meant that jQuery use a check to see if jQuery was called without new and if it is it call it self with new.
October 8th, 2007 at 12:07 pm
@mats:
1: foo = function(){}; foo(); // calls foo
2: foo = function(){}; (foo)(); // calls foo
3: ( function(){} )(); // calls the anonymous function
@Dustin: Check your implementation of .css() and .setStyle(). One loop too many?
October 8th, 2007 at 2:20 pm
The “return this;” in the constructor isn’t required. An object is automatically returned when the “new” keyword is used with a function (you can use a return statement in a constructor to override this behavior and pass back an object other than “this”).
October 8th, 2007 at 2:29 pm
[...] Roll out your own JavaScript Interfaces [...]
October 8th, 2007 at 2:35 pm
[...] Dustin Diaz is on a roll :) He has posted about Roll out your own JavaScript Interfaces in which he discusses the desire to use style from libraries such as prototype, jquery and friends, yet in a small bit of code where you don’t want to use the library: There are times when using a JavaScript library is called for. Building large web applications that use a wide array of utility functions that help aid in developing multi-tiered class systems, advanced UI components, complex event models, and heavy use of DOM scripting helpers. Yep. Those are all great. However, there are other times when you don’t need all that. And often what we end up doing is just importing a few of our favorite functions as globals, and work off those. But what ends up happening in this case is that we lose the particular style that these libraries offer. For instance, I’d still like to be able to do something like this without a library. [...]
October 8th, 2007 at 3:36 pm
What are your thoughts on Mootools implementation of the dollar function? It has a bit more bulk to it that all your suggestions, but I am a big fan of Mootools due to its wide array of features; even if many of them are borrowed from prototype etc. I still don’t think anything comes close to its effects engine and I find code produced using Mootools is generally much smaller than other frameworks. Take for example slimbox, which is almost 10 times smaller than the orignal LightBox.
October 8th, 2007 at 4:52 pm
@Michael Geary: Yeah, I see that. One too many loops for sure as that can be optimized.
@Ross: I definitely missed and had a near “no duh” moment realizing what you just said. Of course returning that isn’t required, it must have skipped my mind considering that we came up with a new function not too long ago, it should have been obvious.
October 8th, 2007 at 5:57 pm
[...] Roll out your own JavaScript Interfaces (tags: javascript programming interface library webdev howto design jquery **) [...]
October 8th, 2007 at 10:17 pm
[...] Roll out your own JavaScript Interfaces jquery in 30 lines. (almost, but a very good introduction to creating chanable methods. (tags: jquery javascript interface library howto) Posted by Richard@Home Filed in 15 [...]
October 8th, 2007 at 10:28 pm
[...] Dustin Diaz is on a roll He has posted about Roll out your own JavaScript Interfaces in which he discusses the desire to use style from libraries such as prototype, jquery and friends, yet in a small bit of code where you don’t want to use the library: There are times when using a JavaScript library is called for. Building large web applications that use a wide array of utility functions that help aid in developing multi-tiered class systems, advanced UI components, complex event models, and heavy use of DOM scripting helpers. Yep. Those are all great. However, there are other times when you don’t need all that. And often what we end up doing is just importing a few of our favorite functions as globals, and work off those. But what ends up happening in this case is that we lose the particular style that these libraries offer. For instance, I’d still like to be able to do something like this without a library. [...]
October 9th, 2007 at 8:00 am
Dustin, I tried your procedure for leftover console.* statements:
window.console = console || {
log: function() { },
info: function() { },
debug: function() { }
};
It still gives error, so I made it into:
window.console = (typeof console == ‘undefined’) ? {
log: function() { },
info: function() { },
debug: function() { }
} : console;
Which does not give errors.
October 10th, 2007 at 1:05 am
An easier way to do that is:
October 10th, 2007 at 2:18 am
[...] Roll out your own JavaScript Interfaces very nice example of a basic modern dom library (tags: code design webdev interface howto) [...]
October 10th, 2007 at 8:19 am
well (postable didn’t work) in short:
October 12th, 2007 at 12:29 am
[...] Roll out your own JavaScript Interfaces — как напиÑать мини-jQuery [...]
October 28th, 2007 at 10:45 am
[...] Roll out your own JavaScript Interfaces [...]
November 3rd, 2007 at 12:55 pm
Very, very nice and a refreshing take on creating libraries, thank you very much.
However, I would like to have my libraries a little more structured, nested functions come to mind. I tried this:
Within setStyle(), I haven’t discovered a way how to reach the scope the each() function lies. Can anyone point me in the right direction?
December 7th, 2007 at 7:04 am
[...] while back Dustin Diaz did a nice explainer on pieces needed for your own personal JavaScript and AJAX interface — [...]
December 7th, 2007 at 7:46 am
I’m late to the party on this one but was curious how to get this to return false when clicking a link. In the sample code, a div is being clicked but if $(’sample1′, ’sample2′) referred to links and they had actual URLs for graceful degradation instead of just ‘#’ as their href value it would cause the browser to go to that page.
How do you resolve that?
February 3rd, 2008 at 3:28 pm
I have only just got used to moo tools and thanks for writing this tutorial, i have found it most useful.
I have been finding javascript so ‘raw’, even such a thing as if($type . .. what a god send !
March 7th, 2008 at 12:34 pm
I have to say I’m lost too :d but it’s good this thing works.
I’ll have to take a better look and see what I’m missing. Argh…javascript…it’s kind of a must.Not knowing javascript won’t do much good in the future..:(
April 13th, 2008 at 2:00 am
This is great. How would you support inheritance and private/public functions with this approach?
May 21st, 2008 at 9:57 am
I must admit, i only know the basics of javascripts. To send forms and assist with flash ect. Howevever i would like to see in a few years time more understanding of this. Are there any books etc anyone can recommend for this?
Thanks
Claire
August 13th, 2008 at 7:32 am
Hey Dustin,
Is the technique you’re using here have anything to do with Cascades? Some recent reading has lead me to believe the returning of this to allow chainability is also known as Cascades but I’m not sure.
Thanks,
Jason