Mootools has been rearranged a bit since version 1.0. Code written for Mootools 1.0 should work with 1.1 for the most part, but the code itself is broken up differently into different files.
Core.js is a good example, as it represents the first file in the library on which all others depend. In 1.0 this "Core" file was Moo.js and its main contribution was the Class object. Now Class is in its own file (see Class) and Core.js instead contains a handful of utilities that are used throughout Mootools.
New to Mootools is a namespace which contains a version number. This namespace isn't used for much else, but it's useful if you need to query the page to see what version of Mootools is in the environment:
var MooTools = { 'version': 1.1 };
$defined quite simply returns true if the argument passed to it is not undefined or null:
var x = null; console.log($defined(x)); /* false */ function example(value){ console.log($defined(value)); } example(); /* logs false; no argument passed */

Javascript is a loosely typed language and this often causes a lot of grief for those that work with it. Mootools' $type function helps by letting you figure out what something is. $type returns the type of an object ('function' or 'string', etc.) or false if the object is not defined:
This example uses the $() function; see Native>Element>$().
$type($('typeTest'))//element if $('typeTest') exists, //otherwise boolean, because $() returns false if the element isn't found. //this example returns true

$type($('elementNotPresent')); //returns boolean, because $() returns false here

<div id="typeElement" style="display: none"> this is a text node <span> </span> </div>
console.log($type($('typeElement').childNodes[0]));// "textnode" console.log($type($('typeElement').getElement('span').childNodes[0]));// "whitespace"

function test(){ console.log($type(arguments)); } test('one','two'); /* logs "arguments" */ test(); /* also logs "arguments" */

$type({});//"object"

$type('hi'); //"string"

$type(''); //"string"

$type(0); // "number"

$type(true); // "boolean"

$type(false); // "boolean"

$type(function(){});//"function"

$type([]);//"array"

$type(new Class());// "class"

$type(document.getElementsByTagName('p'));// "collection"

$type(/([.*])/); //"regexp"

var x = null; $type(x);// false

$type(); // false

One of the basic concepts in Mootools is reusability. The ability to inherit properties from one object to another or merge the properties of two objects is at the heart of what Mootools does. $merge and $extend (known as Object.extend in Mootools 1.0) both allow you to combine the properties of two javascript objects offering up numerous opportunities for clean and reusable code.
These two code blocks do the same thing EXCEPT that $merge does not alter any of the items passed to it (returning the result instead) while $extend changes the first argument to now include the values of the second.
var fruits = { apple: 'red', lemon: 'yellow' }; var otherFruits = { apple: 'green', grape: 'purple' }; $extend(fruits, otherFruits); /* fruits has been altered by $extend */ console.log(fruits); /* logs: {apple:'green', lemon: 'yellow', grape: 'purple'} */

In the example above we see the two objects merged, and because otherFruits was passed in later than fruits it's values trumped those found in the fruits object (so apple came out "green" instead of "red"). Here is $merge doing the same thing, but note that fruits is unaltered and to receive the result of the operation we must set it to something use =.
var fruits = { apple: 'red', lemon: 'yellow' }; var otherFruits = { apple: 'green', grape: 'purple' }; var newFruits = $merge(fruits, otherFruits); console.log('newFruits: ', newFruits); /* fruits has NOT been altered by $merge */ console.log('unaltered fruits: ', fruits); /* logs: {apple:'red', lemon: 'yellow'} */ fruits = $merge(fruits, otherFruits); /* fruits HAS been altered by setting the result using = */ console.log('fruits altered: ', fruits); /* logs: {apple:'green', lemon: 'yellow', grape: 'purple'} */

Note: that $extend, like $merge, returns the result of the operation, but it also alters the first argument.
//continued from above var newFruits = $extend(fruits, otherFruits); //newFruits == fruits; they are the same object
Unlike $extend, $merge can take any number of arguments and the first argument will get the properties of the others.
var fruits = { apple: 'red', lemon: 'yellow' }; var otherFruits = { apple: 'green', grape: 'purple' }; var yetMoreFruits = { apple: 'yellow', orange: 'orange' }; var newFruits = $merge(fruits, otherFruits, yetMoreFruits); console.dir(newFruits); /* logs: {apple:'yellow', lemon: 'yellow', grape: 'purple', orange: 'orange'} */

