Since version 1.0.9, Mooml includes a new feature: globalize. It maybe handy for some websites to globalize all the Mooml template functions (div, a, p, span…) to the window object scope, so they can be used anywhere in the code without the need of defining or evaluating a template.
For example, in normal Mootools code we would create a div like this:
-
// options can have attributes, css, events and more
-
var mydiv = new Element('div', options);
With Mooml.globalize() we can do this:
-
Mooml.globalize(); // Only need to call this once
-
var mydiv = div(options); // Same options as Mootools new Element()
Mooml globalized functions can also have nested elements, which makes very easy to create dom elements:
-
var mydiv = div(options,
-
p('First paragraph'),
-
p('Second paragraph'),
-
div('Nested div:',
-
span('div content')
-
),
-
Mooml.render('nested_template'),
-
'Some <b>inline</b> <em>html</em> too'
-
);
Will generate the dom elements for this html:
-
<div>
-
<p>First paragraph</p>
-
<p>Second paragraph</p>
-
<div>Nested div:
-
<span>div content</span>
-
</div>
-
<!– nested template here –>
-
Some <b>inline</b> <em>html</em> too
-
</div>
Elements created by Mooml template functions are not automatically injected in the DOM. They are just created like when you use new Element().
Please be aware that using Mooml.globalize() feature will pollute the window object scope, overriding any methods with the same name and/or possibly conflicting with other Javascript libraries. As a tip, Mooml.tags can be edited before calling Mooml.globalize(), so only functions for those tags we are interested on will be created.
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:
-
function hello() {
-
alert("hello");
-
}
-
// Will execute hello() after 10 seconds
-
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:
-
var MyClass = new Class({
-
initialize: function() {
-
setTimeout(function() { this.hello(); }, 10000); // This wont work
-
},
-
hello: function() {
-
alert("hello");
-
}
-
});
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:
-
var MyClass = new Class({
-
initialize: function() {
-
setTimeout(function() { this.hello(); }.bind(this), 10000);
-
},
-
hello: function() {
-
alert("hello");
-
}
-
});
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.
-
var MyClass = new Class({
-
initialize: function() {
-
this.text = 'hello';
-
setTimeout(function() { this.hello(); }.bind(this), 10000);
-
},
-
hello: function() {
-
alert(this.text); // This wont work
-
}
-
});
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.
-
var MyClass = new Class({
-
initialize: function() {
-
this.text = 'hello';
-
setTimeout(function() { this.hello.call(this); }.bind(this), 10000);
-
},
-
hello: function() {
-
alert(this.text);
-
}
-
});
Now we can use this inside the hello() function and everything will work fine, no matter how many instances of MyClass we create.
-
var MyClass = new Class({
-
initialize: function(text) {
-
this.text = text;
-
setTimeout(function() { this.hello.call(this); }.bind(this), 10000);
-
},
-
hello: function() {
-
alert(this.text);
-
}
-
});
-
new MyClass('hello');
-
new MyClass('hi there!');
-
new MyClass('wassup?');
Enjoy :)