From ebb31e4ef4c1ac336d805ea4f8fd44d8a85ffa8a Mon Sep 17 00:00:00 2001
From: Ivan Ivanov
+ Most people getting started with JavaScript these days are faced with the challenging task of picking a library to use, or at least which one to learn first. If you're working for a company chances are they have already chosen a framework for you, in which case the point is somewhat moot. If this is the case and they've chosen MooTools and you're used to jQuery, then this article might still be of some use to you.
+
+ Every day on twitter I see numerous posts that boil down to "MooTools or jQuery?" This article aims to help you make that choice.
+
+ I am a MooTools developer. I work on the MooTools framework. I blog about MooTools. I wrote the main online tutorial and the book about MooTools. Obviously, I have a perspective that is somewhat biased. I'll also point out that I don't use jQuery that often. If you're a jQuery developer and see anything that I have misrepresented here, please contact me and help me rectify the issue. My objective here is to be helpful and accurate to people - not to sell one framework over another.
+
+ Helping you make a choice between these two frameworks involves me telling you how they are different. I'll start out by saying that both of them are excellent choices. You can't make a wrong choice here. Both frameworks have their strengths and weaknesses, but, in general, they are both great choices. There are other frameworks out there that are worth digging into as well. Dojo, Prototype, YUI, Ext and others are all great choices. Which one you choose really has more to do with your own style and what you need to accomplish. The purpose of this article is to focus on MooTools and jQuery, as increasingly these are the two frameworks that I see a lot of people considering. Finally, I'm not trying to convince anyone to switch from one framework to the other. There are interesting things about both frameworks from which you can learn. You can read a little more about this article and why I wrote it in my blog post on Clientcide where I announced it.
+
+ Information based on data from jquery.com, mootools.net, and wikipedia.com.
+
+ If you go to the jQuery site, here's what it says at the top of the page:
+
+ ...and if you go to MooTools, this is what you'll find:
+
+ I think this really sums it up. If you ask me (and you're reading this, so I'll assume you just have), the question isn't about which framework is better or worse. It's which one of these things above do you want to do? These two frameworks just aren't trying to do the same things. They overlap in the functionality they provide, but they are not trying to do the same things.
+
+ jQuery's description of itself talks about HTML, events, animations, Ajax, and web development. MooTools talks about object oriented-ness and writing powerful and flexible code. jQuery aspires to "change the way you write JavaScript" while MooTools is designed for the intermediate to advanced JavaScript developer.
+
+ Part of this consideration is the notion of a framework vs a toolkit. MooTools is a framework that attempts to implement JavaScript as it should be (according to MooTools' authors). The aim is to implement an API that feels like JavaScript and enhances everything; not just the DOM. jQuery is a toolkit that gives you an easy to use collection of methods in a self-contained system designed to make the DOM itself more pleasant. It just so happens that the DOM is where most people focus their effort when writing JavaScript, so in many cases, jQuery is all you need.
+
+ Most of the code you write when you write MooTools still feels like JavaScript. If you aren't interested in JavaScript as a language, then learning MooTools is going to feel like a chore. If you are interested in JavaScript and what makes it interesting, powerful, and expressive, then, personally, I think MooTools is the better choice.
+
+ First, jQuery is, by and large, easier to learn. It has an almost colloquial style that almost doesn't feel like programming. If all you want is to get something working quickly without learning JavaScript, jQuery is probably a better choice for you. It's not that MooTools can't help you accomplish the same things, but I'll admit that MooTools can be a little harder to get the hang of if you're new to JavaScript and also that there are just a lot of resources out there to help you learn jQuery - more than there are for MooTools at least.
+
+ If you compare the jQuery community (see the "Discussion" page on jQuery) and the MooTools community (irc, mailing list, and unofficial forum) you'll quickly discover two things: 1) the jQuery community is far larger (I attribute this mostly to the point I made above about how easy it is to learn, but also because...) and 2) they are more active in promoting the library. If you measure jQuery and MooTools on metrics like the number of people using it, the number of search queries run on Google, the number of books sold, etc, you'll see jQuery is ahead by a wide margin.
+
+ To tell you why you might consider MooTools I'll first need to talk a little bit about what both the frameworks do. Ultimately which framework you choose is going to come down to what you want to accomplish and how you like to program (and maybe even if you like to program, at least in JavaScript).
+
+ Part of making this choice is asking what you want to do with JavaScript. Let's consider vanilla JavaScript. No framework; just plain old JS. JavaScript gives you native objects like Strings, Numbers, Functions, Arrays, Dates, Regular Expressions, and more. JavaScript also gives you an inheritance model - a somewhat esoteric model called prototypal inheritance (which I'll talk about more later). These building blocks and the concept of inheritance are the bread and butter of any programming language and they have absolutely nothing to do with browsers or the web or CSS or HTML. You could write anything you wanted to in JavaScript. Tic-tac-toe, chess, photoediting, a web server, whatever. It just so happens that 99% of all the JavaScript out there is run in browsers and that's what we think of it as. The programming language for browsers.
+
+ Understanding that the browser, the DOM, is just where we happen to use JS most of the time but that it's actually a very robust and expressive programming language will help you understand the difference between MooTools and jQuery.
+
+ If you think of the tasks that we want to accomplish in JavaScript strictly in terms of "get stuff on the page and do stuff to it" then jQuery is probably the best choice. It excels at offering a very expressive system for describing behavior on the page in a way that doesn't feel like programming sometimes. You can still use the rest of JavaScript to do what you want to do, but if you're focused on the DOM - changing CSS properties, animating things, fetching content via AJAX, etc - most of what you'll end up writing will be covered by jQuery, and what isn't will likely be plain-old JavaScript. jQuery does provide some methods that aren't about the DOM; for example, it provides a mechanism for iterating over arrays - $.each(array, fn) - or, for example, it offers a trim method for strings - $.trim(str). But there aren't a ton of these types of utility methods, which is fine because, for the most part, if you're just getting stuff out of the DOM, iterating over them, and altering them in some way (adding html, changing styles, adding event listeners for click and mouseover, etc) you don't need much else.
+
+ But if you think of JavaScript's scope in its full breadth, you can see that jQuery doesn't focus on things outside of the DOM. This is one of the reasons it is so easy to learn, but it also limits the ways it can help you write JavaScript. It's just not trying to be anything other than a solid programming system for the DOM. It doesn't address inheritance nor does it address the basic utilities of all the native types in the JavaScript language, but it doesn't need to. If you want to mess around with strings, dates, regular expressions, arrays and functions, you can. It's just not jQuery's job to help you do it. JavaScript as a language is there at your feet. jQuery makes the DOM your playground, but the rest of JavaScript is just not in its scope.
+
+ This is where MooTools is vastly different. Rather than focusing exclusively on the DOM (though, as I'll get into in a bit, it offers all the functionality that jQuery does but accomplishes this in a very different manner), MooTools takes into its scope the entire language. If jQuery makes the DOM your playground, MooTools aims to make JavaScript your playground, and this is one of the reasons why it's harder to learn.
+
+ The JavaScript programming language has some really awesome things about it. For starters, it's a functional language, which means that it treats functions as high-order objects that can be passed around as variables just like any other object - strings or numbers for example. It's designed with this concept in mind and many of the methods and patterns in it work best when you write code this way. It's the difference between:
+
+ and
+
+ JavaScript has an inheritance model that is not quite unique but at least rather rare in programming languages. Instead of classes that are defined that can be subclassed it passes along traits through prototypal inheritance. This means that objects inherit directly from other objects. If you reference a property on an object that inherits from another object, the language inspects the child object for that property and, if it doesn't find it, looks for it on the parent. This is how a method on, say, an array works. When you type:
+
+ the method "forEach" is not a property of the array you declare ([1,2,3]), it is a property of the prototype for all Arrays. When you reference this method the language looks for a method called forEach on your array, and, not finding it, then looks at the prototype for all arrays. This means that the forEach method is not in memory once for every array in memory; it is only in memory for the prototype of arrays. This is incredibly efficient and ultimately quite powerful. (Side note: MooTools aliases the forEach method as each)
+
+ Javascript has a special word: "this". It's hard for me to succinctly define what "this" is all about but, by default, "this" is the object to which the current method belongs. It allows objects to refer to themselves within their methods as they would otherwise have no means to do so. This becomes important when you create children objects and have numerous instances of that object; how else could the method of an object refer to itself? When the actual copy of the method exists on the parent, not the child, the "this" keyword allows these instances to refer to their own state. (here's a much more complete description of the "this" keyword, and another from Mozilla.)
+
+ The "this" keyword allows objects that inherit from other objects to refer to themselves, but there are times when you may want to reference something else through "this". This is called binding, wherein you specify a different "this" for a method. The "each" method on Array allows you to specify the bound object with a second argument. Here's an example of where you might want to pass in a different "this":
+
+ In the example above, we bind ninja (which is "this" inside the logInventory method) to the method we pass to the array so that we can refer to the log property of ninja. If we didn't do this, "this" would be window.
+
+ These are just some examples of the power and expressiveness that JavaScript has to offer - inheritance, self reference and binding, and efficient prototype properties. The bad news is that vanilla JavaScript doesn't make these powerful things very useful or accessible, and this is where MooTools starts. It makes these types of patterns easy and rather pleasant to use. You end up writing more abstract code, and in the long run, this is a good thing - a powerful thing. Learning how these patterns are valuable and how to use them properly takes effort, but the up side is that the code you author is both highly reusable and much easier to maintain. I'll talk about these two things a bit more in a minute.
+
+ Because MooTools focuses on making the JavaScript API itself more stable and coherent, it is focused less on giving you an interface that "changes the way you write JavaScript" and more on making JavaScript as a whole less frustrating; MooTools is an extension to the JavaScript language. MooTools tries to make JavaScript the way it is meant to be. A significant portion of the core library is spent on augmenting Function, String, Array, Number, Element and other prototypes. The other big thing it offers is a function called Class.
+
+ Now, Class looks to many people like it's trying to recreate a more classical inheritance model that one might find in Java or C++, but that's not the case. What Class does is make the prototypal inheritance model of JavaScript easier for you and me to access and take advantage of. I'll note that these concepts are not unique to MooTools (other frameworks offer similar functionality), but both of these concepts are not present in jQuery. jQuery does not offer an inheritance system nor does it offer any enhancements to native objects (Function, String, etc). This is not a deficiency of jQuery as the authors of jQuery could easily offer these things. Rather, they have designed a toolkit with a different goal in mind. Where MooTools aims to make JavaScript more fun, jQuery aims to make the DOM more fun and its designers have chosen to limit their scope to that task.
+
+ And this is why jQuery is more accessible. It doesn't ask that you learn JavaScript inside and out. It doesn't throw you into the deep end with prototypal inheritance, binding, "this", and native prototypes. When you get started with jQuery in its official tutorial, this is the first jQuery code example you find:
+ and here's the third:
+ If you read the MooTools book or the MooTools tutorial (both of which I authored) they start in a much different place. While you can skip ahead and quickly learn about effects and the DOM, if you want to learn MooTools, you have to start with things like Class, and, I'll admit: if you're new to programming, or you just want to get something working on your site without having to learn everything about JavaScript, chances are jQuery is going to look a lot more friendly to you.
+
+ On the other hand, if you want to learn JavaScript itself, MooTools is a great way to do it. It implements a lot of things that JavaScript is going to have (many of the methods on Natives are just the JavaScript 1.8 spec and beyond). If you're used to programming, especially both object oriented and functional programming, MooTools has a lot of design patterns that are very exciting and expressive.
+
+ If you look at the things jQuery can do, there's often a counterpart in MooTools. If you look at the things MooTools can do, there is often no way to emulate it using jQuery code because of jQuery's focus on the DOM. MooTools has a broader functionality than jQuery, but there's nothing about jQuery that prevents you from doing those things. For example, jQuery does not come with any sort of inheritance system, but that's ok. You could, if you want, use the MooTools Class in conjunction with jQuery if you wanted to (or write your own). There's even an inheritance plug-in for jQuery (I haven't used it, but I assume it offers pretty much the same kind of functionality).
+ If we look at the example from jQuery above:
+ and we wanted to translate this to MooTools, we'd have:
+
+ These are very similar no?
+
+ Here's a more complex example from jQuery:
+
+ and in MooTools:
+
+ Again, very similar. I'd argue that the MooTools version is more explicit, but also more verbose because of it. It's clear reading the MooTools code that we're adding two events - one for mouse enter and one on mouse leave, while the jQuery version is more concise; its hover method accepts two methods - the first for mouse enter and the second for mouse leave. I personally like the fact that the MooTools code is more legible but that's a very subjective observation.
+
+ I will say that sometimes jQuery can become too esoteric for my taste. The methods don't always make sense to me just looking at them and I find it hard to parse. This is somewhat unfair though, as I am intimately familiar with MooTools, so reading MooTools is easy for me. But one of the things I appreciate about MooTools is how almost all the method and class names really name the thing. Methods are almost always verbs and leave little doubt as to what they do. Every programming language requires you to go to the docs to look up syntax when you write it - I'm not saying that. I'm just saying that I find the API of MooTools to be more coherent and consistent.
+ But what if you like the jQuery syntax? One way to illustrate the power of MooTools is to show you how easy it is to change it to suit your tastes. If we wanted to implement the hover method from jQuery in MooTools, we could easily do so: Indeed, there are MooTools plug-ins that do just that; give you the jQuery syntax for MooTools. MooTools' focus on extensibility means you can implement anything you like. This is something jQuery can't do. MooTools can mimic jQuery if you want it to, but jQuery can't mimic MooTools. If you want to write classes or extend native prototypes or do some of the other things MooTools can, you'll have to write it yourself.
+ Let's do another of these. Here's some jQuery (from the jQuery tutorial):
+
+ This is an example of a syntax that I personally don't prefer. Looking at the code above I am hard pressed to be sure of what it's doing. Most notably I'm curious about what .end does and how does .find, which follows it, relate to what .end does? Now, looking at the docs on jQuery makes it very clear what .end does (it resets to the value of the original selector, in this case #faq). But this seems very odd to me. When I do work with jQuery, I often find myself unsure what a method is going to return to me. Obviously this doesn't bother everyone else as jQuery has a lot of people happily using it, so I'll chalk it up to personal preference again.
+
+ Let's look at the above logic as MooTools:
+
+ Again, the MooTools code is a bit more verbose, but also more explicit. Also note that the design pattern here is to store the reference to #faq in a variable, where jQuery uses its .end method to return to it. I'll note that it's possible to write highly chained code with Mootools. For example:
+
+ But really, writing code like this - lots of logic in a domready statement - with either framework, I'd argue, is itself a bad practice. It's far better to encapsulate your logic into reusable chunks.
+
+ It's very tempting when you're working on a web project to write code this way. Just add some logic on the page that selects the DOM elements and "sets them up" by hiding some, altering others, and adding event listeners for click or mouseover. Developing code this way is very efficient, very fast. The problem with writing all your logic in domready statements is that you end up with a lot of code that does the same thing in different places. If we take the FAQ pattern above we could easily apply the same logic elsewhere on a different page with any list of terms and definitions. Are we going to repeat the same logic every time we find this pattern?
+
+ A simple way to make it reusable is to wrap the logic in a function and pass in arguments. Here's what that might look like in jQuery:
+
+ This is much better for two really big and important reasons:
+
+ jQuery actually has a slightly more refined system for writing reusable "widgets" like these. Rather than encourage you to drop them into functions like the above example (which is really rather crude) it encourages you to write jQuery plug-ins. Here's what that would look like:
+
+
+ But looking at the example above, there's not much difference between declaring our faq function this way vs. declaring it as a stand alone function. Granted, it's not in the global namespace, but we could have just as easily added it to a namespace of our own. By attaching it to jQuery we can chain it with other jquery methods. The other benefit is that the "this" inside our function is the current context of whatever is in the jQuery chain at that moment. By using this pattern for plug-ins we're able to make our plug-in look like it's part of jQuery, but other than that, our plug-in is basically a single function that takes the current jQuery context, does stuff to it, and then returns the context for the next item in the chain. There's not a lot of complexity here, which makes it easy for anyone to write jQuery plug-ins - they're just single functions.
+
+ Note that it is possible to write more complex plugins with jQuery with methods and state. This kind of pattern is supported with the jQuery UI plugin system and doesn't use the same mechanism as the basic plugin (like our faq example). Instead, you attach an object with methods and properties to the jQuery object (i.e. $.ui.tabs). There's a shortcut to invoke this object ($(selector).tabs()) so that you can continue chaining as with the faq plugin. But because it doesn't return a reference to the tabs object created for the items in your selector, you're forced to call that selector again to invoke methods on it. Instead of calling myTabInstance.add(url, label, index) you must execute the selector again and call your function by name (as a string): $(selector).tabs('add', url, label, index);. This means you're running your selector twice (unless you store it in a variable somewhere), and that you don't ever have a pointer to the "add" method that you can do things like bind or delay. This post is focused on the MooTools and jQuery cores, and while jQuery's UI system does provide this functionality, it's not something that comes with jQuery by default.
+
+ In MooTools when you want to define a pattern, you're more likely to use either a Class or implement a method into a native object (into String, for example).
+
+ Rather than give you an almost completely different language from JavaScript's native style, MooTools attempts to walk the middle ground between defining its own custom syntax and extending JavaScript's own design patterns. One of the ways it does this is by extending the prototypes of the native objects in the language and in the DOM. This means that if you needed a method to trim a string, MooTools encourages you to add that method to String itself (note that String.trim is already in MooTools; you don't need to add this yourself):
+
+ This means you can just execute " no more spaces on the end! ".trim() and get back "no more spaces on the end!". Some would say that implementing properties into native prototypes is inappropriate. It's the reason why MooTools and Prototype.js can't play well with each other - any framework that manipulates prototypes of natives doesn't play well with any other framework that does the same. If I define String.prototype.foo() and another library on the same page defines it, too, which ever one comes last wins. In a way, this is similar to the problem we face with the global window namespace. This is how JavaScript works. This is how JavaScript 1.8 has added so many features. It adds them to the prototypes.
+
+ The MooTools developers include a robust framework that is easy for you to extend with your own functionality with the intention that people who include the framework in the page are going to use it, not some other framework. It's actually kind of rude to ask users to download two frameworks. The only reason to include two frameworks is because you want to use plug-ins from both, and in the minds of the MooTools authors (myself included), if you want a plug-in that isn't available with the framework of your choice, it's more appropriate for you to spend the time porting it to your environment than to ask your users to download another framework.
+
+ Once you learn how JavaScript works and see the power of extending native objects, a whole new level of programming opens up. You can write plug-ins that alter Elements or Dates or Functions. While some might argue that adding methods to natives this way is a kind of pollution, I'd argue that this is how JavaScript is meant to be used. It is a design feature of the language. By attaching methods to natives you allow your code to be concise and compartmentalized. jQuery does this too, but limits its prototype enhancements to the jQuery object.
+
+ While you can easily chain multiple method calls on the jQuery object, on any other type of object you have to use
+ generics. For example, in jQuery if you want to trim a string and then iterate over each line, you would have to write:
+ But because MooTools modifies prototypes, you can do this:
+ Taking a look at this makes it extremely clear how powerful it is to
+ modify prototypes. Chaining on DOM elements isn't the only place chaining is
+ useful. MooTools lets you chain methods on any object, including
+ running a method on multiple elements at once.
+
+ The key here is that at the heart of the MooTools framework is the notion that it's there to let you program what you want. If there's functionality that's not in the core, you can extend it and add your own. The job of the core is not to provide everyone with every bit of functionality that they could ever want, but to provide the tools that allow you write the things that you want. A big part of that is making it easier to extend the prototypes of natives, and take advantage of prototypal inheritance. You can do these things with vanilla JavaScript but MooTools makes it easier and more pleasant.
+
+
+ Despite its name, the MooTools Class function is not really a class nor does it create them. It has design patterns that might remind you of classes in a more traditional programming language, but really Class is all about objects and prototypal inheritance. (Unfortunately, using words like "class" are the most convenient way to describe these things, so for the purposes of this article, when I refer to "classes" I'm referring to functions that return objects - which I'll call "instances" - that inherit from a prototype.)
+
+ To make a class, you pass an object to the Class constructor like this:
+
+ You pass Class an object (above, we pass an object with members like "isAlive" and "eat") and this object becomes the prototype of every instance of that class. To create an instance, you call it like this:
+
+ Now we have an instance of Human. bob has the properties of the object we defined when we created our Human class. But the important thing is that bob has these properties through inheritance. When we reference bob.eat, bob doesn't really have this property. JavaScript looks at bob and he doesn't have an eat method, so it looks up the inheritance chain and finds it on the object we passed when we created the Human class. This is true for energy, too. At first glance this looks potentially bad; we don't want all the humans we create to gain energy every time that bob eats. The important thing to recognize is that the first time we assign a value to bob's energy, we assign him his own value and we no longer look at the prototype for it. So the first time bob eats, he gets his own definition for energy (set to 2).
+
+ Note that bob's name and age are unique to him; these are assigned to him when the class is initialized in the initialize method.
+
+ This whole pattern may seem a little odd to you, but the value here is that we can define functionality for a pattern and create instances of that pattern every time we need it. Each instance maintains its own state. So if we create another instance each one is independent of the other, but inherits from the same base pattern:
+
+ Where things get really interesting is when we want to augment this behavior.
+
+ Let's revisit our jQuery faq plug-in. What would happen if we wanted to add more functionality to that plug-in. What if we wanted to make an ajax version that fetched the answers to the questions from the server? Let's imagine that the faq plug-in was authored by someone else and we want to add more to it without altering it in any way (we don't want to fork it).
+
+ Our only real choices are to either duplicate the faq plug-in's logic entirely (remember, it's a single function), essentially forking it, or we can invoke it and then add more logic to it. Given a choice, the latter seems to save us the most trouble. It would look something like this:
+
+ This has some down sides. First of all, our faq class is going to repeat our selector for the definitions, which might be expensive; there's no way to store the retrieved definitions and pass it on for the second time they are needed. Secondly, we can't add our ajax logic into the middle of the faq plug-in's own logic for displaying the definition. The original plug-in called slideToggle which expands the definition using an effect. This is problematic because this effect is going to go off before our ajax finishes loading. There's no real solution here unless we just duplicate the entire faq plug-in.
+
+ Now let's consider our MooTools Human class. It has properties like isAlive and energy and it has a method called eat. What if we wanted to make a new version of Human that had additional properties? With MooTools, we extend the class:
+
+ You can see that we've added a lot of functionality here into a subclass. This subclass has all these properties that are unique to Ninjas. Ninjas start off with an initial energy value of 100. Ninjas get a side. They also get an attack method that lets them kill other Humans, but it costs the Ninja energy.
+
+ Picking this apart a bit, there are some interesting things to consider here. Note that we have an initialize method in the Ninja class. This would appear to overwrite the initialize method in the Human class, but we can still access it by calling this.parent, passing along the arguments that the parent class's initialize expects. Further, we can control when our logic occurs; before or after the call to the parent. We can assign new values to properties (like the energy value) and we can define new functionality. Imagine if we could do this with our faq plug-in for jQuery. We could load our ajax and THEN slide open the value.
+
+ MooTools has another pattern called a Mixin. Unlike the parent to
+ child relationship that is defined by extending one class into a
+ subclass, you can also define classes that are mixed into other
+ classes to imbue them with their properties. Here's an example:
+
+ Here we've broken the qualities that make a Ninja different from a Human and put them in a class of their own. This lets us reuse this code outside of Ninja. We could then imbue our Ninja class with the qualities of a warrior like so:
+
+ Ninja still works as it did before, but Warrior is at our disposal to reuse:
+
+ Now we have a Samurai class and a Ninja class. But look at how little code both Ninja and Samurai took to define. Both of them are similar in that they are humans with warrior qualities, but they are different in that samurais are always, always good, while ninjas have shifting allegiances. By spending the time to write a Human class and a Warrior class, we're able to have three different classes with no repetition of code while maintaining a very granular level of control over when methods are called and how they relate to each other. Each instance we create has its own state and the code itself is very legible.
+
+ Now that you have an overview of how classes work in MooTools, let's look at our faq class that we wrote in jQuery and write it as we would in MooTools and then extend it to add Ajax to it just as we did with jQuery.
+
+ Woah. That's a lot of code. Even if we remove all the comments it's still two dozen lines long. I already illustrated above that we could build this plug-in with roughly the same amount of code as the jQuery version. So why is this one so much longer? Well, we've made it much more flexible. To use the class, we just call the constructor, like this:
+
+ We can access methods and properties of the instance. But what about our ajax functionality? The problem with our ajax extension to the jQuery version was that we couldn't delay the opening of the definition until after it loaded. We don't have that problem with our MooTools version:
+
+
+ Now we have a version of our FAQ class that allows us to get the definitions from the server. Note that we were able to integrate the new logic in a way that doesn't expand the definition until after the content comes back from the server (which we couldn't do with the jQuery version). Also note that we really only had to describe the new functionality (the ajax) and little else. This extensibility makes it possible for you to create families of plug-ins that offer different shades of functionality. It also means that you can use someone else's plug-in and alter just the bits that you to be want different if you need to (without forking it). This helps explain why, for any given design pattern - a date picker, a tab interface, etc, that you typically only find a few plug-ins for MooTools. Most of the plug-ins you get either solve your problem or, if not, you can just extend them to add the things you need.
+
+
+ As I illustrated earlier, it's possible to write complex jQuery widgets with methods and state. Most of the code you write when doing this is vanilla JavaScript when you need to express logic that isn't related to the DOM. But jQuery's model doesn't offer a system for extending these instances into subclasses. Nor does it help you with mixins that can be reused easily. Finally, jQuery's plugins are always attached to DOM elements. If you wanted to write a class that, say, processed URLs, there's no stateful system for such a thing unless you write it yourself.
+
+ jQuery focuses on expressiveness, quick and easy coding, and the DOM while MooTools focuses on extension, inheritance, legibility, reuse, and maintainability. If you put those two things on opposite sides of a scale, the jQuery side translates into something with which it's easy to get started and see quick results but (in my experience) can turn into code that's harder to reuse and maintain (but really that's up to you; it's not jQuery's problem, per se), while the MooTools side takes longer to learn and requires you to write more code upfront before you see results, but afterwards is more reusable and more maintainable.
+
+ Further, the MooTools core does not contain every feature you can imagine and neither does the jQuery core. Both frameworks keep their cores rather lean, leaving it to you and others to write plug-ins and extensions. Their job is not to give you every feature you could want but to give you the tools so that you can implement anything you can imagine. This is the power of JavaScript, and of JavaScript frameworks in general, and both frameworks excel at it. MooTools takes a more holistic approach and gives you tools to write anything you can imagine beyond the scope of the DOM, but pays the price by having a steeper learning curve. MooTools' extensible and holistic approach gives you a superset of jQuery's features, but jQuery's focus on a slick DOM API doesn't preclude you from using the native inheritance methods of JavaScript or from using a class system like MooTools if you want it.
+
+ This is why I say that both frameworks are excellent choices. My effort here has been to highlight the differences in philosophies between the two codebases and highlight their advantages and disadvantages. I doubt I've been successful in keeping my preference for MooTools completely in check, but hopefully this has been helpful. Regardless of which framework you choose to work with, you now know a lot more about both, hopefully. If you have the luxury of time, I strongly recommend implementing a site with each. Then write your own review of them both and maybe your perspective will highlight some things I missed.
+ A history of this document can be viewed on github.
+
+
+ About me: I am a MooTools contributor and I blog about JavaScript and other things on my site Clientcide as well as release numerous plug-ins for MooTools. I am the author of MooTools Essentials as well as the MooTools online tutorial. I work at a company in the SF Bay Area called Cloudera. I can be contacted thusly.
+ A note on comments here: These comments are moderated. No comments will show up until they are approved. Comments that are not productive (i.e. inflammatory, rude, etc) will not be approved. Similarly, "fan" comments won't be approved either - i.e. no "FrameworkX Rulez! It's better than FrameworkY for realz!" are not constructive comments.
+
- Most people getting started with JavaScript these days are faced with the challenging task of picking a library to use, or at least which one to learn first. If you're working for a company chances are they have already chosen a framework for you, in which case the point is somewhat moot. If this is the case and they've chosen MooTools and you're used to jQuery, then this article might still be of some use to you.
-
- Every day on twitter I see numerous posts that boil down to "MooTools or jQuery?" This article aims to help you make that choice.
-
- I am a MooTools developer. I work on the MooTools framework. I blog about MooTools. I wrote the main online tutorial and the book about MooTools. Obviously, I have a perspective that is somewhat biased. I'll also point out that I don't use jQuery that often. If you're a jQuery developer and see anything that I have misrepresented here, please contact me and help me rectify the issue. My objective here is to be helpful and accurate to people - not to sell one framework over another.
-
- Helping you make a choice between these two frameworks involves me telling you how they are different. I'll start out by saying that both of them are excellent choices. You can't make a wrong choice here. Both frameworks have their strengths and weaknesses, but, in general, they are both great choices. There are other frameworks out there that are worth digging into as well. Dojo, Prototype, YUI, Ext and others are all great choices. Which one you choose really has more to do with your own style and what you need to accomplish. The purpose of this article is to focus on MooTools and jQuery, as increasingly these are the two frameworks that I see a lot of people considering. Finally, I'm not trying to convince anyone to switch from one framework to the other. There are interesting things about both frameworks from which you can learn. You can read a little more about this article and why I wrote it in my blog post on Clientcide where I announced it.
+ В наши дни большинство людей, начинающих использовать JavaScript, сталкиваются с непростой задачей выбора библиотеки
+ для дальнейшего использования, или, по крайней мере, какую из них изучать в первую очередь.
+ Если вы работаете в какой-либо компании, то выбор, вероятно, уже сделан за вас, и тогда этот вопрос отпадает. Тем не менее, если
+ вы привыкли к jQuery, а компания заставляет использовать MooTools,
+ эта статья все-таки может оказаться вам полезной.
+
+ Каждый день
+ в твиттере
+ я вижу множество постов, которые сводятся к "MooTools или jQuery?". Эта статья поможет вам определиться с выбором.
+
+ Я — разработчик MooTools. Я работаю над этим фреймворком. Я веду блог про MooTools. Я написал
+ основное онлайн руководство и
+ книгу о MooTools.
+ Очевидно, моя точка зрения несколько предвзята. Подчеркну также, что я не особо часто использую jQuery.
+ Если вы разработчик jQuery и увидели, что я исказил что-нибудь, пожалуйста, свяжитесь со
+ мной, чтобы помочь исправить это недоразумение. Моя задача здесь — помочь людям сделать выбор,
+ а не выставлять один фреймворк перед другим в более выгодном свете.
+
+ Желание помочь вам выбрать между jQuery и MooTools заставляет меня рассказать вам, насколько
+ они отличаются друг от друга. Начну с того, что они оба являются прекрасными фреймворками. Сделать неправильный выбор здесь невозможно.
+ Разумеется, у каждого из них есть свои достоинства и недостатки, но, в целом, они оба — отличный выбор.
+ Есть также и другие фреймворки, которые стоят того, чтобы взглянуть на них более подробно. Dojo,
+ Prototype, YUI,
+ Ext и прочие — тоже прекрасный выбор. Какой именно из них подойдет,
+ больше зависит от вашего стиля и от того, что именно вы хотите сделать. Цель данной статьи — сфокусироваться
+ на MooTools и jQuery, так как именно из них двоих все больше и больше людей пытаются выбирать. В конце концов,
+ я не пытаюсь никого убедить переключиться с одного фреймворка на другой. В них обоих есть что почерпнуть
+ и чему научиться. Более подробно о том, что побудило меня написать эту статью, вы можете прочитать
+ в моем посте на Clientcide.
- Information based on data from jquery.com, mootools.net, and wikipedia.com.
+ Информация основана на данных jquery.com, mootools.net, и wikipedia.com.
- If you go to the jQuery site, here's what it says at the top of the page:
+ Если вы зайдете на сайт jQuery, вот что вы увидите вверху страницы:
- ...and if you go to MooTools, this is what you'll find:
+ ...а вот что написано на официальном сайте MooTools:
- I think this really sums it up. If you ask me (and you're reading this, so I'll assume you just have), the question isn't about which framework is better or worse. It's which one of these things above do you want to do? These two frameworks just aren't trying to do the same things. They overlap in the functionality they provide, but they are not trying to do the same things.
+ Я думаю, это действительно все неплохо суммирует. Если вы спросите меня (а поскольку вы это читаете,
+ я полагаю, что вы уже спросили), вопрос не в том, какой фреймворк лучше или хуже. А в том, что из вышеперечисленных вещей
+ вы хотели бы делать? Эти два фреймворка просто разработаны с разной целью. Разумеется, есть
+ некоторая функциональность, которая присутствует в них обоих, но, тем не менее, они не пытаются делать одно и то же.
- jQuery's description of itself talks about HTML, events, animations, Ajax, and web development. MooTools talks about object oriented-ness and writing powerful and flexible code. jQuery aspires to "change the way you write JavaScript" while MooTools is designed for the intermediate to advanced JavaScript developer.
+ Описание jQuery говорит о HTML, событиях, анимациях, Ajax и веб-разработке. MooTools говорит об
+ объектно-ориентированности и написании мощного и гибкого кода. jQuery стремится "изменить то, как вы обычно пишете JavaScript",
+ в то время как MooTools разработан для разработчиков среднего и продвинутого уровня.
- Part of this consideration is the notion of a framework vs a toolkit. MooTools is a framework that attempts to implement JavaScript as it should be (according to MooTools' authors). The aim is to implement an API that feels like JavaScript and enhances everything; not just the DOM. jQuery is a toolkit that gives you an easy to use collection of methods in a self-contained system designed to make the DOM itself more pleasant. It just so happens that the DOM is where most people focus their effort when writing JavaScript, so in many cases, jQuery is all you need.
+ Важно различать концепции фреймворка и набора инструментов (toolkit). MooTools — это фреймворк, который
+ пытается сделать JavaScript таким, каким он должен быть (согласно авторам MooTools).
+ Его цель — реализовать API, который выглядел бы как JavaScript, но расширял бы все, не только DOM.
+ jQuery — это toolkit, который дает вам удобный набор методов, которые делают работу с DOM более приятной.
+ Просто так получилось, что DOM — это то, на чем концентрируется большинство людей, которые пишут JavaScript,
+ так что, в большинстве случаев jQuery — все, что вам нужно.
- Most of the code you write when you write MooTools still feels like JavaScript. If you aren't interested in JavaScript as a language, then learning MooTools is going to feel like a chore. If you are interested in JavaScript and what makes it interesting, powerful, and expressive, then, personally, I think MooTools is the better choice.
+ Большая часть кода, которую вы пишете, используя MooTools, все еще выглядит как JavaScript.
+ Если вам не интересен JavaScript как язык, то изучение MooTools, скорей всего, станет для вас неприятной рутиной.
+ А если вам интересен JavaScript сам по себе, и то, что делает его таким мощным и выразительным, то
+ лично я думаю, что MooTools подойдет вам больше.
- First, jQuery is, by and large, easier to learn. It has an almost colloquial style that almost doesn't feel like programming. If all you want is to get something working quickly without learning JavaScript, jQuery is probably a better choice for you. It's not that MooTools can't help you accomplish the same things, but I'll admit that MooTools can be a little harder to get the hang of if you're new to JavaScript and also that there are just a lot of resources out there to help you learn jQuery - more than there are for MooTools at least.
-
- If you compare the jQuery community (see the "Discussion" page on jQuery) and the MooTools community (irc, mailing list, and unofficial forum) you'll quickly discover two things: 1) the jQuery community is far larger (I attribute this mostly to the point I made above about how easy it is to learn, but also because...) and 2) they are more active in promoting the library. If you measure jQuery and MooTools on metrics like the number of people using it, the number of search queries run on Google, the number of books sold, etc, you'll see jQuery is ahead by a wide margin.
-
- To tell you why you might consider MooTools I'll first need to talk a little bit about what both the frameworks do. Ultimately which framework you choose is going to come down to what you want to accomplish and how you like to program (and maybe even if you like to program, at least in JavaScript).
+
+ Во-первых, jQuery, по большому счету, легче в освоении. Стиль его кода близок к разговорному и даже почти не
+ ощущается как программирование. Если вам нужно склепать что-нибудь по-быстрому, не изучая JavaScript, то
+ jQuery, вероятно, лучший выбор для вас. Это не значит, что MooTools не сможет вам помочь в таких вещах, но
+ я признаю, что MooTools может оказаться слегка сложнее в изучении, если вы новичок в JavaScript, а также
+ что ресурсов, готовых помочь в изучении jQuery, ощутимо больше, чем аналогичных для MooTools.
+
+ Если вы сравните сообщество jQuery (смотрите страницу "Обсуждение" на сайте jQuery)
+ и сообщество MooTools (irc,
+ mailing list, и
+ unofficial forum),
+ вы быстро обнаружите две вещи:
+ 1) сообщество jQuery гораздо больше (я приписываю это большей частью тому, насколько легче его изучать, однако есть еще одна причина...),
+ 2) оно более активно продвигает свою библиотеку.
+ Если вы измерите jQuery и MooTools с той точки зрения, сколько
+ человек их использует, сколько запросов о них делается в Гугле, сколько было продано книг и так далее,
+ вы увидите, что jQuery находится впереди с большим отрывом.
+
+ Чтобы рассказать о том, почему вам, возможно, стоит поглядеть в сторону MooTools, я сперва должен поговорить о том,
+ что вообще оба эти фреймворка делают. В конечном счете, какой фреймворк вы выберете, зависит от того, что вы хотели бы
+ получить, и как вам нравится программировать (а может быть, и нравится ли вам программировать вообще,
+ по крайней мере на JavaScript).
jQuery vs MooTools
+
+ Disclaimer
+ Purpose
+ Table o' Contents
+
+
+
+ The Stats
+
+
+
+
+
+ jQuery Core
+ MooTools Core
+
+
+ Library Size
+ 55.9K
+ 64.3K
+
+
+ Features
+
+
+ License
+ MIT & GPL
+ MIT
+
+
+ DOM Utilites
+ yes
+ yes
+
+
+ Animation
+ yes
+ yes
+
+
+ Event Handling
+ yes
+ yes
+
+
+ CSS3 Selectors
+ yes (a subset)
+ yes (a subset)
+
+
+ Ajax
+ yes
+ yes
+
+
+ Native Extensions (excluding Element)
+ about a dozen for Array, Object, and String
+ about six dozen for Array, Object, String, Function, and Number
+
+
+ Inheritance
+ Not supported directly with jQuery
+ Provided with Class constructor
+
+
+ Other Considerations
+
+
+ plug-ins
+ Hundreds of unofficial plug-ins in a directory at plugins.jquery.com
+ Roughly 4 dozen official plug-ins available at mootools.net/more. Unofficial plugin directory at mootools.net/plugins.
+
+
+ Official UI library
+ yes
+ no
+ The Mottos Say It All
+
+
+ jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.
+ MooTools is a compact, modular, Object-Oriented JavaScript framework designed for the intermediate to advanced JavaScript developer. It allows you to write powerful, flexible, and cross-browser code with its elegant, well documented, and coherent API.
+ The Learning Curve and The Community
+
+ What JavaScript Is Good For
+
+ More Than Just The DOM
+
+ Inheritance with JavaScript
+
+ for (var i = 0; i < myArray.length; i++) { /* do stuff */ }
+ myArray.forEach(function(item, index) { /* do stuff */ });
+ [1,2,3].forEach(function(item) { alert(item) }); //this alerts 1 then 2 then 3
+ Self Reference
+ var ninja = {
+ weapons: ['katana', 'throwing stars', 'exploding palm technique'],
+ log: function(message) {
+ console.log(message);
+ },
+ logInventory: function() {
+ this.weapons.each(function(weapon) {
+ //we want "this" to point to ninja...
+ this.log('this ninja can kill with its ' + weapon);
+ }, this); //so we pass "this" (which is ninja) to Array.each
+ }
+};
+ninja.logInventory();
+//this ninja can kill with its katana
+//this ninja can kill with its throwing stars
+//this ninja can kill with its exploding palm technique
+
+ MooTools Makes JavaScript Itself More Fun
+
+ jQuery Makes the DOM More Fun
+
+ window.onload = function() {
+ alert("welcome");
+}
+
+ $(document).ready(function() {
+ $("a").click(function(event) {
+ alert("Thanks for visiting!");
+ });
+});
+
+ Anything You Can Do I Can Do Better
+
+ $(document).ready(function() {
+ $("a").click(function(event) {
+ alert("Thanks for visiting!");
+ });
+});
+
+ window.addEvent('domready', function() {
+ $$('a').addEvent('click', function(event) {
+ alert('Thanks for visiting!');
+ });
+});
+ $(document).ready(function() {
+ $("#orderedlist li:last").hover(function() {
+ $(this).addClass("green");
+ },
+ function() {
+ $(this).removeClass("green");
+ });
+});
+
+ window.addEvent('domready',function() {
+ $$('#orderedlist li:last-child').addEvents({
+ mouseenter: function() {
+ this.addClass('green');
+ },
+ mouseleave: function() {
+ this.removeClass('green');
+ }
+ });
+});
+
+ MooTools Lets You Have It Your Way
+
+ Element.implement({
+ hover : function(enter,leave){
+ return this.addEvents({ mouseenter : enter, mouseleave : leave });
+ }
+});
+
+//and then you could use it exactly like the jQuery version:
+$$('#orderlist li:last').hover(function(){
+ this.addClass('green');
+},
+function(){
+ this.removeClass('green');
+});
+
+
+ Chaining as a Design Pattern
+
+ $(document).ready(function() {
+ $('#faq').find('dd').hide().end().find('dt').click(function() {
+ $(this).next().slideToggle();
+ });
+});
+
+ window.addEvent('domready', function() {
+ var faq = $('faq');
+ faq.getElements('dd').hide();
+ faq.getElements('dt').addEvent('click', function() {
+ this.getNext().slide('toggle');
+ });
+});
+
+
+
+ item.getElements('input[type=checkbox]')
+ .filter(function(box) {
+ return box.checked != checked;
+ })
+ .set('checked', checked)
+ .getParent()[(checked) ? 'addClass' : 'removeClass']('checked')
+ .fireEvent((checked) ? 'check' : 'uncheck');
+
+ Reusing Code with jQuery
+
+ function faq(container, terms, definitions) {
+ $(container).find(terms).hide().end().find(definitions).click(function() {
+ $(this).next().slideToggle();
+ });
+};
+$(document).ready(function() {
+ faq('#faq', 'dd', 'dt');
+});
+
+
+
+ jQuery.fn.faq = function(options) {
+ var settings = jQuery.extend({
+ terms: 'dt',
+ definitions: 'dd'
+ }, options);
+ //"this" is the current context; in this case, the elements we want to turn into faq layouts
+ $(this).find(settings.terms).hide().end().find(settings.definitions).click(function() {
+ $(this).next().slideToggle();
+ });
+ return this;
+};
+
+
+ which you would use thusly:
+
+ $('#faq').faq();
+
+ Reusing Code with MooTools
+
+ String.implement({
+ trim: function() {
+ return this.replace(/^\s+|\s+$/g, '');
+ }
+});
+
+ $.each( $.trim( $('span.something').html() ).split("\n"), function(i, line){alert(line);});
+
+ $('span.something').get('html').trim().split("\n").each(function(line){alert(line);});
+
+ MooTools and Inheritance
+
+ var Human = new Class({
+ initialize: function(name, age) {
+ this.name = name;
+ this.age = age;
+ },
+ isAlive: true,
+ energy: 1,
+ eat: function() {
+ this.energy = this.energy + 1; //same as this.energy++
+ }
+});
+
+ var bob = new Human("bob", 20); //bob's name is "bob" and he's 20 years old.
+ bob.eat(); //bob.energy == 2
+ var Alice = new Human();
+//alice.energy == 1
+//bob.energy == 2
+
+ Extending and Implementing Classes
+
+ jQuery.fn.ajaxFaq = function(options) {
+ var settings = jQuery.extend({
+ //some ajax specific options like the url to request terms from
+ url: '/getfaq.php'
+ definitions: 'dd'
+ }, options);
+ //"this" is the current context; in this case, the elements we want to turn into faq layouts
+ $(this).find(settings.definitions).click(function() {
+ $(this).load(.....); //the logic to load the content from the term
+ });
+ this.faq(); //call our original faq plug-in
+});
+ var Ninja = new Class({
+ Extends: Human,
+ initialize: function(name, age, side) {
+ this.side = side;
+ this.parent(name, age);
+ },
+ energy: 100,
+ attack: function(target) {
+ this.energy = this.energy - 5;
+ target.isAlive = false;
+ }
+});
+ var bob = new Human('Bob', 25);
+var blackNinja = new Ninja('Nin Tendo', 'unknown', 'evil');
+//blackNinja.isAlive = true
+//blackNinja.name = 'Nin Tendo'
+blackNinja.attack(bob);
+//bob never had a chance
+
+ var Warrior = new Class({
+ energy: 100,
+ kills: 0,
+ attack: function(target) {
+ target.isAlive = false;
+ this.energy = this.energy - 5;
+ this.kills++;
+ }
+});
+
+ var Ninja = new Class({
+ Extends: Human,
+ Implements: Warrior, //can be an array if you want to implement more than one
+ initialize: function(name, age, side) {
+ this.side = side;
+ this.parent(name, age);
+ }
+});
+
+ var Samurai = new Class({
+ Extends: Human,
+ Implements: Warrior,
+ side: 'good'
+});
+
+
+var FAQ = new Class({
+ //Options is another class provided by MooTools
+ Implements: Options,
+ //these are the default options
+ options: {
+ terms: 'dt',
+ definitions: 'dd'
+ },
+ initialize: function(container, options) {
+ //we store a reference to our container
+ this.container = $(container);
+ //setOptions is a method provided by the Options mixin
+ //it merges the options passed in with the defaults
+ this.setOptions(options);
+ //we store the terms and definitions
+ this.terms = this.container.getElements(this.options.terms);
+ this.definitions = this.container.getElements(this.options.definitions);
+ //we call our attach method
+ //by breaking this into its own method
+ //it makes our class easier to extend
+ this.attach();
+ },
+ attach: function(){
+ //loop through the terms
+ this.terms.each(function(term, index) {
+ //add a click event to each one
+ term.addEvent('click', function(){
+ //that calls our toggle method for
+ //the current index
+ this.toggle(index);
+ }, this);
+ }, this);
+ },
+ toggle: function(index){
+ //toggle open the definition for the given index
+ this.definitions[index].slide('toggle');
+ }
+});
+
+
+ var myFAQ = new FAQ(myContainer);
+//and now we can call methods on it if we want:
+myFAQ.toggle(2); //toggle the 3rd element
+
+
+ FAQ.Ajax = new Class({
+ //this class inherits the properties of FAQ
+ Extends: FAQ,
+ //it also gets a new option in addition to the other defaults
+ //this one for url, that we're going to append the index of the
+ //term to; in reality we might make this more robust, but for
+ //this example it serves the purpose
+ options: {
+ url: null;
+ },
+ //we're going to cache the results, so if a section is opened
+ //twice, we won't hit the server for the data
+ indexesLoaded: [],
+ toggle: function(index){
+ //if we've already loaded the definition
+ if (this.indexesLoaded[index]) {
+ //just call the previous version of toggle
+ this.parent(index);
+ } else {
+ //otherwise, request the data from the server
+ new Request.HTML({
+ update: this.definitions[index],
+ url: this.options.url + index,
+ //and when the data is loaded, expand the definition
+ onComplete: function(){
+ this.indexesLoaded[index] = true;
+ this.definitions[index].slide('toggle');
+ }.bind(this)
+ }).send();
+ }
+ }
+});
+
+
+ Decision Time
+
+
+
+ jQuery vs MooTools
Disclaimer
- Purpose
- Отказ от ответственности
+ Цель данной статьи
+ Table o' Contents
-
-
+ Содержание
+
+
- The Stats
+ Сухие цифры
- jQuery Core
- MooTools Core
+ Ядро jQuery
+ Ядро MooTools
-
Library Size
+ Размер библиотеки
55.9K
64.3K
-
Features
+ Особенности
-
License
+ Лицензия
MIT & GPL
MIT
-
DOM Utilites
- yes
- yes
+ Функции для работы с DOM
+ есть
+ есть
-
Animation
- yes
- yes
+ Анимация
+ есть
+ есть
-
Event Handling
- yes
- yes
+ Обработка событие
+ есть
+ есть
-
CSS3 Selectors
- yes (a subset)
- yes (a subset)
+ CSS3 селекторы
+ есть (подмножество)
+ есть (подмножество)
Ajax
- yes
- yes
+ есть
+ есть
-
Native Extensions (excluding Element)
- about a dozen for Array, Object, and String
- about six dozen for Array, Object, String, Function, and Number
+ Нативные расширения (кроме Element)
+ около 12 для Array, Object, и String
+ 70+ для Array, Object, String, Function, и Number
-
Inheritance
- Not supported directly with jQuery
- Provided with Class constructor
+ Наследование
+ Напрямую не поддерживается jQuery
+ Предоставляется конструктором Class
-
Other Considerations
+ Прочие соображения
-
plug-ins
- Hundreds of unofficial plug-ins in a directory at plugins.jquery.com
- Roughly 4 dozen official plug-ins available at mootools.net/more. Unofficial plugin directory at mootools.net/plugins.
+ Плагины
+ Сотни неофициальных плагинов — plugins.jquery.com
+ Около 50 официальных плагинов тут — mootools.net/more. Неофициальные плагины тут — mootools.net/plugins.
-
Official UI library
- yes
- no
+ Официальная библиотека UI
+ есть
+ нет
The Mottos Say It All
-
-
+ Девизы говорят сами за себя
jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.
+
+ jQuery — быстрая и компактная JavaScript библиотека, которая упрощает работу с HTML документами,
+ обработкой событий, анимацией и Ajax для быстрой веб-разработки. jQuery cоздан, чтобы изменить
+ то, как вы обычно пишете JavaScript.
+
MooTools is a compact, modular, Object-Oriented JavaScript framework designed for the intermediate to advanced JavaScript developer. It allows you to write powerful, flexible, and cross-browser code with its elegant, well documented, and coherent API.
+ MooTools — это компактный, модульный, объектно-ориентированный JavaScript фреймворк, созданный для
+ JavaScript разработчиков среднего и продвинутого уровня. Он позволяет писать мощный, гибкий и кроссбраузерный
+ код с элегантным, понятным, логичным и хорошо документированным API.
+
The Learning Curve and The Community
-
- Сложность изучения и сообщество
+ Содержание
Сложность изучения и сообщество
- Part of making this choice is asking what you want to do with JavaScript. Let's consider vanilla JavaScript. No framework; just plain old JS. JavaScript gives you native objects like Strings, Numbers, Functions, Arrays, Dates, Regular Expressions, and more. JavaScript also gives you an inheritance model - a somewhat esoteric model called prototypal inheritance (which I'll talk about more later). These building blocks and the concept of inheritance are the bread and butter of any programming language and they have absolutely nothing to do with browsers or the web or CSS or HTML. You could write anything you wanted to in JavaScript. Tic-tac-toe, chess, photoediting, a web server, whatever. It just so happens that 99% of all the JavaScript out there is run in browsers and that's what we think of it as. The programming language for browsers. -
-- Understanding that the browser, the DOM, is just where we happen to use JS most of the time but that it's actually a very robust and expressive programming language will help you understand the difference between MooTools and jQuery. +
+ Важно понять, что именно вы хотите делать с помощью JavaScript. Давайте рассмотрим "чистый" JavaScript. Без фреймворков, просто старый добрый JS. + JavaScript предоставляет изначально нативные объекты вроде + Strings, + Numbers, + Functions, + Arrays, + Dates, + Regular Expressions, + и так далее. + JavaScript также предоставляет вам способ наследования — довольно эзотерический способ, + называемый прототипное наследование + (о котором мы поговорим позже). Вот эти строительные блоки и концепция наследования — хлеб с маслом + любого языка программирования, и они не имеют совершенно никакого отношения к браузерам, вебу или CSS с HTML. + Вы можете написать на JavaScript все, что хотите. Крестики-нолики, шахматы, обработчик фотографий, + веб-сервер, что угодно. Просто так получилось, что 99% всего JavaScript запускается в браузерах, и поэтому + мы так о нем думаем. Как о языке программирования для браузеров. +
++ Понимание того, что браузеры и DOM — всего лишь то, для чего мы исторически больше всего используем + JavaScript, а на самом деле это очень надежный и выразительный язык программирования, поможет вам + понять различия между MooTools и jQuery.
-- If you think of the tasks that we want to accomplish in JavaScript strictly in terms of "get stuff on the page and do stuff to it" then jQuery is probably the best choice. It excels at offering a very expressive system for describing behavior on the page in a way that doesn't feel like programming sometimes. You can still use the rest of JavaScript to do what you want to do, but if you're focused on the DOM - changing CSS properties, animating things, fetching content via AJAX, etc - most of what you'll end up writing will be covered by jQuery, and what isn't will likely be plain-old JavaScript. jQuery does provide some methods that aren't about the DOM; for example, it provides a mechanism for iterating over arrays - $.each(array, fn) - or, for example, it offers a trim method for strings - $.trim(str). But there aren't a ton of these types of utility methods, which is fine because, for the most part, if you're just getting stuff out of the DOM, iterating over them, and altering them in some way (adding html, changing styles, adding event listeners for click and mouseover, etc) you don't need much else. -
-- But if you think of JavaScript's scope in its full breadth, you can see that jQuery doesn't focus on things outside of the DOM. This is one of the reasons it is so easy to learn, but it also limits the ways it can help you write JavaScript. It's just not trying to be anything other than a solid programming system for the DOM. It doesn't address inheritance nor does it address the basic utilities of all the native types in the JavaScript language, but it doesn't need to. If you want to mess around with strings, dates, regular expressions, arrays and functions, you can. It's just not jQuery's job to help you do it. JavaScript as a language is there at your feet. jQuery makes the DOM your playground, but the rest of JavaScript is just not in its scope. -
-- This is where MooTools is vastly different. Rather than focusing exclusively on the DOM (though, as I'll get into in a bit, it offers all the functionality that jQuery does but accomplishes this in a very different manner), MooTools takes into its scope the entire language. If jQuery makes the DOM your playground, MooTools aims to make JavaScript your playground, and this is one of the reasons why it's harder to learn. +
+ Если все ваши задачи, которые вы хотите решить с помощью JavaScript — это "взять эту штуку + со страницы и сделать с ней вот эти вот штуки", то jQuery, вероятно, для вас лучший выбор. + Ему прекрасно удается предоставлять очень выразительный способ описания поведения объектов на странице, + который иногда даже не похож на программирование. Вы по-прежнему можете использовать остальную часть + JavaScript для других целей, но если вы в основном сконцентрированы на DOM — изменении CSS свойств, + анимации объектов, получении данных через AJAX и тому подобном — большая часть того, что вы пишете, + будет покрыта jQuery, и эта часть не будет выглядеть как старый добрый JavaScript. + jQuery предоставляет несколько методов, не относящихся к DOM. Например, механизм для итерации + по массивам — $.each(array, fn) — + или, например, функцию для обрезания строк — $.trim(str). + Но этих методов там совсем немного, что и хорошо, поскольку в большей части кода вы просто + получаете всякие штуки из DOM, итерируете по ним и меняете каким-либо образом (добавляете html, + изменяете стили, добавляете обработчики события для click и mouseover и т.п.), и вам особо + ничего больше не нужно. +
++ Но если вы подумаете о JavaScript в более широком смысле, вы увидете, что jQuery не фокусируется на + вещах помимо DOM. Это, кстати, одна из причин, почему его так легко изучать, но это также ограничивает + вас в предоставляемых библиотекой возможностях. Он даже просто не пытается быть чем-то большим, + чем отличной системой программирования для DOM. Он не обращает внимания ни на наследование, + ни на все нативные типы в языке JavaScript, но ему этого и не нужно. Если вам нужно возится со + строками, датами, регулярными выражениями, массивами и функциями, без проблем. Просто это уже + не работа jQuery. К вашим услугам обычный JavaScript. jQuery делает вам конфетку из DOM, но все остальное + уже выходит за его рамки. +
++ Вот в чем отличие MooTools. Вместо того чтобы фокусироваться только на DOM (хотя, как вам дальше будет + видно, он предлагает всю ту же функциональность, что и jQuery, просто в совершенно другой манере), + MooTools включает в свои рамки весь язык. Если jQuery делает вам конфетку из DOM, MooTools пытается + сделать конфетку из самого JavaScript, и это одна из причин, по которой его сложнее изучать.
From 254c0f29d7589a8c86a2c0c188bc4f3f98e87772 Mon Sep 17 00:00:00 2001 From: Ivan Ivanov+ + +
+В наши дни большинство людей, начинающих использовать JavaScript, сталкиваются с непростой задачей выбора библиотеки для дальнейшего использования, или, по крайней мере, какую из них изучать в первую очередь. Если вы работаете в какой-либо компании, то выбор, вероятно, уже сделан за вас, и тогда этот вопрос отпадает. Тем не менее, если вы привыкли к jQuery, а компания заставляет использовать MooTools, эта статья все-таки может оказаться вам полезной. -
- ++ Каждый день в твиттере я вижу множество постов, которые сводятся к "MooTools или jQuery?". Эта статья поможет вам определиться с выбором. -
-+
+Я — разработчик MooTools. Я работаю над этим фреймворком. Я веду блог про MooTools. Я написал основное онлайн руководство и книгу о MooTools. @@ -132,10 +132,10 @@
+
Желание помочь вам выбрать между jQuery и MooTools заставляет меня рассказать вам, насколько они отличаются друг от друга. Начну с того, что они оба являются прекрасными фреймворками. Сделать неправильный выбор здесь невозможно. Разумеется, у каждого из них есть свои достоинства и недостатки, но, в целом, они оба — отличный выбор. @@ -147,9 +147,9 @@
- | Ядро jQuery | -Ядро MooTools | -
---|---|---|
Размер библиотеки | -55.9K | -64.3K | -
Особенности | -||
Лицензия | -MIT & GPL | -MIT | -
Функции для работы с DOM | -есть | -есть | -
Анимация | -есть | -есть | -
Обработка событие | -есть | -есть | -
CSS3 селекторы | -есть (подмножество) | -есть (подмножество) | -
Ajax | -есть | -есть | -
Нативные расширения (кроме Element) | -около 12 для Array, Object, и String | -70+ для Array, Object, String, Function, и Number | -
Наследование | -Напрямую не поддерживается jQuery | -Предоставляется конструктором Class | -
Прочие соображения | -||
Плагины | -Сотни неофициальных плагинов — plugins.jquery.com | -Около 50 официальных плагинов тут — mootools.net/more. Неофициальные плагины тут — mootools.net/plugins. | -
Официальная библиотека UI | -есть | -нет | -
- Информация основана на данных jquery.com, mootools.net, и wikipedia.com. -
- - -+ +
+ | Ядро jQuery | +Ядро MooTools | +
---|---|---|
Размер библиотеки | +55.9K | +64.3K | +
Особенности | +||
Лицензия | +MIT & GPL | +MIT | +
Функции для работы с DOM | +есть | +есть | +
Анимация | +есть | +есть | +
Обработка событие | +есть | +есть | +
CSS3 селекторы | +есть (подмножество) | +есть (подмножество) | +
Ajax | +есть | +есть | +
Нативные расширения (кроме Element) | +около 12 для Array, Object, и String | +70+ для Array, Object, String, Function, и Number | +
Наследование | +Напрямую не поддерживается jQuery | +Предоставляется конструктором Class | +
Прочие соображения | +||
Плагины | +Сотни неофициальных плагинов — plugins.jquery.com | +Около 50 официальных плагинов тут — mootools.net/more. Неофициальные плагины тут — mootools.net/plugins. | +
Официальная библиотека UI | +есть | +нет | +
+ Информация основана на данных jquery.com, mootools.net, и wikipedia.com. +
+ + +Если вы зайдете на сайт jQuery, вот что вы увидите вверху страницы: -
-+ +jQuery — быстрая и компактная JavaScript библиотека, которая упрощает работу с HTML документами, обработкой событий, анимацией и Ajax для быстрой веб-разработки. jQuery cоздан, чтобы изменить то, как вы обычно пишете JavaScript.-- ...а вот что написано на официальном сайте MooTools: -
-MooTools — это компактный, модульный, объектно-ориентированный JavaScript фреймворк, созданный для ++ ...а вот что написано на официальном сайте MooTools: +
+MooTools — это компактный, модульный, объектно-ориентированный JavaScript фреймворк, созданный для JavaScript разработчиков среднего и продвинутого уровня. Он позволяет писать мощный, гибкий и кроссбраузерный код с элегантным, понятным, логичным и хорошо документированным API.-+
Я думаю, это действительно все неплохо суммирует. Если вы спросите меня (а поскольку вы это читаете, я полагаю, что вы уже спросили), вопрос не в том, какой фреймворк лучше или хуже. А в том, что из вышеперечисленных вещей вы хотели бы делать? Эти два фреймворка просто разработаны с разной целью. Разумеется, есть некоторая функциональность, которая присутствует в них обоих, но, тем не менее, они не пытаются делать одно и то же. -
-+
+Описание jQuery говорит о HTML, событиях, анимациях, Ajax и веб-разработке. MooTools говорит об объектно-ориентированности и написании мощного и гибкого кода. jQuery стремится "изменить то, как вы обычно пишете JavaScript", в то время как MooTools разработан для разработчиков среднего и продвинутого уровня. -
-+
+Важно различать концепции фреймворка и набора инструментов (toolkit). MooTools — это фреймворк, который пытается сделать JavaScript таким, каким он должен быть (согласно авторам MooTools). Его цель — реализовать API, который выглядел бы как JavaScript, но расширял бы все, не только DOM. jQuery — это toolkit, который дает вам удобный набор методов, которые делают работу с DOM более приятной. Просто так получилось, что DOM — это то, на чем концентрируется большинство людей, которые пишут JavaScript, так что, в большинстве случаев jQuery — все, что вам нужно. -
-+
+Большая часть кода, которую вы пишете, используя MooTools, все еще выглядит как JavaScript. Если вам не интересен JavaScript как язык, то изучение MooTools, скорей всего, станет для вас неприятной рутиной. А если вам интересен JavaScript сам по себе, и то, что делает его таким мощным и выразительным, то лично я думаю, что MooTools подойдет вам больше. -
+ - -Сложность изучения и сообщество
-Сложность изучения и сообщество
+Во-первых, jQuery, по большому счету, легче в освоении. Стиль его кода близок к разговорному и даже почти не ощущается как программирование. Если вам нужно склепать что-нибудь по-быстрому, не изучая JavaScript, то jQuery, вероятно, лучший выбор для вас. Это не значит, что MooTools не сможет вам помочь в таких вещах, но я признаю, что MooTools может оказаться слегка сложнее в изучении, если вы новичок в JavaScript, а также что ресурсов, готовых помочь в изучении jQuery, ощутимо больше, чем аналогичных для MooTools. -
-+
+Если вы сравните сообщество jQuery (смотрите страницу "Обсуждение" на сайте jQuery) и сообщество MooTools (irc, mailing list, и @@ -312,17 +312,17 @@
Сложность изучения и сообщество
Если вы измерите jQuery и MooTools с той точки зрения, сколько человек их использует, сколько запросов о них делается в Гугле, сколько было продано книг и так далее, вы увидите, что jQuery находится впереди с большим отрывом. - -+
+Чтобы рассказать о том, почему вам, возможно, стоит поглядеть в сторону MooTools, я сперва должен поговорить о том, что вообще оба эти фреймворка делают. В конечном счете, какой фреймворк вы выберете, зависит от того, что вы хотели бы получить, и как вам нравится программировать (а может быть, и нравится ли вам программировать вообще, по крайней мере на JavaScript). -
- - -Для чего годится JavaScript
-+
+ + +Для чего годится JavaScript
+Важно понять, что именно вы хотите делать с помощью JavaScript. Давайте рассмотрим "чистый" JavaScript. Без фреймворков, просто старый добрый JS. JavaScript предоставляет изначально нативные объекты вроде Strings, @@ -330,27 +330,27 @@
Для чего годится JavaScript
Functions, Arrays, Dates, - Regular Expressions, + Regular Expressions и так далее. JavaScript также предоставляет вам способ наследования — довольно эзотерический способ, - называемый прототипное наследование + называемый прототипным наследованием (о котором мы поговорим позже). Вот эти строительные блоки и концепция наследования — хлеб с маслом любого языка программирования, и они не имеют совершенно никакого отношения к браузерам, вебу или CSS с HTML. Вы можете написать на JavaScript все, что хотите. Крестики-нолики, шахматы, обработчик фотографий, веб-сервер, что угодно. Просто так получилось, что 99% всего JavaScript запускается в браузерах, и поэтому - мы так о нем думаем. Как о языке программирования для браузеров. - -+ мы так о нем думаем, как о языке программирования для браузеров. +
+Понимание того, что браузеры и DOM — всего лишь то, для чего мы исторически больше всего используем JavaScript, а на самом деле это очень надежный и выразительный язык программирования, поможет вам понять различия между MooTools и jQuery. -
- - -Больше, чем просто DOM
-+
+ + +Больше, чем просто DOM
+Если все ваши задачи, которые вы хотите решить с помощью JavaScript — это "взять эту штуку - со страницы и сделать с ней вот эти вот штуки", то jQuery, вероятно, для вас лучший выбор. + со страницы и сделать с ней вот эти штуки", то jQuery, вероятно, для вас лучший выбор. Ему прекрасно удается предоставлять очень выразительный способ описания поведения объектов на странице, который иногда даже не похож на программирование. Вы по-прежнему можете использовать остальную часть JavaScript для других целей, но если вы в основном сконцентрированы на DOM — изменении CSS свойств, @@ -363,8 +363,8 @@
Больше, чем просто DOM
получаете всякие штуки из DOM, итерируете по ним и меняете каким-либо образом (добавляете html, изменяете стили, добавляете обработчики события для click и mouseover и т.п.), и вам особо ничего больше не нужно. - -+
+Но если вы подумаете о JavaScript в более широком смысле, вы увидете, что jQuery не фокусируется на вещах помимо DOM. Это, кстати, одна из причин, почему его так легко изучать, но это также ограничивает вас в предоставляемых библиотекой возможностях. Он даже просто не пытается быть чем-то большим, @@ -373,87 +373,136 @@
Больше, чем просто DOM
строками, датами, регулярными выражениями, массивами и функциями, без проблем. Просто это уже не работа jQuery. К вашим услугам обычный JavaScript. jQuery делает вам конфетку из DOM, но все остальное уже выходит за его рамки. - -+
+Вот в чем отличие MooTools. Вместо того чтобы фокусироваться только на DOM (хотя, как вам дальше будет видно, он предлагает всю ту же функциональность, что и jQuery, просто в совершенно другой манере), MooTools включает в свои рамки весь язык. Если jQuery делает вам конфетку из DOM, MooTools пытается сделать конфетку из самого JavaScript, и это одна из причин, по которой его сложнее изучать. -
- - -Inheritance with JavaScript
- -- The JavaScript programming language has some really awesome things about it. For starters, it's a functional language, which means that it treats functions as high-order objects that can be passed around as variables just like any other object - strings or numbers for example. It's designed with this concept in mind and many of the methods and patterns in it work best when you write code this way. It's the difference between: -
-for (var i = 0; i < myArray.length; i++) { /* do stuff */ }-- and -
-myArray.forEach(function(item, index) { /* do stuff */ });-- JavaScript has an inheritance model that is not quite unique but at least rather rare in programming languages. Instead of classes that are defined that can be subclassed it passes along traits through prototypal inheritance. This means that objects inherit directly from other objects. If you reference a property on an object that inherits from another object, the language inspects the child object for that property and, if it doesn't find it, looks for it on the parent. This is how a method on, say, an array works. When you type: -
-[1,2,3].forEach(function(item) { alert(item) }); //this alerts 1 then 2 then 3-- the method "forEach" is not a property of the array you declare ([1,2,3]), it is a property of the prototype for all Arrays. When you reference this method the language looks for a method called forEach on your array, and, not finding it, then looks at the prototype for all arrays. This means that the forEach method is not in memory once for every array in memory; it is only in memory for the prototype of arrays. This is incredibly efficient and ultimately quite powerful. (Side note: MooTools aliases the forEach method as each) -
- - -Self Reference
-- Javascript has a special word: "this". It's hard for me to succinctly define what "this" is all about but, by default, "this" is the object to which the current method belongs. It allows objects to refer to themselves within their methods as they would otherwise have no means to do so. This becomes important when you create children objects and have numerous instances of that object; how else could the method of an object refer to itself? When the actual copy of the method exists on the parent, not the child, the "this" keyword allows these instances to refer to their own state. (here's a much more complete description of the "this" keyword, and another from Mozilla.) -
-- The "this" keyword allows objects that inherit from other objects to refer to themselves, but there are times when you may want to reference something else through "this". This is called binding, wherein you specify a different "this" for a method. The "each" method on Array allows you to specify the bound object with a second argument. Here's an example of where you might want to pass in a different "this": -
+ + + +Наследование в JavaScript
++ Язык программирования JavaScript имеет несколько замечательных особенностей. Во-первых, это + функциональный язык, что означает, + что функции в нем являются объектами высшего порядка, которые могут передаваться повсюду в качестве + переменных, как и любые другие объекты, например, строки и числа. Его создавали, держа в уме эту + концепцию, и большинство его методов и подходов работают лучше всего, если вы пишете код в этом стиле. + Есть некоторые различия между: +
+for (var i = 0; i < myArray.length; i++) { /* делать всякие штуки */ }++ и +
+myArray.forEach(function(item, index) { /* делать всякие штуки */ });++ В JavaScript особенная модель наследования, + которая не то что бы уникальна, но, по крайней мере, довольно редко встречается в языках программирования. + Вместо классов, которые нужно объявлять отдельно, чтобы из них создавать подклассы, здесь используется + прототипное наследование. + Это означает, что объекты наследуются напрямую от других объектов. Если вы обращаетесь к свойству + какого-нибудь объекта, который наследуется от другого объекта, язык проверяет наличие данного свойства + у наследника, и если не находит, ищет такое свойство у родителя. Вот как этот метод работает, скажем, + на массивах. Когда вы печатаете: +
+[1,2,3].forEach(function(item) { alert(item) }); // выводит сначала 1, потом 2, потом 3++ метод "forEach" + не является свойством массива, который вы объявили ([1,2,3]), это общее свойство прототипа + для всех массивов. Когда вы обращаетесь к этому методу, JavaScript ищет метод forEach в вашем массиве + и, не найдя, ищет его в прототипе всех массивов. Это означает, что метод forEach не хранится в памяти + для каждого отдельно взятого массива, а хранится в одном месте только для прототипа массивов. Это невероятно + эффективно и довольно мощно. (Замечание: в MooTools метод forEach доступен как each). +
+ + +Ссылки на самого себя
++ В JavaScript есть ключевое слово "this". Сложно кратко сказать, что это вообще такое, но, по умолчанию, + "this" — это тот объект, которому принадлежит текущий метод. Это позволяет объектам ссылаться + на самих себя, а иначе они бы не имели такой возможности. Это становится важным, когда вы создаете + много дочерних объектов. Как иначе эти объекты могли бы сослаться на самих себя в своих же методах? + Когда настоящий метод расположен не в дочернем объекте, а в родителе, "this" позволяет + дочернему объекту обращаться к своему состоянию, а не к состоянию родителя. + (Здесь гораздо более подробно рассказано про "this", + и вот еще от Мозиллы.) +
++ Ключевое слово "this" позволяет объектам, наследующимся от других объектов, обращаться к самим себе, + но бывают случаи, когда нужно обращаться через "this" к чему-нибудь другому. Это называется + binding (привязывание), + когда вы определяете другой "this" для метода. Метод "each" для массивов позволяет вам + передать вторым параметром связанный объект. Вот пример того, где вам может понадобиться передавать другой + "this": +
var ninja = { - weapons: ['katana', 'throwing stars', 'exploding palm technique'], + weapons: ['катана', 'метательные звездочки', 'супер техника ударов ладонями, взрывающая сердца'], log: function(message) { console.log(message); }, logInventory: function() { this.weapons.each(function(weapon) { - //we want "this" to point to ninja... - this.log('this ninja can kill with its ' + weapon); - }, this); //so we pass "this" (which is ninja) to Array.each + // мы хотим, чтобы "this" ссылался на ниндзю + this.log('У этого ниндзи есть ' + weapon); + }, this); // так что мы передаем "this" (который ниндзя) в Array.each } }; ninja.logInventory(); -//this ninja can kill with its katana -//this ninja can kill with its throwing stars -//this ninja can kill with its exploding palm technique- -- In the example above, we bind ninja (which is "this" inside the logInventory method) to the method we pass to the array so that we can refer to the log property of ninja. If we didn't do this, "this" would be window. -
-- These are just some examples of the power and expressiveness that JavaScript has to offer - inheritance, self reference and binding, and efficient prototype properties. The bad news is that vanilla JavaScript doesn't make these powerful things very useful or accessible, and this is where MooTools starts. It makes these types of patterns easy and rather pleasant to use. You end up writing more abstract code, and in the long run, this is a good thing - a powerful thing. Learning how these patterns are valuable and how to use them properly takes effort, but the up side is that the code you author is both highly reusable and much easier to maintain. I'll talk about these two things a bit more in a minute. -
- - -MooTools Makes JavaScript Itself More Fun
- -- Because MooTools focuses on making the JavaScript API itself more stable and coherent, it is focused less on giving you an interface that "changes the way you write JavaScript" and more on making JavaScript as a whole less frustrating; MooTools is an extension to the JavaScript language. MooTools tries to make JavaScript the way it is meant to be. A significant portion of the core library is spent on augmenting Function, String, Array, Number, Element and other prototypes. The other big thing it offers is a function called Class. -
-- Now, Class looks to many people like it's trying to recreate a more classical inheritance model that one might find in Java or C++, but that's not the case. What Class does is make the prototypal inheritance model of JavaScript easier for you and me to access and take advantage of. I'll note that these concepts are not unique to MooTools (other frameworks offer similar functionality), but both of these concepts are not present in jQuery. jQuery does not offer an inheritance system nor does it offer any enhancements to native objects (Function, String, etc). This is not a deficiency of jQuery as the authors of jQuery could easily offer these things. Rather, they have designed a toolkit with a different goal in mind. Where MooTools aims to make JavaScript more fun, jQuery aims to make the DOM more fun and its designers have chosen to limit their scope to that task. -
- - -jQuery Makes the DOM More Fun
- -- And this is why jQuery is more accessible. It doesn't ask that you learn JavaScript inside and out. It doesn't throw you into the deep end with prototypal inheritance, binding, "this", and native prototypes. When you get started with jQuery in its official tutorial, this is the first jQuery code example you find: -
- +// У этого ниндзи есть катана +// У этого ниндзи есть метательные звездочки +// У этого ниндзи есть супер техника ударов ладонями, взрывающая сердца + ++ В примере выше мы привязываем ниндзю (который "this" внутри метода logInventory) к методу, + который мы передаем массиву, так что мы можем обращаться к свойству log у ниндзи. Если бы мы этого + не сделали, "this" был бы объектом window. +
++ Это только пара примеров силы и выразительности языка JavaScript — наследования, ссылок на самих себя + и связывания, а также эффективного использования свойств в прототипах. Плохие новости в том, что + чистый JavaScript не предоставляет удобных возможностей работать со всеми этими вещами, и тогда на + сцену выходит MooTools. Он превращает эти подходы в простые и приятные в использовании. В итоге + вы пишете более абстрактный код, и, по большому счету, это хорошо. Научиться использовать эти подходы + правильно требует усилий, но, в конечном счете, ваш код с большей вероятностью можно будет повторно + использовать и гораздо легче поддерживать. Поговорим об этих двух вещах более подробно. +
+ + +MooTools делает Javascript более крутым
++ Поскольку MooTools стремится превратить API JavaScript в более стабильный и логичный, + он меньше фокусируется на том, чтобы предоставить вам интерфейс, который "изменит то, как вы обычно пишете + JavaScript", а больше на том, чтобы сделать JavaScript в целом менее мучительным в использовании. + MooTools — это расширение языка JavaScript. Он пытается сделать из JavaScript то, чем он должен + быть. Значительная часть ядра библиотеки посвящена расширению Function, String, Array, Number, + Element и других прототипов. Также, очень важная часть — функция Class. +
++ Class для многих людей выглядит так, как будто мы попытались воссоздать более классическое + наследование, как в Java или C++, но + это не так. + Основная задача Class — сделать модель прототипного наследования более простой + в использовании. Замечу, что этот подход есть не только в MooTools, другие фреймворки предлагают + похожую функциональность, но в jQuery этого нет. jQuery не предлагает ни системы наследования, + ни расширений для обычных объектов (Function, String и т.п.). Это не недостаток jQuery, так как его + авторы легко могли бы добавить такую функциональность, но они разрабатывали библиотеку совершенно + с другой целью. В то время как MooTools стремится сделать JavaScript более крутым, jQuery делает + DOM более крутым, и его разработчики решили ограничить масштаб проекта только этой задачей. +
+ + +jQuery Makes the DOM More Fun
+ ++ And this is why jQuery is more accessible. It doesn't ask that you learn JavaScript inside and out. It doesn't throw you into the deep end with prototypal inheritance, binding, "this", and native prototypes. When you get started with jQuery in its official tutorial, this is the first jQuery code example you find: +
+window.onload = function() { alert("welcome"); }-and here's the third:
+and here's the third:
$(document).ready(function() { $("a").click(function(event) { @@ -461,43 +510,43 @@-jQuery Makes the DOM More Fun
}); });- If you read the MooTools book or the MooTools tutorial (both of which I authored) they start in a much different place. While you can skip ahead and quickly learn about effects and the DOM, if you want to learn MooTools, you have to start with things like Class, and, I'll admit: if you're new to programming, or you just want to get something working on your site without having to learn everything about JavaScript, chances are jQuery is going to look a lot more friendly to you. -
- -- On the other hand, if you want to learn JavaScript itself, MooTools is a great way to do it. It implements a lot of things that JavaScript is going to have (many of the methods on Natives are just the JavaScript 1.8 spec and beyond). If you're used to programming, especially both object oriented and functional programming, MooTools has a lot of design patterns that are very exciting and expressive. -
- - -Anything You Can Do I Can Do Better
- -- If you look at the things jQuery can do, there's often a counterpart in MooTools. If you look at the things MooTools can do, there is often no way to emulate it using jQuery code because of jQuery's focus on the DOM. MooTools has a broader functionality than jQuery, but there's nothing about jQuery that prevents you from doing those things. For example, jQuery does not come with any sort of inheritance system, but that's ok. You could, if you want, use the MooTools Class in conjunction with jQuery if you wanted to (or write your own). There's even an inheritance plug-in for jQuery (I haven't used it, but I assume it offers pretty much the same kind of functionality). -
- -If we look at the example from jQuery above:
- ++ If you read the MooTools book or the MooTools tutorial (both of which I authored) they start in a much different place. While you can skip ahead and quickly learn about effects and the DOM, if you want to learn MooTools, you have to start with things like Class, and, I'll admit: if you're new to programming, or you just want to get something working on your site without having to learn everything about JavaScript, chances are jQuery is going to look a lot more friendly to you. +
+ ++ On the other hand, if you want to learn JavaScript itself, MooTools is a great way to do it. It implements a lot of things that JavaScript is going to have (many of the methods on Natives are just the JavaScript 1.8 spec and beyond). If you're used to programming, especially both object oriented and functional programming, MooTools has a lot of design patterns that are very exciting and expressive. +
+ + +Anything You Can Do I Can Do Better
+ ++ If you look at the things jQuery can do, there's often a counterpart in MooTools. If you look at the things MooTools can do, there is often no way to emulate it using jQuery code because of jQuery's focus on the DOM. MooTools has a broader functionality than jQuery, but there's nothing about jQuery that prevents you from doing those things. For example, jQuery does not come with any sort of inheritance system, but that's ok. You could, if you want, use the MooTools Class in conjunction with jQuery if you wanted to (or write your own). There's even an inheritance plug-in for jQuery (I haven't used it, but I assume it offers pretty much the same kind of functionality). +
+ +If we look at the example from jQuery above:
+$(document).ready(function() { $("a").click(function(event) { alert("Thanks for visiting!"); }); });- -- and we wanted to translate this to MooTools, we'd have: -
+ ++ and we wanted to translate this to MooTools, we'd have: +
window.addEvent('domready', function() { $$('a').addEvent('click', function(event) { alert('Thanks for visiting!'); }); });-- These are very similar no? -
-- Here's a more complex example from jQuery: -
++ These are very similar no? +
++ Here's a more complex example from jQuery: +
$(document).ready(function() { $("#orderedlist li:last").hover(function() { @@ -508,9 +557,9 @@-Anything You Can Do I Can Do Better
}); });- and in MooTools: -
++ and in MooTools: +
window.addEvent('domready',function() { $$('#orderedlist li:last-child').addEvents({ @@ -523,19 +572,19 @@-Anything You Can Do I Can Do Better
}); });- Again, very similar. I'd argue that the MooTools version is more explicit, but also more verbose because of it. It's clear reading the MooTools code that we're adding two events - one for mouse enter and one on mouse leave, while the jQuery version is more concise; its hover method accepts two methods - the first for mouse enter and the second for mouse leave. I personally like the fact that the MooTools code is more legible but that's a very subjective observation. -
- -- I will say that sometimes jQuery can become too esoteric for my taste. The methods don't always make sense to me just looking at them and I find it hard to parse. This is somewhat unfair though, as I am intimately familiar with MooTools, so reading MooTools is easy for me. But one of the things I appreciate about MooTools is how almost all the method and class names really name the thing. Methods are almost always verbs and leave little doubt as to what they do. Every programming language requires you to go to the docs to look up syntax when you write it - I'm not saying that. I'm just saying that I find the API of MooTools to be more coherent and consistent. -
- - -MooTools Lets You Have It Your Way
- -But what if you like the jQuery syntax? One way to illustrate the power of MooTools is to show you how easy it is to change it to suit your tastes. If we wanted to implement the hover method from jQuery in MooTools, we could easily do so:
- ++ Again, very similar. I'd argue that the MooTools version is more explicit, but also more verbose because of it. It's clear reading the MooTools code that we're adding two events - one for mouse enter and one on mouse leave, while the jQuery version is more concise; its hover method accepts two methods - the first for mouse enter and the second for mouse leave. I personally like the fact that the MooTools code is more legible but that's a very subjective observation. +
+ ++ I will say that sometimes jQuery can become too esoteric for my taste. The methods don't always make sense to me just looking at them and I find it hard to parse. This is somewhat unfair though, as I am intimately familiar with MooTools, so reading MooTools is easy for me. But one of the things I appreciate about MooTools is how almost all the method and class names really name the thing. Methods are almost always verbs and leave little doubt as to what they do. Every programming language requires you to go to the docs to look up syntax when you write it - I'm not saying that. I'm just saying that I find the API of MooTools to be more coherent and consistent. +
+ + +MooTools Lets You Have It Your Way
+ +But what if you like the jQuery syntax? One way to illustrate the power of MooTools is to show you how easy it is to change it to suit your tastes. If we wanted to implement the hover method from jQuery in MooTools, we could easily do so:
+Element.implement({ hover : function(enter,leave){ return this.addEvents({ mouseenter : enter, mouseleave : leave }); @@ -551,14 +600,14 @@-MooTools Lets You Have It Your Way
});Indeed, there are MooTools plug-ins that do just that; give you the jQuery syntax for MooTools. MooTools' focus on extensibility means you can implement anything you like. This is something jQuery can't do. MooTools can mimic jQuery if you want it to, but jQuery can't mimic MooTools. If you want to write classes or extend native prototypes or do some of the other things MooTools can, you'll have to write it yourself.
- - -Chaining as a Design Pattern
- -- Let's do another of these. Here's some jQuery (from the jQuery tutorial): -
+Indeed, there are MooTools plug-ins that do just that; give you the jQuery syntax for MooTools. MooTools' focus on extensibility means you can implement anything you like. This is something jQuery can't do. MooTools can mimic jQuery if you want it to, but jQuery can't mimic MooTools. If you want to write classes or extend native prototypes or do some of the other things MooTools can, you'll have to write it yourself.
+ + +Chaining as a Design Pattern
+ ++ Let's do another of these. Here's some jQuery (from the jQuery tutorial): +
$(document).ready(function() { $('#faq').find('dd').hide().end().find('dt').click(function() { @@ -566,12 +615,12 @@-Chaining as a Design Pattern
}); });- This is an example of a syntax that I personally don't prefer. Looking at the code above I am hard pressed to be sure of what it's doing. Most notably I'm curious about what .end does and how does .find, which follows it, relate to what .end does? Now, looking at the docs on jQuery makes it very clear what .end does (it resets to the value of the original selector, in this case #faq). But this seems very odd to me. When I do work with jQuery, I often find myself unsure what a method is going to return to me. Obviously this doesn't bother everyone else as jQuery has a lot of people happily using it, so I'll chalk it up to personal preference again. -
-- Let's look at the above logic as MooTools: -
++ This is an example of a syntax that I personally don't prefer. Looking at the code above I am hard pressed to be sure of what it's doing. Most notably I'm curious about what .end does and how does .find, which follows it, relate to what .end does? Now, looking at the docs on jQuery makes it very clear what .end does (it resets to the value of the original selector, in this case #faq). But this seems very odd to me. When I do work with jQuery, I often find myself unsure what a method is going to return to me. Obviously this doesn't bother everyone else as jQuery has a lot of people happily using it, so I'll chalk it up to personal preference again. +
++ Let's look at the above logic as MooTools: +
window.addEvent('domready', function() { var faq = $('faq'); @@ -583,30 +632,30 @@-Chaining as a Design Pattern
- Again, the MooTools code is a bit more verbose, but also more explicit. Also note that the design pattern here is to store the reference to #faq in a variable, where jQuery uses its .end method to return to it. I'll note that it's possible to write highly chained code with Mootools. For example: -
++ Again, the MooTools code is a bit more verbose, but also more explicit. Also note that the design pattern here is to store the reference to #faq in a variable, where jQuery uses its .end method to return to it. I'll note that it's possible to write highly chained code with Mootools. For example: +
item.getElements('input[type=checkbox]') - .filter(function(box) { - return box.checked != checked; - }) - .set('checked', checked) - .getParent()[(checked) ? 'addClass' : 'removeClass']('checked') - .fireEvent((checked) ? 'check' : 'uncheck');- -- But really, writing code like this - lots of logic in a domready statement - with either framework, I'd argue, is itself a bad practice. It's far better to encapsulate your logic into reusable chunks. -
- - -Reusing Code with jQuery
- -- It's very tempting when you're working on a web project to write code this way. Just add some logic on the page that selects the DOM elements and "sets them up" by hiding some, altering others, and adding event listeners for click or mouseover. Developing code this way is very efficient, very fast. The problem with writing all your logic in domready statements is that you end up with a lot of code that does the same thing in different places. If we take the FAQ pattern above we could easily apply the same logic elsewhere on a different page with any list of terms and definitions. Are we going to repeat the same logic every time we find this pattern? -
-- A simple way to make it reusable is to wrap the logic in a function and pass in arguments. Here's what that might look like in jQuery: -
+ .filter(function(box) { + return box.checked != checked; + }) + .set('checked', checked) + .getParent()[(checked) ? 'addClass' : 'removeClass']('checked') + .fireEvent((checked) ? 'check' : 'uncheck'); + ++ But really, writing code like this - lots of logic in a domready statement - with either framework, I'd argue, is itself a bad practice. It's far better to encapsulate your logic into reusable chunks. +
+ + +Reusing Code with jQuery
+ ++ It's very tempting when you're working on a web project to write code this way. Just add some logic on the page that selects the DOM elements and "sets them up" by hiding some, altering others, and adding event listeners for click or mouseover. Developing code this way is very efficient, very fast. The problem with writing all your logic in domready statements is that you end up with a lot of code that does the same thing in different places. If we take the FAQ pattern above we could easily apply the same logic elsewhere on a different page with any list of terms and definitions. Are we going to repeat the same logic every time we find this pattern? +
++ A simple way to make it reusable is to wrap the logic in a function and pass in arguments. Here's what that might look like in jQuery: +
function faq(container, terms, definitions) { $(container).find(terms).hide().end().find(definitions).click(function() { @@ -617,55 +666,55 @@-Reusing Code with jQuery
faq('#faq', 'dd', 'dt'); });- This is much better for two really big and important reasons: -
--
-- - If tomorrow we need to change how these lists work (maybe we want to add click tracking logic so we can measure it in our web logs or maybe we want to fetch the definitions via ajax) we can just change our main faq method and everywhere we use it just gets updated. Or if there's a new version of jQuery released that changes the way things work, we can just go update our one method instead of a dozen copies everywhere. I call this keeping a small footprint in my application. By keeping the points where my application touches my more generic code as small as possible, it makes it easier for me to fix bugs, upgrade frameworks, add features, or alter functionality. -
-- - The second reason is that it's less code. By reusing the same method over and over again, I don't repeat myself and this is valuable in any programming environment. It also makes the code my visitors have to download smaller. -
-- jQuery actually has a slightly more refined system for writing reusable "widgets" like these. Rather than encourage you to drop them into functions like the above example (which is really rather crude) it encourages you to write jQuery plug-ins. Here's what that would look like: +
+ This is much better for two really big and important reasons: +
++
+- + If tomorrow we need to change how these lists work (maybe we want to add click tracking logic so we can measure it in our web logs or maybe we want to fetch the definitions via ajax) we can just change our main faq method and everywhere we use it just gets updated. Or if there's a new version of jQuery released that changes the way things work, we can just go update our one method instead of a dozen copies everywhere. I call this keeping a small footprint in my application. By keeping the points where my application touches my more generic code as small as possible, it makes it easier for me to fix bugs, upgrade frameworks, add features, or alter functionality. +
+- + The second reason is that it's less code. By reusing the same method over and over again, I don't repeat myself and this is valuable in any programming environment. It also makes the code my visitors have to download smaller. +
++ jQuery actually has a slightly more refined system for writing reusable "widgets" like these. Rather than encourage you to drop them into functions like the above example (which is really rather crude) it encourages you to write jQuery plug-ins. Here's what that would look like:
jQuery.fn.faq = function(options) { var settings = jQuery.extend({ terms: 'dt', definitions: 'dd' }, options); - //"this" is the current context; in this case, the elements we want to turn into faq layouts + //"this" is the current context; in this case, the elements we want to turn into faq layouts $(this).find(settings.terms).hide().end().find(settings.definitions).click(function() { $(this).next().slideToggle(); }); return this; };- - which you would use thusly: - -$('#faq').faq();+ + which you would use thusly: + +$('#faq').faq();-- But looking at the example above, there's not much difference between declaring our faq function this way vs. declaring it as a stand alone function. Granted, it's not in the global namespace, but we could have just as easily added it to a namespace of our own. By attaching it to jQuery we can chain it with other jquery methods. The other benefit is that the "this" inside our function is the current context of whatever is in the jQuery chain at that moment. By using this pattern for plug-ins we're able to make our plug-in look like it's part of jQuery, but other than that, our plug-in is basically a single function that takes the current jQuery context, does stuff to it, and then returns the context for the next item in the chain. There's not a lot of complexity here, which makes it easy for anyone to write jQuery plug-ins - they're just single functions. -
++ But looking at the example above, there's not much difference between declaring our faq function this way vs. declaring it as a stand alone function. Granted, it's not in the global namespace, but we could have just as easily added it to a namespace of our own. By attaching it to jQuery we can chain it with other jquery methods. The other benefit is that the "this" inside our function is the current context of whatever is in the jQuery chain at that moment. By using this pattern for plug-ins we're able to make our plug-in look like it's part of jQuery, but other than that, our plug-in is basically a single function that takes the current jQuery context, does stuff to it, and then returns the context for the next item in the chain. There's not a lot of complexity here, which makes it easy for anyone to write jQuery plug-ins - they're just single functions. +
-- Note that it is possible to write more complex plugins with jQuery with methods and state. This kind of pattern is supported with the jQuery UI plugin system and doesn't use the same mechanism as the basic plugin (like our faq example). Instead, you attach an object with methods and properties to the jQuery object (i.e. $.ui.tabs). There's a shortcut to invoke this object ($(selector).tabs()) so that you can continue chaining as with the faq plugin. But because it doesn't return a reference to the tabs object created for the items in your selector, you're forced to call that selector again to invoke methods on it. Instead of calling myTabInstance.add(url, label, index) you must execute the selector again and call your function by name (as a string): $(selector).tabs('add', url, label, index);. This means you're running your selector twice (unless you store it in a variable somewhere), and that you don't ever have a pointer to the "add" method that you can do things like bind or delay. This post is focused on the MooTools and jQuery cores, and while jQuery's UI system does provide this functionality, it's not something that comes with jQuery by default. -
++ Note that it is possible to write more complex plugins with jQuery with methods and state. This kind of pattern is supported with the jQuery UI plugin system and doesn't use the same mechanism as the basic plugin (like our faq example). Instead, you attach an object with methods and properties to the jQuery object (i.e. $.ui.tabs). There's a shortcut to invoke this object ($(selector).tabs()) so that you can continue chaining as with the faq plugin. But because it doesn't return a reference to the tabs object created for the items in your selector, you're forced to call that selector again to invoke methods on it. Instead of calling myTabInstance.add(url, label, index) you must execute the selector again and call your function by name (as a string): $(selector).tabs('add', url, label, index);. This means you're running your selector twice (unless you store it in a variable somewhere), and that you don't ever have a pointer to the "add" method that you can do things like bind or delay. This post is focused on the MooTools and jQuery cores, and while jQuery's UI system does provide this functionality, it's not something that comes with jQuery by default. +
- -Reusing Code with MooTools
+ +Reusing Code with MooTools
-- In MooTools when you want to define a pattern, you're more likely to use either a Class or implement a method into a native object (into String, for example). -
- -- Rather than give you an almost completely different language from JavaScript's native style, MooTools attempts to walk the middle ground between defining its own custom syntax and extending JavaScript's own design patterns. One of the ways it does this is by extending the prototypes of the native objects in the language and in the DOM. This means that if you needed a method to trim a string, MooTools encourages you to add that method to String itself (note that String.trim is already in MooTools; you don't need to add this yourself): -
++ In MooTools when you want to define a pattern, you're more likely to use either a Class or implement a method into a native object (into String, for example). +
+ ++ Rather than give you an almost completely different language from JavaScript's native style, MooTools attempts to walk the middle ground between defining its own custom syntax and extending JavaScript's own design patterns. One of the ways it does this is by extending the prototypes of the native objects in the language and in the DOM. This means that if you needed a method to trim a string, MooTools encourages you to add that method to String itself (note that String.trim is already in MooTools; you don't need to add this yourself): +
String.implement({ trim: function() { @@ -673,50 +722,50 @@-Reusing Code with MooTools
} });- This means you can just execute " no more spaces on the end! ".trim() and get back "no more spaces on the end!". Some would say that implementing properties into native prototypes is inappropriate. It's the reason why MooTools and Prototype.js can't play well with each other - any framework that manipulates prototypes of natives doesn't play well with any other framework that does the same. If I define String.prototype.foo() and another library on the same page defines it, too, which ever one comes last wins. In a way, this is similar to the problem we face with the global window namespace. This is how JavaScript works. This is how JavaScript 1.8 has added so many features. It adds them to the prototypes. -
-- The MooTools developers include a robust framework that is easy for you to extend with your own functionality with the intention that people who include the framework in the page are going to use it, not some other framework. It's actually kind of rude to ask users to download two frameworks. The only reason to include two frameworks is because you want to use plug-ins from both, and in the minds of the MooTools authors (myself included), if you want a plug-in that isn't available with the framework of your choice, it's more appropriate for you to spend the time porting it to your environment than to ask your users to download another framework. -
-- Once you learn how JavaScript works and see the power of extending native objects, a whole new level of programming opens up. You can write plug-ins that alter Elements or Dates or Functions. While some might argue that adding methods to natives this way is a kind of pollution, I'd argue that this is how JavaScript is meant to be used. It is a design feature of the language. By attaching methods to natives you allow your code to be concise and compartmentalized. jQuery does this too, but limits its prototype enhancements to the jQuery object. -
- -- While you can easily chain multiple method calls on the jQuery object, on any other type of object you have to use - generics. For example, in jQuery if you want to trim a string and then iterate over each line, you would have to write: -
- -$.each( $.trim( $('span.something').html() ).split("\n"), function(i, line){alert(line);});- -But because MooTools modifies prototypes, you can do this:
- -$('span.something').get('html').trim().split("\n").each(function(line){alert(line);});- -- Taking a look at this makes it extremely clear how powerful it is to - modify prototypes. Chaining on DOM elements isn't the only place chaining is - useful. MooTools lets you chain methods on any object, including - running a method on multiple elements at once. -
- -- The key here is that at the heart of the MooTools framework is the notion that it's there to let you program what you want. If there's functionality that's not in the core, you can extend it and add your own. The job of the core is not to provide everyone with every bit of functionality that they could ever want, but to provide the tools that allow you write the things that you want. A big part of that is making it easier to extend the prototypes of natives, and take advantage of prototypal inheritance. You can do these things with vanilla JavaScript but MooTools makes it easier and more pleasant. - -
- - - -MooTools and Inheritance
- -- Despite its name, the MooTools Class function is not really a class nor does it create them. It has design patterns that might remind you of classes in a more traditional programming language, but really Class is all about objects and prototypal inheritance. (Unfortunately, using words like "class" are the most convenient way to describe these things, so for the purposes of this article, when I refer to "classes" I'm referring to functions that return objects - which I'll call "instances" - that inherit from a prototype.) -
-- To make a class, you pass an object to the Class constructor like this: -
- ++ This means you can just execute " no more spaces on the end! ".trim() and get back "no more spaces on the end!". Some would say that implementing properties into native prototypes is inappropriate. It's the reason why MooTools and Prototype.js can't play well with each other - any framework that manipulates prototypes of natives doesn't play well with any other framework that does the same. If I define String.prototype.foo() and another library on the same page defines it, too, which ever one comes last wins. In a way, this is similar to the problem we face with the global window namespace. This is how JavaScript works. This is how JavaScript 1.8 has added so many features. It adds them to the prototypes. +
++ The MooTools developers include a robust framework that is easy for you to extend with your own functionality with the intention that people who include the framework in the page are going to use it, not some other framework. It's actually kind of rude to ask users to download two frameworks. The only reason to include two frameworks is because you want to use plug-ins from both, and in the minds of the MooTools authors (myself included), if you want a plug-in that isn't available with the framework of your choice, it's more appropriate for you to spend the time porting it to your environment than to ask your users to download another framework. +
++ Once you learn how JavaScript works and see the power of extending native objects, a whole new level of programming opens up. You can write plug-ins that alter Elements or Dates or Functions. While some might argue that adding methods to natives this way is a kind of pollution, I'd argue that this is how JavaScript is meant to be used. It is a design feature of the language. By attaching methods to natives you allow your code to be concise and compartmentalized. jQuery does this too, but limits its prototype enhancements to the jQuery object. +
+ ++ While you can easily chain multiple method calls on the jQuery object, on any other type of object you have to use + generics. For example, in jQuery if you want to trim a string and then iterate over each line, you would have to write: +
+ +$.each( $.trim( $('span.something').html() ).split("\n"), function(i, line){alert(line);});+ +But because MooTools modifies prototypes, you can do this:
+ +$('span.something').get('html').trim().split("\n").each(function(line){alert(line);});+ ++ Taking a look at this makes it extremely clear how powerful it is to + modify prototypes. Chaining on DOM elements isn't the only place chaining is + useful. MooTools lets you chain methods on any object, including + running a method on multiple elements at once. +
+ ++ The key here is that at the heart of the MooTools framework is the notion that it's there to let you program what you want. If there's functionality that's not in the core, you can extend it and add your own. The job of the core is not to provide everyone with every bit of functionality that they could ever want, but to provide the tools that allow you write the things that you want. A big part of that is making it easier to extend the prototypes of natives, and take advantage of prototypal inheritance. You can do these things with vanilla JavaScript but MooTools makes it easier and more pleasant. + +
+ + + +MooTools and Inheritance
+ ++ Despite its name, the MooTools Class function is not really a class nor does it create them. It has design patterns that might remind you of classes in a more traditional programming language, but really Class is all about objects and prototypal inheritance. (Unfortunately, using words like "class" are the most convenient way to describe these things, so for the purposes of this article, when I refer to "classes" I'm referring to functions that return objects - which I'll call "instances" - that inherit from a prototype.) +
++ To make a class, you pass an object to the Class constructor like this: +
+var Human = new Class({ initialize: function(name, age) { this.name = name; @@ -728,57 +777,57 @@- -MooTools and Inheritance
this.energy = this.energy + 1; //same as this.energy++ } });- You pass Class an object (above, we pass an object with members like "isAlive" and "eat") and this object becomes the prototype of every instance of that class. To create an instance, you call it like this: -
+ ++ You pass Class an object (above, we pass an object with members like "isAlive" and "eat") and this object becomes the prototype of every instance of that class. To create an instance, you call it like this: +
var bob = new Human("bob", 20); //bob's name is "bob" and he's 20 years old.-- Now we have an instance of Human. bob has the properties of the object we defined when we created our Human class. But the important thing is that bob has these properties through inheritance. When we reference bob.eat, bob doesn't really have this property. JavaScript looks at bob and he doesn't have an eat method, so it looks up the inheritance chain and finds it on the object we passed when we created the Human class. This is true for energy, too. At first glance this looks potentially bad; we don't want all the humans we create to gain energy every time that bob eats. The important thing to recognize is that the first time we assign a value to bob's energy, we assign him his own value and we no longer look at the prototype for it. So the first time bob eats, he gets his own definition for energy (set to 2). -
-bob.eat(); //bob.energy == 2-- Note that bob's name and age are unique to him; these are assigned to him when the class is initialized in the initialize method. -
-- This whole pattern may seem a little odd to you, but the value here is that we can define functionality for a pattern and create instances of that pattern every time we need it. Each instance maintains its own state. So if we create another instance each one is independent of the other, but inherits from the same base pattern: -
- ++ Now we have an instance of Human. bob has the properties of the object we defined when we created our Human class. But the important thing is that bob has these properties through inheritance. When we reference bob.eat, bob doesn't really have this property. JavaScript looks at bob and he doesn't have an eat method, so it looks up the inheritance chain and finds it on the object we passed when we created the Human class. This is true for energy, too. At first glance this looks potentially bad; we don't want all the humans we create to gain energy every time that bob eats. The important thing to recognize is that the first time we assign a value to bob's energy, we assign him his own value and we no longer look at the prototype for it. So the first time bob eats, he gets his own definition for energy (set to 2). +
+bob.eat(); //bob.energy == 2++ Note that bob's name and age are unique to him; these are assigned to him when the class is initialized in the initialize method. +
++ This whole pattern may seem a little odd to you, but the value here is that we can define functionality for a pattern and create instances of that pattern every time we need it. Each instance maintains its own state. So if we create another instance each one is independent of the other, but inherits from the same base pattern: +
+var Alice = new Human(); //alice.energy == 1 //bob.energy == 2- -- Where things get really interesting is when we want to augment this behavior. -
- - -Extending and Implementing Classes
- -- Let's revisit our jQuery faq plug-in. What would happen if we wanted to add more functionality to that plug-in. What if we wanted to make an ajax version that fetched the answers to the questions from the server? Let's imagine that the faq plug-in was authored by someone else and we want to add more to it without altering it in any way (we don't want to fork it). -
-- Our only real choices are to either duplicate the faq plug-in's logic entirely (remember, it's a single function), essentially forking it, or we can invoke it and then add more logic to it. Given a choice, the latter seems to save us the most trouble. It would look something like this: -
+ ++ Where things get really interesting is when we want to augment this behavior. +
+ + +Extending and Implementing Classes
+ ++ Let's revisit our jQuery faq plug-in. What would happen if we wanted to add more functionality to that plug-in. What if we wanted to make an ajax version that fetched the answers to the questions from the server? Let's imagine that the faq plug-in was authored by someone else and we want to add more to it without altering it in any way (we don't want to fork it). +
++ Our only real choices are to either duplicate the faq plug-in's logic entirely (remember, it's a single function), essentially forking it, or we can invoke it and then add more logic to it. Given a choice, the latter seems to save us the most trouble. It would look something like this: +
jQuery.fn.ajaxFaq = function(options) { var settings = jQuery.extend({ - //some ajax specific options like the url to request terms from + //some ajax specific options like the url to request terms from url: '/getfaq.php' definitions: 'dd' }, options); - //"this" is the current context; in this case, the elements we want to turn into faq layouts + //"this" is the current context; in this case, the elements we want to turn into faq layouts $(this).find(settings.definitions).click(function() { $(this).load(.....); //the logic to load the content from the term }); this.faq(); //call our original faq plug-in });-- This has some down sides. First of all, our faq class is going to repeat our selector for the definitions, which might be expensive; there's no way to store the retrieved definitions and pass it on for the second time they are needed. Secondly, we can't add our ajax logic into the middle of the faq plug-in's own logic for displaying the definition. The original plug-in called slideToggle which expands the definition using an effect. This is problematic because this effect is going to go off before our ajax finishes loading. There's no real solution here unless we just duplicate the entire faq plug-in. -
-- Now let's consider our MooTools Human class. It has properties like isAlive and energy and it has a method called eat. What if we wanted to make a new version of Human that had additional properties? With MooTools, we extend the class: -
++ This has some down sides. First of all, our faq class is going to repeat our selector for the definitions, which might be expensive; there's no way to store the retrieved definitions and pass it on for the second time they are needed. Secondly, we can't add our ajax logic into the middle of the faq plug-in's own logic for displaying the definition. The original plug-in called slideToggle which expands the definition using an effect. This is problematic because this effect is going to go off before our ajax finishes loading. There's no real solution here unless we just duplicate the entire faq plug-in. +
++ Now let's consider our MooTools Human class. It has properties like isAlive and energy and it has a method called eat. What if we wanted to make a new version of Human that had additional properties? With MooTools, we extend the class: +
var Ninja = new Class({ Extends: Human, initialize: function(name, age, side) { @@ -791,9 +840,9 @@-Extending and Implementing Classes
target.isAlive = false; } });- You can see that we've added a lot of functionality here into a subclass. This subclass has all these properties that are unique to Ninjas. Ninjas start off with an initial energy value of 100. Ninjas get a side. They also get an attack method that lets them kill other Humans, but it costs the Ninja energy. -
++ You can see that we've added a lot of functionality here into a subclass. This subclass has all these properties that are unique to Ninjas. Ninjas start off with an initial energy value of 100. Ninjas get a side. They also get an attack method that lets them kill other Humans, but it costs the Ninja energy. +
var bob = new Human('Bob', 25); var blackNinja = new Ninja('Nin Tendo', 'unknown', 'evil'); @@ -802,15 +851,15 @@-Extending and Implementing Classes
blackNinja.attack(bob); //bob never had a chance- Picking this apart a bit, there are some interesting things to consider here. Note that we have an initialize method in the Ninja class. This would appear to overwrite the initialize method in the Human class, but we can still access it by calling this.parent, passing along the arguments that the parent class's initialize expects. Further, we can control when our logic occurs; before or after the call to the parent. We can assign new values to properties (like the energy value) and we can define new functionality. Imagine if we could do this with our faq plug-in for jQuery. We could load our ajax and THEN slide open the value. -
-- MooTools has another pattern called a Mixin. Unlike the parent to - child relationship that is defined by extending one class into a - subclass, you can also define classes that are mixed into other - classes to imbue them with their properties. Here's an example: -
++ Picking this apart a bit, there are some interesting things to consider here. Note that we have an initialize method in the Ninja class. This would appear to overwrite the initialize method in the Human class, but we can still access it by calling this.parent, passing along the arguments that the parent class's initialize expects. Further, we can control when our logic occurs; before or after the call to the parent. We can assign new values to properties (like the energy value) and we can define new functionality. Imagine if we could do this with our faq plug-in for jQuery. We could load our ajax and THEN slide open the value. +
++ MooTools has another pattern called a Mixin. Unlike the parent to + child relationship that is defined by extending one class into a + subclass, you can also define classes that are mixed into other + classes to imbue them with their properties. Here's an example: +
var Warrior = new Class({ energy: 100, @@ -822,9 +871,9 @@-Extending and Implementing Classes
} });- Here we've broken the qualities that make a Ninja different from a Human and put them in a class of their own. This lets us reuse this code outside of Ninja. We could then imbue our Ninja class with the qualities of a warrior like so: -
++ Here we've broken the qualities that make a Ninja different from a Human and put them in a class of their own. This lets us reuse this code outside of Ninja. We could then imbue our Ninja class with the qualities of a warrior like so: +
var Ninja = new Class({ Extends: Human, @@ -834,10 +883,10 @@- -Extending and Implementing Classes
this.parent(name, age); } });- Ninja still works as it did before, but Warrior is at our disposal to reuse: -
+ ++ Ninja still works as it did before, but Warrior is at our disposal to reuse: +
var Samurai = new Class({ Extends: Human, @@ -845,166 +894,166 @@-Extending and Implementing Classes
side: 'good' });- Now we have a Samurai class and a Ninja class. But look at how little code both Ninja and Samurai took to define. Both of them are similar in that they are humans with warrior qualities, but they are different in that samurais are always, always good, while ninjas have shifting allegiances. By spending the time to write a Human class and a Warrior class, we're able to have three different classes with no repetition of code while maintaining a very granular level of control over when methods are called and how they relate to each other. Each instance we create has its own state and the code itself is very legible. -
- -- Now that you have an overview of how classes work in MooTools, let's look at our faq class that we wrote in jQuery and write it as we would in MooTools and then extend it to add Ajax to it just as we did with jQuery. -
++ Now we have a Samurai class and a Ninja class. But look at how little code both Ninja and Samurai took to define. Both of them are similar in that they are humans with warrior qualities, but they are different in that samurais are always, always good, while ninjas have shifting allegiances. By spending the time to write a Human class and a Warrior class, we're able to have three different classes with no repetition of code while maintaining a very granular level of control over when methods are called and how they relate to each other. Each instance we create has its own state and the code itself is very legible. +
+ ++ Now that you have an overview of how classes work in MooTools, let's look at our faq class that we wrote in jQuery and write it as we would in MooTools and then extend it to add Ajax to it just as we did with jQuery. +
var FAQ = new Class({ - //Options is another class provided by MooTools - Implements: Options, - //these are the default options - options: { - terms: 'dt', - definitions: 'dd' - }, - initialize: function(container, options) { - //we store a reference to our container - this.container = $(container); - //setOptions is a method provided by the Options mixin - //it merges the options passed in with the defaults - this.setOptions(options); - //we store the terms and definitions - this.terms = this.container.getElements(this.options.terms); - this.definitions = this.container.getElements(this.options.definitions); - //we call our attach method - //by breaking this into its own method - //it makes our class easier to extend - this.attach(); - }, - attach: function(){ - //loop through the terms - this.terms.each(function(term, index) { - //add a click event to each one - term.addEvent('click', function(){ - //that calls our toggle method for - //the current index - this.toggle(index); - }, this); - }, this); - }, - toggle: function(index){ - //toggle open the definition for the given index - this.definitions[index].slide('toggle'); - } + //Options is another class provided by MooTools + Implements: Options, + //these are the default options + options: { + terms: 'dt', + definitions: 'dd' + }, + initialize: function(container, options) { + //we store a reference to our container + this.container = $(container); + //setOptions is a method provided by the Options mixin + //it merges the options passed in with the defaults + this.setOptions(options); + //we store the terms and definitions + this.terms = this.container.getElements(this.options.terms); + this.definitions = this.container.getElements(this.options.definitions); + //we call our attach method + //by breaking this into its own method + //it makes our class easier to extend + this.attach(); + }, + attach: function(){ + //loop through the terms + this.terms.each(function(term, index) { + //add a click event to each one + term.addEvent('click', function(){ + //that calls our toggle method for + //the current index + this.toggle(index); + }, this); + }, this); + }, + toggle: function(index){ + //toggle open the definition for the given index + this.definitions[index].slide('toggle'); + } });-- Woah. That's a lot of code. Even if we remove all the comments it's still two dozen lines long. I already illustrated above that we could build this plug-in with roughly the same amount of code as the jQuery version. So why is this one so much longer? Well, we've made it much more flexible. To use the class, we just call the constructor, like this: -
++ Woah. That's a lot of code. Even if we remove all the comments it's still two dozen lines long. I already illustrated above that we could build this plug-in with roughly the same amount of code as the jQuery version. So why is this one so much longer? Well, we've made it much more flexible. To use the class, we just call the constructor, like this: +
var myFAQ = new FAQ(myContainer); //and now we can call methods on it if we want: myFAQ.toggle(2); //toggle the 3rd element-- We can access methods and properties of the instance. But what about our ajax functionality? The problem with our ajax extension to the jQuery version was that we couldn't delay the opening of the definition until after it loaded. We don't have that problem with our MooTools version: - -
++ We can access methods and properties of the instance. But what about our ajax functionality? The problem with our ajax extension to the jQuery version was that we couldn't delay the opening of the definition until after it loaded. We don't have that problem with our MooTools version: + +
FAQ.Ajax = new Class({ - //this class inherits the properties of FAQ - Extends: FAQ, - //it also gets a new option in addition to the other defaults - //this one for url, that we're going to append the index of the - //term to; in reality we might make this more robust, but for - //this example it serves the purpose - options: { - url: null; - }, - //we're going to cache the results, so if a section is opened - //twice, we won't hit the server for the data - indexesLoaded: [], - toggle: function(index){ - //if we've already loaded the definition - if (this.indexesLoaded[index]) { - //just call the previous version of toggle - this.parent(index); - } else { - //otherwise, request the data from the server - new Request.HTML({ - update: this.definitions[index], - url: this.options.url + index, - //and when the data is loaded, expand the definition - onComplete: function(){ - this.indexesLoaded[index] = true; - this.definitions[index].slide('toggle'); - }.bind(this) - }).send(); - } - } + //this class inherits the properties of FAQ + Extends: FAQ, + //it also gets a new option in addition to the other defaults + //this one for url, that we're going to append the index of the + //term to; in reality we might make this more robust, but for + //this example it serves the purpose + options: { + url: null; + }, + //we're going to cache the results, so if a section is opened + //twice, we won't hit the server for the data + indexesLoaded: [], + toggle: function(index){ + //if we've already loaded the definition + if (this.indexesLoaded[index]) { + //just call the previous version of toggle + this.parent(index); + } else { + //otherwise, request the data from the server + new Request.HTML({ + update: this.definitions[index], + url: this.options.url + index, + //and when the data is loaded, expand the definition + onComplete: function(){ + this.indexesLoaded[index] = true; + this.definitions[index].slide('toggle'); + }.bind(this) + }).send(); + } + } });-- Now we have a version of our FAQ class that allows us to get the definitions from the server. Note that we were able to integrate the new logic in a way that doesn't expand the definition until after the content comes back from the server (which we couldn't do with the jQuery version). Also note that we really only had to describe the new functionality (the ajax) and little else. This extensibility makes it possible for you to create families of plug-ins that offer different shades of functionality. It also means that you can use someone else's plug-in and alter just the bits that you to be want different if you need to (without forking it). This helps explain why, for any given design pattern - a date picker, a tab interface, etc, that you typically only find a few plug-ins for MooTools. Most of the plug-ins you get either solve your problem or, if not, you can just extend them to add the things you need. - -
- -- As I illustrated earlier, it's possible to write complex jQuery widgets with methods and state. Most of the code you write when doing this is vanilla JavaScript when you need to express logic that isn't related to the DOM. But jQuery's model doesn't offer a system for extending these instances into subclasses. Nor does it help you with mixins that can be reused easily. Finally, jQuery's plugins are always attached to DOM elements. If you wanted to write a class that, say, processed URLs, there's no stateful system for such a thing unless you write it yourself. -
- - -Decision Time
- -- jQuery focuses on expressiveness, quick and easy coding, and the DOM while MooTools focuses on extension, inheritance, legibility, reuse, and maintainability. If you put those two things on opposite sides of a scale, the jQuery side translates into something with which it's easy to get started and see quick results but (in my experience) can turn into code that's harder to reuse and maintain (but really that's up to you; it's not jQuery's problem, per se), while the MooTools side takes longer to learn and requires you to write more code upfront before you see results, but afterwards is more reusable and more maintainable. -
-- Further, the MooTools core does not contain every feature you can imagine and neither does the jQuery core. Both frameworks keep their cores rather lean, leaving it to you and others to write plug-ins and extensions. Their job is not to give you every feature you could want but to give you the tools so that you can implement anything you can imagine. This is the power of JavaScript, and of JavaScript frameworks in general, and both frameworks excel at it. MooTools takes a more holistic approach and gives you tools to write anything you can imagine beyond the scope of the DOM, but pays the price by having a steeper learning curve. MooTools' extensible and holistic approach gives you a superset of jQuery's features, but jQuery's focus on a slick DOM API doesn't preclude you from using the native inheritance methods of JavaScript or from using a class system like MooTools if you want it. -
-- This is why I say that both frameworks are excellent choices. My effort here has been to highlight the differences in philosophies between the two codebases and highlight their advantages and disadvantages. I doubt I've been successful in keeping my preference for MooTools completely in check, but hopefully this has been helpful. Regardless of which framework you choose to work with, you now know a lot more about both, hopefully. If you have the luxury of time, I strongly recommend implementing a site with each. Then write your own review of them both and maybe your perspective will highlight some things I missed. -
-A history of this document can be viewed on github.
-- -
-
-- About me: I am a MooTools contributor and I blog about JavaScript and other things on my site Clientcide as well as release numerous plug-ins for MooTools. I am the author of MooTools Essentials as well as the MooTools online tutorial. I work at a company in the SF Bay Area called Cloudera. I can be contacted thusly. -
- - -
-A note on comments here: These comments are moderated. No comments will show up until they are approved. Comments that are not productive (i.e. inflammatory, rude, etc) will not be approved. Similarly, "fan" comments won't be approved either - i.e. no "FrameworkX Rulez! It's better than FrameworkY for realz!" are not constructive comments. -
- - - -
+ Now we have a version of our FAQ class that allows us to get the definitions from the server. Note that we were able to integrate the new logic in a way that doesn't expand the definition until after the content comes back from the server (which we couldn't do with the jQuery version). Also note that we really only had to describe the new functionality (the ajax) and little else. This extensibility makes it possible for you to create families of plug-ins that offer different shades of functionality. It also means that you can use someone else's plug-in and alter just the bits that you to be want different if you need to (without forking it). This helps explain why, for any given design pattern - a date picker, a tab interface, etc, that you typically only find a few plug-ins for MooTools. Most of the plug-ins you get either solve your problem or, if not, you can just extend them to add the things you need. + +
+ ++ As I illustrated earlier, it's possible to write complex jQuery widgets with methods and state. Most of the code you write when doing this is vanilla JavaScript when you need to express logic that isn't related to the DOM. But jQuery's model doesn't offer a system for extending these instances into subclasses. Nor does it help you with mixins that can be reused easily. Finally, jQuery's plugins are always attached to DOM elements. If you wanted to write a class that, say, processed URLs, there's no stateful system for such a thing unless you write it yourself. +
+ + ++ jQuery focuses on expressiveness, quick and easy coding, and the DOM while MooTools focuses on extension, inheritance, legibility, reuse, and maintainability. If you put those two things on opposite sides of a scale, the jQuery side translates into something with which it's easy to get started and see quick results but (in my experience) can turn into code that's harder to reuse and maintain (but really that's up to you; it's not jQuery's problem, per se), while the MooTools side takes longer to learn and requires you to write more code upfront before you see results, but afterwards is more reusable and more maintainable. +
++ Further, the MooTools core does not contain every feature you can imagine and neither does the jQuery core. Both frameworks keep their cores rather lean, leaving it to you and others to write plug-ins and extensions. Their job is not to give you every feature you could want but to give you the tools so that you can implement anything you can imagine. This is the power of JavaScript, and of JavaScript frameworks in general, and both frameworks excel at it. MooTools takes a more holistic approach and gives you tools to write anything you can imagine beyond the scope of the DOM, but pays the price by having a steeper learning curve. MooTools' extensible and holistic approach gives you a superset of jQuery's features, but jQuery's focus on a slick DOM API doesn't preclude you from using the native inheritance methods of JavaScript or from using a class system like MooTools if you want it. +
++ This is why I say that both frameworks are excellent choices. My effort here has been to highlight the differences in philosophies between the two codebases and highlight their advantages and disadvantages. I doubt I've been successful in keeping my preference for MooTools completely in check, but hopefully this has been helpful. Regardless of which framework you choose to work with, you now know a lot more about both, hopefully. If you have the luxury of time, I strongly recommend implementing a site with each. Then write your own review of them both and maybe your perspective will highlight some things I missed. +
+A history of this document can be viewed on github.
++ +
++ About me: I am a MooTools contributor and I blog about JavaScript and other things on my site Clientcide as well as release numerous plug-ins for MooTools. I am the author of MooTools Essentials as well as the MooTools online tutorial. I work at a company in the SF Bay Area called Cloudera. I can be contacted thusly. +
+ + +A note on comments here: These comments are moderated. No comments will show up until they are approved. Comments that are not productive (i.e. inflammatory, rude, etc) will not be approved. Similarly, "fan" comments won't be approved either - i.e. no "FrameworkX Rulez! It's better than FrameworkY for realz!" are not constructive comments. +
+ + + +