From d483ce0a9c8b19dafa70be93ca071673b86a65e2 Mon Sep 17 00:00:00 2001 From: Jared Grippe Date: Sat, 9 Oct 2010 17:32:54 -0700 Subject: [PATCH] added jQuery.subclass --- src/core.js | 31 ++++++++++++++++---- test/unit/core.js | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/src/core.js b/src/core.js index 4361577e..0bf0cb4b 100644 --- a/src/core.js +++ b/src/core.js @@ -3,7 +3,7 @@ var jQuery = (function() { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context ); + return new jQuery.fn.init( selector, context, rootjQuery ); }, // Map over jQuery in case of overwrite @@ -78,7 +78,8 @@ var jQuery = function( selector, context ) { class2type = {}; jQuery.fn = jQuery.prototype = { - init: function( selector, context ) { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) @@ -112,6 +113,7 @@ jQuery.fn = jQuery.prototype = { // HANDLE: $(html) -> $(array) if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; doc = (context ? context.ownerDocument || context : document); // If a single string is passed in and it's a single tag @@ -171,7 +173,7 @@ jQuery.fn = jQuery.prototype = { // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { - return jQuery( context ).find( selector ); + return this.constructor( context ).find( selector ); } // HANDLE: $(function) @@ -222,7 +224,7 @@ jQuery.fn = jQuery.prototype = { // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set - var ret = jQuery(); + var ret = this.constructor(); if ( jQuery.isArray( elems ) ) { push.apply( ret, elems ); @@ -287,7 +289,7 @@ jQuery.fn = jQuery.prototype = { }, end: function() { - return this.prevObject || jQuery(null); + return this.prevObject || this.constructor(null); }, // For internal use only. @@ -960,6 +962,25 @@ jQuery.extend({ return { browser: match[1] || "", version: match[2] || "0" }; }, + subclass: function(){ + function jQuerySubclass( selector, context ) { + return new jQuerySubclass.fn.init( selector, context ); + } + jQuerySubclass.superclass = this; + jQuerySubclass.fn = jQuerySubclass.prototype = this(); + jQuerySubclass.fn.constructor = jQuerySubclass; + jQuerySubclass.subclass = this.subclass; + 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; + }, + browser: {} }); diff --git a/test/unit/core.js b/test/unit/core.js index bfb2f1cf..d26e7c56 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -1063,3 +1063,75 @@ test("jQuery.when()", function() { }); } }); + +test("jQuery.subclass", function(){ + expect(378); + + var Subclass = jQuery.subclass(), + SubclassSubclass = Subclass.subclass(), + jQueryDocument = jQuery(document), + selectors, contexts, methods, method, arg, description; + + jQueryDocument.toString = function(){ return 'jQueryDocument'; }; + + Subclass.fn.subclassMethod = function(){}; + SubclassSubclass.fn.subclassSubclassMethod = function(){}; + + selectors = [ + 'body', + 'html, body', + '
' + ] + + methods = [ // all methods that return a new jQuery instance + ['eq', 1], + ['add', document], + ['end'], + ['has'], + ['closest', 'div'], + ['filter', document], + ['find'] + ] + + contexts = [undefined, document, jQueryDocument]; + + jQuery.each(selectors, function(i, selector){ + + jQuery.each(methods, function(){ + method = this[0] + arg = this[1] + + jQuery.each(contexts, function(i, context){ + + description = '("'+selector+'", '+context+').'+method+'('+(arg||'')+')'; + + same( + jQuery(selector, context)[method](arg).subclassMethod, undefined, + 'jQuery'+description+' doesnt have Subclass methods' + ); + same( + jQuery(selector, context)[method](arg).subclassSubclassMethod, undefined, + 'jQuery'+description+' doesnt have SubclassSubclass methods' + ); + same( + Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod, + 'Subclass'+description+' has Subclass methods' + ); + same( + Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined, + 'Subclass'+description+' doesnt have SubclassSubclass methods' + ); + same( + SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod, + 'SubclassSubclass'+description+' has Subclass methods' + ); + same( + SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod, + 'SubclassSubclass'+description+' has SubclassSubclass methods' + ); + + }); + }); + }); + +});