The value of apple in yetMoreFruits is preserved because it was the last passed in.
It's important to note that $merge is recursive. Unlike $extend, which just takes the members of the second argument and adds them to the first argument, $merge will do the same except when one of the members is another object. In this case it will recurse into that object and copy its values into the result.
This is important, because in javascript if you ever type var object = someOtherObject you are not creating a copy of that object but merely another pointer to it:
var x = {one: 1}; var y = x; console.dir(x == y); /* true */ x.two = 2; /* changing x also changes y */ console.dir(y.two); /* 2 */

But two objects with the same properties are NOT == to each other:
var x = {one: 1}; var y = {one: 1}; console.dir(x == y); /* false */ x.two = 2; /* changing x does not change y */ console.dir(y.two); /* undefined */

If you use $extend to merge two objects together and the second object contains members that are also objects, you will create a prototypical link between the two:
var fruits = { apple: 'red', lemon: 'yellow' }; var detailedFruits = { apple: { goldenDelicious: 'yellow', pinkLady: 'red', sour:'green' } }; $extend(fruits, detailedFruits); console.dir(fruits); /* logs {apple:{goldenDelicious:'yellow', pinkLady:'red', sour: 'green'}, lemon: 'yellow'} */ /* changing apple in one changes it in both */ detailedFruits.apple.pinkLady = 'pink'; console.dir(fruits); /* logs {apple:{goldenDelicious:'yellow', pinkLady:'pink', sour: 'green'}, lemon: 'yellow'} */

The link between fruits and detailedFruits shouldn't exist, but it does because apple is an object.
$merge, though, will recurse into detailedFruits.apple copying the values of each of its members so that this link does not exist.
var fruits = { apple: 'red', lemon: 'yellow' }; var detailedFruits = { apple: { goldenDelicious: 'yellow', pinkLady: 'red', sour:'green' } }; fruits = $merge(fruits, detailedFruits); console.dir(fruits); /* logs {apple:{goldenDelicious:'yellow', pinkLady:'red', sour: 'green'}, lemon: 'yellow'} */ /* now changes to one object do not affect the other */ detailedFruits.apple.pinkLady = 'pink'; console.dir(fruits); /* logs {apple:{goldenDelicious:'yellow', pinkLady:'red', sour: 'green'}, lemon: 'yellow'} */

Most of the time you won't use $extend. It's used within Mootools for certain types of inheritance, specifically with Class.extend, but when you are working with your code to implement options or manage data, its generally safer to use $merge unless you are positive that the objects do not contain members that are also objects.
Because $merge can take any number of objects and because it does not alter them, $merge also provides a safe way to copy objects:
var x = {one: 1}; var y = x; console.dir(x == y); /* true */ var z = $merge(x); console.dir(x == z); /* false */

Here y and x are the same entity while z has the same values as x, but is a copy of it.
Will add a .extend method to the objects passed as a parameter, but the property passed in will be copied to the object's prototype only if not previously existent. It's handy if you don't want the .extend method of an object to overwrite existing methods. This is used automatically in Mootools to implement Array/String/Function/Number methods to browsers that don't support them without having to manually check that the property doesn't already exist.
You won't find much use, if any, for $native in your own code, but you can use .extend on the native elements to add your own functionality to them:
String.extend({ alert: function(){ alert(this); } }); "hi there".alert(); /* alerts "hi there" */

The Abstract class adds the .extend method to an object. Note that if you later use the for(keys in object) method to loop over this your iteration will return the extend member, too.
var fruits = new Abstract({ apple: 'red' }); fruits.extend({ lemon: 'yellow' }); console.log(fruits); //logs {apple: 'red', lemon: 'yellow', extend: function(){...}}

