Monday, October 8th, 2007
$: Now with more magic!
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.
Dustin would like to write something like this:
-
-
$('foo', 'bar').on('click', function(e) {
-
$(this).css({
-
color: 'green',
-
fontSize: '2em'
-
}).addClass('active');
-
});
-
And to implement the magic he takes Prototypes $() and makes it a special object that can do much more:
-
-
(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);
-
}
-
})();
-
You can see a demonstration at work.












Basically, Dustin is reinventing jQuery =P
I wholeheartedly agree though and am currently in a similar process of thought. jQuery can be a whole lot less bulky (and it’s small to begin with) and it seems they’re headed towards the same mentality as well.
ps. I’m not on the pro-jQuery bandwagon, we use prototype ourselves as well at my company…
jQuery in 54 lines ;)
Amazing!
Neat stuff. Maybe some simplified version of Prototype’s Ajax object and it’ll be all I need. Also, can someone explain to me what the parentheses around the function do? Like
(function (){
...
})();
Is this another way to create objects? Thanks in advance for any help.
Is that console.log in the css function left in there on purpose?
it is a function that call itself,the reason to do this is to keep the global namespace clean so the _$ is local to the function but the $ function is exposed because it is append to the global namespace(i.e. window).
To be fair, this isn’t “all” of jQuery in 54 lines. It was just a couple of the core functions. And by no means is it a replacement, or a released js library - this was just a sample implementation of a couple functions that has a cool chainable interface :)
Sorry, but what is the point with that? You can do that with mootools core functions and elements extensions…
$$(’#foo’, ‘#bar’).addEvent(’click’, function(){
this.setStyles({
‘color’: ‘green’,
‘fontSize’: ‘2em’
}).addClass(’active’);
});
it is neither news, nor it is something special, so what is the point?
Nice work Dustin.
@Chris: “There are times when using a JavaScript library is called for…” i read this somewhere.
That is why mootools is modular
In prototype you can do:
$('mydiv').innerHTML = "Hello everybody";The code above does not allow you to do that… :p
Holy shit! Its a f**king example, its not a JS library to replace jQuery or Prototype. It is simply showing you how the core of jQuery is built