I would like to make a subclassed jQuery wrapper that has all the methods jQuery has plus some more. I would also like to override some jQuery methods. Here is an example of what I would like to achieve
calendar('.cal').showPopup()
.selectDate(new Date())
.addClass('popup-visible');
alert(calendar.val());
Note that calendar works just like the jQuery object except
- It has some additional methods (showPopup and selectDate)
- It has an overridden method (val)
- When using method chaining, the Calendar object is returned. This means that addClass shouldn't revert back to a jQuery object.
I'll be grateful if someone points me in the right direction开发者_如何学Python. I've been playing with scopes and $.extend and prototypes but can't seem to get anything to work.
Thanks!
Turns out that jQuery 1.5 has a new method called sub :)
According to the documentation, sub
creates a new copy of jQuery whose properties and methods can be modified without affecting the original jQuery object. http://api.jquery.com/jQuery.sub/
This method didn't allow you to subclass a subclass but I found a modified method in their ticket tracker that allowed this:
jQuery.subclass = function(){
function jQuerySubclass( selector, context ) {
return new jQuerySubclass.fn.init( selector, context );
}
jQuery.extend(true, jQuerySubclass, this);
jQuerySubclass.superclass = this;
jQuerySubclass.fn = jQuerySubclass.prototype = this();
jQuerySubclass.fn.constructor = jQuerySubclass;
jQuerySubclass.fn.init = function init( selector, context ) {
if (context && context instanceof jQuery && !(context instanceof jQuerySubclass)){
context = jQuerySubclass(context);
}
return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );
};
jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
var rootjQuerySubclass = jQuerySubclass(document);
return jQuerySubclass;
};
This allows you to do something like this:
var Calendar = jQuery.subclass();
Calendar.create = function() {
var cal = Calendar( /* some html code for building the calendar */ );
// Do some processing like binding events, etc
return cal;
}
Calendar.fn.val = function(value) {
//Calendar's implementation of val
}
The Calendar object will act just like a jQuery object except for those differences above. It will also correctly return an instance of Calendar when I chain methods together. This is neat because
- We can easily build custom widgets without cluttering the jQuery namespace.
- We can provide our own implementations of jQuery methods
- We can make use of jQuery's power with methods like trigger and bind already part of the class
Next, I'm interested in allowing classes to be registered by selector. This way, when you call $('.MyAwesomeCalendar'), you'll get back a Calendar object without having to explicitly call Calendar('.MyAwesomeCalendar').
I'm going to start out by saying that I think you should dig a little further into jQuery's $.fn
plugin method. You can read more about it here:
http://docs.jquery.com/Plugins/Authoring
I would accomplish the above like this:
(function($){
$.fn.calendar = function(){
//do something useful
return this; // necessary for chaining
};
$.fn.calendar.showPopup = function(){
//do something useful
return this; //necessary for chaining
}
)(jQuery);
So, that being said. Your above example would require a similar syntax to return jQuery to your calendar
function, and that will have to return Calendar's this
to allow for chaining. I can't prove this code below but it's a good start:
var Calendar = (function($){
calendar = {
showPopup : function($){
//do something useful
return $; //required for chaining
},
val : function($){
//return your inherent functionality
return $; //required for chaining
}
}
});
var calendar = new Calendar(jQuery);
Like I said, it's ugly and not at all how it should be done.
I'm not a javascript expert - but I believe that's how that is accomplished. I'll welcome any criticism as well.
精彩评论