Mootools applies Abstract to the window and the document for you and defines a new property called document.head:
var Window = new Abstract(window); var Document = new Abstract(document); document.head = document.getElementsByTagName('head')[0];
A common practice in javascript is to use the native javascript object to keep your code out of the global namespace. If you create a function called show() it's very likely that this is going to get overwritten by someone else who decides to use a generic name like that in their own code. If they both get added to the same page, one overwrites the other.
This often leads to functions with names like showThisThingOnMyPage() which is ugly and hard to remember. So instead of creating show() in the global namespace, we can create functionality as members of an object:
var City = { numberOfBuildings: 0, //some default value hasTraffic: true, grow: function(howMany){ this.numberOfBuildings += howMany; } };
Now we can reference City.grow() to increment how many buildings there are in the City. This has numerous advantages. For starters, we can use names that are easy to remember, instead of a function that looks like this:
var City = { numberOfBuildings: 0, hasTraffic: true }; function growCity(city, howMany){ city.numberOfBuildings += howMany; };
Our version is more simple (City.grow()). Another advantage of working with object namespaces is that the whole object gets evaluated at once. Instead of code that declares a bunch of variables then a bunch of functions and then puts them together, we can refer to this.value within the object's functions and we don't have to worry about whether or not that member (value) has been defined previously:
var City = { hasTraffic: true, getBuildings: function(){ return this.numberOfBuildings || 0; }, grow: function(howMany){ this.numberOfBuildings = this.getBuildings() + howMany; } };
In this example above, I didn't define numberOfBuildings before I started but instead only when I needed it. Here it didn't really save me any time, but in general, object namespaces allow you to define values of the object at any time and even refer to members that may not be there yet (such as return this.numberOfBuildings || 0, so that if numberOfBuildings isn't defined, it doesn't matter).
It's important to note that an object like this is treated as a single line of javascript. The whole object is parsed at the last };, which means that the order of all the members doesn't matter. Unlike writing things in the global namespace, where you can't refer to functions or variables that aren't yet defined, here these things aren't looked for until that last };.
Mootools has a very powerful inheritance model (see: Class) and 99% of the time you should use this to create reusable functionality, but sometimes it's not the perfect solution for what you're trying to do. There's an alternate method (other than the Class object) for reusing namespaces like this by using $merge:
var City = { hasTraffic: true, getBuildings: function(){ return this.numberOfBuildings || 0; }, grow: function(howMany){ this.numberOfBuildings = this.getBuildings() += howMany; } }; var SanFrancisco = { hasFog: true, numberOfBuildings: 1000, earthquake: function() { this.numberOfBuildings = this.numberOfBuildings/2; } }; $merge(SanFrancisco, City); //now SF has the props of City SanFrancisco.earthquake.apply(SanFrancisco); //hope you have insurance! //see note below regarding .apply()
Again, when we get to the section on Class you'll see that they are much more powerful, but not every collection of functionality is useful as a Class and this is a way to still reuse your code with namespaced objects.
Note in the example above I call SanFrancisco.earthquake.apply(). The reason why is because the earthquake function refers to this which we need to point to SanFrancisco, but instead will refer to the window (because that is the scope when we call it). I'm not going to explain this further here, because we're getting ahead of ourselves, but in order for this to work we need to use 03-native#function.bind|bind or apply. I don't want to get ahead of ourselves here, so just take my word for it and read on; all will become clear...
$chk returns true if the passed in value/object exists (is not undefined or null) or is 0, otherwise returns false. Note that $chk will return false for empty strings (but not for empty arrays or objects).
$chk([]); //true

$chk(0); //true

$chk(''); //false

$chk(null); //false

$chk(false); //false

It's similar to $defined but, unlike defined which ONLY checks for undefined and null, $chk actually evaluates the property unless it is zero (in which case it returns true).
$defined(''); //true

$defined(false); //true

$pick returns the first object if defined (it uses $defined), otherwise returns the second.
Pick is just a shortcut for an if/else statement. It takes two variables and returns the first if it is defined or not null, otherwise it returns the second argument. This means you can call $pick(false, defaultVal) and $pick will return false, because it's defined.
function test(variable){ alert($pick(variable, 'no variable defined!')); } test(); /* alerts 'no variable defined!' */ test('hi'); /* alerts 'hi' */ test(false); /* alerts 'false' */ test(''); /* alerts '' */

If you were to write this function above out without $pick, it'd look like this:
function test(variable){ if(typeof variable == "undefined" || variable == null) alert('no variable defined'); else alert(variable); }
What's important to note here is that zero, an empty string, and false when passed to $pick will return that value. If you were to evaluate the variable itself: if(variable) alert(variable) - your conditional would evaluate those values (zero, "", the boolean false) and alert that no variable was defined.
It saves you the time of writing out a long if statement. But it gets even more useful when you need to nest things:
function test(variable) { variable = $pick(variable, $pick(someOtherVariable, defaultValue)); } //typing this out with if/else statements would look like: function test(variable){ if(typeof variable == "undefined" || variable == null){ if(typeof someOtherValue != "undefined" && someOtherValue != null) variable = someOtherValue; else variable = defaultValue; } return variable; }
Returns a random number between the minimum and maximum you pass in:
$random(0,9); //returns a random number between 0 and 9

A shortcut for new Date.getTime();.
$time(); //the current time value

$clear clears the passed in timeout:
var oneSec = setTimeout(function(){alert('one second later...')}, 1000); $clear(oneSec); //nevermind

Utilities.js also includes a few browser detection variables added to the window object.
*window.ie - will be set to true if the current browser is internet explorer (any).
mootorial/01-core.txt · Last modified: 2008/04/14 14:52 by jimomighty