I want method chaining to work, but it seems i'm not getting some concepts.
This:
$(".list").activeJS()
first has to use jQuery to get a HTMLElement nodelist and then it has to call the activeJS() function passing the nodelist.
var activeJS = function(item){
alert(item) //nodelist
}
Now i get a TypeError: $(...).activeJS is not a function error in my console.
Thx,
If you want to create a function callable from a jQuery object, you have to add it to the jQuery prototype object:
jQuery.fn.activeJS = function(item) {
// ... whatever
};
When a function is added to jQuery (which allows for chaining) it is referred to as a plugin and several things must be taken into consideration. For example, is your function itself chainable? Will your function work on a single element or multiple? I would recommend that you research jQuery plugins and build your function as a plugin in jQuery.
Here is an excellent tutorial on building a jQuery plugin that covers concepts such as chaining, passing properties and calling different plugin functions. Take a look at the article and determine if your function truly needs to be a plugin.
It may be better to simply pass jQuery and the selected elements as arguments to your function instead of chaining.
Take a look at this example:
var obj = {
fn: function(){
console.log("fn method");
return this;
},
abc: function(){
console.log("abc method");
return this;
},
oneMore: function(){
console.log("one more method");
return this;
}
};
Here chaining is provided by returning reference to obj Object.
Simply, every time you call a method on that object, you are returning that object - and you can continue calling its methods. This is basic chaining pattern that you can find in jQuery also - slightly modified but the idea is same. Thanks to dynamic nature of javascript we can do this kind of things. Chaining allows coupling of related methods that are connected by common object. This pattern has its roots in functional programming, and javascript is heavily influenced by functional languages (mostly scheme).
But too much chaining can lead to unreadable code as can be seen in lot of jQuery examples.
Related
In Javascript, it's possible to have some kind of inheritance, by using function contructors and their "prototype" attribute (i.e the "parent of future instances"), or more recently Object.create(), to get new objects.
However recently I needed to "override" the Jquery object ("$") for one of my projects, that is to say, provide a similar function, which also has all the fn/extend/... [inherited] attributes of the original "jQuery" factory function.
The goal was to have a "$()" function which always received "window.parent" as the second parameter by default, so that the whole program modified the parent frame and not the iframe in which the program was loaded.
Typically I expected to be able to do something like this:
var oldJQ = $;
$ = function (selector) {
return oldJQ(selector, window.parent);
}
$.__proto__ = oldJQ .__proto__;
$.extend({...}); // must work
Despite numerous attempts, I couldn't get it to work, I always got simple objects instead of real functions when using the "new" keyword, or the inheritance didn't work. I found alternative ways (for example, by copy-pasting all attributes from $ into my new function object), but it seems to me like a horrible way of doing stuffs.
Is there any way to have a new function object which has, as a parent/prototype, the original $ object ?
While functions are objects in javascript, they aren't regular objects. Specifically, they're objects for which inheritance is broken. Functions are not the only such objects in the language, DOM elements are similarly handicapped. That's one reason jQuery is implemented as wrapper around DOM rather than extending the DOM's features via inheritance.
Fortunately, while OOP doesn't work in this case, we can take inspiration from jQuery itself and use FP to do what we need. In other words, while you can't inherit functions, you can wrap it in another function.
For example, if you need a special console.log function for your app that sends logs back to your server you can override it by redefining it:
var log_orig = console.log;
console.log = function () {
ajaxlog([].slice.call(arguments,0).map(function(x){
return JSON.parse(x);
}).join(',');
log_orig.apply(console,arguments);
}
Or if you want a special version of $ that does something extra:
function $$ () {
/*
* do extra stuff
*/
return $.apply(null,arguments);
}
Or if you want to override $ instead if wrapping:
var old$ = $;
function $ () {
/*
* do extra stuff
*/
return old$.apply(null,arguments);
}
Why would you use a jQuery plugin over a traditional javascript function? The only difference I see is you need to pass in a jQuery object into the js function... other that that, I don't see a huge difference, as it seems both can accomplish the same thing in similar steps:
$(document).ready(function () {
$('p').jQuery_greenify();
greenify($('p'));
});
$.fn.jQuery_greenify = function () {
this.css("color", "green");
};
function greenify (el) {
el.css("color", "green");
}
I also find namespacing to be easier with javascript functions:
var mynamespace = {
greenify : function (el) {
el.css("color", "green");
}
}
mynamespace.greenify($('p'));
Usually, usefulness of JQuery functions is in chaining them. Just like you want to call:
string.substring(2, 5).startsWith("lol")
instead of
Util.StartsWith(Util.substring(string, 2, 5), "lol")
It's easier to read that way. In fact, I think that second function might still need a "return this" to be useful?
It may depend on the context - some operations are very much tied to an element or set of elements, while others just make more sense standing on their own - thus, your approach of namespacing would be just fine. It's partially coding style.
A disclaimer - I'm not as experienced with writing JQuery plugins, this is just my general observations based on JS language design.
Always a jQuery object
When using a plugin as you said (it is really an object prototype) You are sure that this will be a jQuery object since you cannot call it without a jQuery object except if you make your way around with .call, .apply, .bind and etc.
Meanwhile, you can pass anything to a function, so the argument may not be a jQuery object and will throw an error.
Readability when chaining
You can chain function with both method, but let be honest, with a jQuery prototype, it is prettier :
$.fn.jQuery_greenify = function () {
return this.css("color", "green");
};
$('div').jQuery_greenify().append(...);
//VS
function greenify (el) {
return el.css("color", "green");
}
greenify($('div')).append(...);
Scope
When adding a function to the prototype, no matter which scope you are, it will be accessible everywhere. That allow you the create a certain closure :
(function(){
$.fn.jQuery_greenify = function () {
return this.css("color", "green");
};
})();
$('div').jQuery_greenify(); //Work
//VS
(function(){
function greenify (el) {
return el.css("color", "green");
}
})();
greenify($('div')); //Undefined is not a function error
The original usefulness of jQuery was to provide a consistent API to things such as DOM manipulation and AJAX - things which [older] browsers implemented very differently. It would take 20+ lines of code to do what can be done with 1 - 2 lines with jQuery. It abstracted away all of the inconsistencies so you could just focus on coding.
Then, John Resig's worst nightmare happened and people now think jQuery is a language, almost separate and independent from Javascript. </rant>
Today, most browsers have adopted standards and you don't have to worry so much about inconsistencies unless you are trying to support < IE9. You can use something like underscore to help take advantage of newer javascript features (with backwards compatability for things which are still inconsistently implemented even in today's browsers).
Regarding plugins, the advantage is having a consistent way to implement reusable code. For example, I kind of disagree with how you created a namespace (not really, but I would have done it differently).
Point is, it's all javascript. Learn javascript. If it's easier and quicker to do it without using a library, by all means do it! Pay attention to the community and try and use techniques which have been adopted by others... even if it occasionally means using a library.
NOTE: If someone puts jQuery under the "languages" section on their resume, throw it in the trash.
Excuse me first. because i don't know this is question is valid or not. i if any one clear my doubt then i am happy.
Basically : what is the different between calling a method like:
object.methodname();
$('#element').methodname();
calling both way is working, but what is the different between, in which criteria make first and second type of methods. is it available in the core javascript as well?
In case if i have a function is it possible to make 2 type of method call always?
Can any one give some good reference to understand correctly?
Thanks in advance.
The first syntax:
object.methodName();
Says to call a function, methodName(), that is defined as a property of object.
The second syntax:
$('#element').methodname();
Says to call a function called $() which (in order for this to work) must return an object and then call methodname() on that returned object.
You said that "calling both way is working," - so presumably you've got some code something like this:
var myObject = $('#element');
myObject.methodname();
This concept of storing the result of the $() function in a variable is commonly called "caching" the jQuery object, and is more efficient if you plan to call a lot of methods on that object because every time you call the jQuery $() function it creates another jQuery object.
"Is it available in the core javascript as well?" Yes, if you implement functions that return objects. That is, JS supports this (it would have to, since jQuery is just a JS library) but it doesn't happen automatically, you have to write appropriate function code. For example:
function getObject() {
return {
myMethod1 : function() { alert("myMethod1"); return this; },
myMethod2 : function() { alert("myMethod2"); return this; }
};
}
getObject().myMethod1().myMethod2();
In my opinion explaining this concept in more depth is beyond the scope of a Stack Overflow answer - you need to read some JavaScript tutorials. MDN's Working With Objects article is a good place to start once you have learned the JS fundamentals (it could be argued that working with objects is a JS fundamental, but obviously I mean even more fundamental stuff than that).
The difference is very subtle.
object.methodname();
This is when JavaScript has the object at hand.
$('#element').methodname();
If you are using jQuery, you are asking jQuery to select the object that has the id of #element. After that you invoke the method on the selected object.
Could someone write down a very simple basic example in javascript to conceptualize (and hopefully make me understand) how the jQuery plugin design pattern is done and how it works?
I'm not interested in how creating plugin for jQuery (so no jQuery code here at all).
I'm interested in a simple explanation (maybe with a bit of Javascript code) to explain how it is done the plugin concept.
Plz do not reply me to go and read jQuery code, I tried, but I it's too complex, otherwise I would have not post a question here.
Thanks!
jQuery has a library of functions stored in an internal object named fn. These are the ones that you can call on every jQuery object.
When you do $("div.someClass") you get a jQuery object containing all <div> elements of that class. Now you can do $("div.someClass").each( someFunction ) to apply someFunction to each of them. This means, that each() is one of the functions stored in fn (a built-in one in this case).
If you extend (add to) the internal fn object, then you automatically make available your custom function to the same syntax. Lets assume you have a function that logs all elements to the console, called log(). You could append this function to $.fn, and then use it as $("div.someClass").log().
Every function appended to the fn object will be called in such a way that inside the function body, the this keyword will point to the jQuery object you've used.
Common practice is to return this at the end of the custom function, so that method chaining does not break: $("div.someClass").log().each( someFunction ).
There are several ways to append functions to the $.fn object, some safer than others. A pretty safe one is to do:
jQuery.fn.extend({
foo: function() {
this.each( function() { console.log(this.tagName); } );
return this;
}
})
Tomalak already posted almost everything You need to know.
There is one last thing that helps jQuery do the trick with the this keyword.
it's amethod called apply()
var somefunction=function(){
alert(this.text);
}
var anObject={text:"hello"};
somefunction.apply(anObject);
//alert "hello" will happen
It really helps in creating abstractions so that framework/plugin users would just use this as intuition tells them, whatever there is inside Your code
It works, as many other js frameworks, using javascript prototype orientation.
For instance you can declare a simple function
var alertHelloWorld = function() {
alert('hello world');
}
And then tie it to an existing object (including DOM nodes)
document.doMyAlert = alertHelloWorld;
If you do this
document.doMyAlert();
The alertHelloWorld function will be executed
You can read more about javascript object prototyping here
Coming from mootools and JAVA, mootools class implementation is a real nice way to structure my code, plus I can have some nice features like extending, implementing and so on. Starting with jquery I found my self writing $.fn plugins that cant use code of other plugins. Plus it seems no good idea to use the plugin structure for complex stuff that hasn't much to do with DOM Elements. Is there a better way then $.fn? What do you recommend to structure my code using jquery.
This is a tough question to answer.
JavaScript's incredible flexibility's downside is that every programmer and his brother-in-law has a different way of doing things.
The downside of pulling in a library for doing "Class" based OOP in JavaScript (Prototype library, Moo, Joose, JS.Class, Base2, etc.) is that you immediately cut down on the number of fellow JavaScript programmers who can read your code.
Obviously, jQuery encourages you to think in terms of "collections." A collection is what you get back from a $() or jQuery() call. John Resig once considered adding a class system to jQuery, but finally decided against it. I think he's said that he's never needed a real "Class" system in JavaScript programming.
For all but the largest JS projects, I'd say forget about a Class system. Leverage JS's incredible object and array system (including literals). Namespace heavily (variables and methods alike).
I've had a lot of luck using arrays of objects for most situations I'd normally use Classes for.
An interesting extension of the jQuery collection concept is in Ariel Flesler's jQuery.Collection plugin here. It lets you treat "normal" data much as you would treat DOM data in jQuery.
I recently started using Underscore.js, which gives you a lot of functional tools to treat your data as collections.
What you generally need are mechanism for code extension and packaging.
For the former, I use the pseudo class-based default oo mechanism, sometimes with a helper function to make inheritance easier:
Function.prototype.derive = (function() {
function Dummy() {}
return function() {
Dummy.prototype = this.prototype;
return new Dummy;
};
})();
function Base() {}
function Sub() {}
Sub.prototype = Base.derive();
The latter can be achieved by namespacing via self-executing functions. It's even possible to fake import statements:
// create package:
var foo = new (function() {
// define package variables:
this.bar = 'baz';
this.spam = 'eggs';
// export package variables:
this.exports = (function(name, obj) {
var acc = [];
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
acc.push(prop + '=' + name + '.' + prop);
}
return 'var ' + acc.join(',') + ';';
})('foo', this);
});
// use package:
(function() {
// import package variables:
eval(foo.exports);
alert(spam);
})();
jQuery isn't really meant to be used for structuring your code. It's meant to be a tool that you use from your other code, not a way of life.
The rest of your code should be written whatever way you like. Just use jQuery when you want to do DOM manipulation, Ajax calls, cross-browser events, etc.
You may want to learn how to use the .prototype property to put some of your code into "classes", so that you can reuse the same code in different places, by just creating a new instantiation, basically.
You can also put code into objects so that you have a unique namespace, so it is easier to share related objects amongst different projects.
Basically you will be structuring your code as you do for straight javascript, but jQuery abstracts out some of the common functionality so you don't have to worry about browser issues, but it is just a helper, it really doesn't provide a framework as much as just making some concepts simpler. For example, rather than using onclick I tend to use .bind('click', ...) but that is if I want to have the potential of more than one event hander on an element.