Bug Tracker

Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#9212 closed feature (wontfix)

jQuery with classes

Reported by: sgehrig@… Owned by:
Priority: low Milestone: 1.7
Component: core Version: 1.6
Keywords: 1.7-discuss Cc:
Blocked by: Blocking:

Description (last modified by scottgonzalez)

Dear jQuery community

I spent the last hours writing a jQuery-like class implementation. It's an adaption from the UI Widget functionalities. It would be a great if something like this would be included into the the jQuery base framework. I've attached my code below. Please let me know if it's possible to integrate something like this into the jQuery core.


(function ($) {


    /**
    * @method Extends jQuery with a namespace functionality.
    **/
    $.fn.namespace = function (strNamespace) {
        strNamespace = String(strNamespace);

        var NS_SEPARATOR = '.';
        var parts = strNamespace.split(NS_SEPARATOR);
        var objToExtend = $.fn;
        var fullNamespace = '$.fn.';
        var nsStart = 0;

        if (parts[0] === '$') {
            nsStart = 1;
        }
        if (parts.length > 1 && parts[1] === 'fn') {
            nsStart = 2;
        }

        for (var i = nsStart; i < parts.length; ++i) {
            fullNamespace += parts[i];
            if (!objToExtend[parts[i]]) {
                var newNs = {};
                newNs[parts[i]] = { namespace: parts[i], fullNamespace: fullNamespace };
                $.extend(objToExtend, newNs);
            }
            objToExtend = objToExtend[parts[i]];
            fullNamespace += NS_SEPARATOR;
        }
        return objToExtend;
    };


    /**
    * @method Extends jQuery with public class declarations similar to the widget classes.
    **/
    $.fn.pubClass = function (strNamespace, strName, objBase, fncClass) {
        strNamespace = String(strNamespace);
        strName = String(strName);

        var fullName = strNamespace + '.' + strName;
        var namespaceObj = $.fn.namespace(strNamespace);

        // create selector for plugin
        $.expr[':'][fullName] = function (elem) {
            return !!$.data(elem, strName);
        };

        // apply argument overloading
        if (jQuery.isFunction(objBase)) {
            fncClass = objBase;
        }

        var prototypeInst = new fncClass();
        prototypeInst.options = $.extend({}, prototypeInst.options);

        namespaceObj[strName] = function (options) {
            if (arguments.length) {
                $.fn.proxyInstantiate(this, options);
            }
        }
        namespaceObj[strName].prototype = $.extend(true, objBase || {}, prototypeInst);

        $.fn.proxyPrototype(strName, namespaceObj[strName]);
    };


    /**
    * @method Instantiates a new proxy object and sets the given arguments as options.
    **/
    $.fn.proxyInstantiate = function (objSelf, objOptions) {
        objSelf = Object(objSelf);

        var args = Array.prototype.slice.call(arguments, 1);
        var options = args.length
            ? $.extend.apply(null, [true, objOptions].concat(args))
            : objOptions;

        objSelf.options = $.extend(true, {}, objSelf.options, options);

        if (objSelf._create) {
            objSelf._create();
        }
        if (objSelf._init) {
            objSelf._init();
        }
    };


    /**
    * @method Assigns the given class to the JQuery fn tree.
    **/
    $.fn.proxyPrototype = function (strName, fncClazz) {
        strName = String(strName);
        $.fn.assertIsTrue('fncClazz', typeof (fncClazz) === 'function');

        $.fn[strName] = function (options) {
            return new fncClazz(options);
        };
    };

    /**
    * @method Throws an argument exception if the given flag is false.
    **/
    $.fn.assertIsTrue = function (strArgumentName, blnMustBeTrue) {
        strArgumentName = String(strArgumentName);

        if (!blnMustBeTrue) {
            var errorObj = {
                message: 'The given argument "' + strArgumentName + '" contains a value which value is out of range.',
                argument: strArgumentName,
                toString: function () {
                    return this.message;
                }
            };
            throw errorObj;
        }
    };

})(jQuery);

Thanking you in anticipation.

Best Regards

Silvan

Change History (17)

comment:1 Changed 8 years ago by Rick Waldron

Component: unfiledcore
Priority: undecidedlow
Status: newopen

comment:2 Changed 8 years ago by roger.meier

I would love to see something like the " jQuery with classes" as a feature of jQuery Core.

Today there ar many similar implementations and concepts (plugins, jQuery UI Widget) available and having a mature OO like class implementation within jQuery core would be great. This will also simplify object oriented development and harmonize architecture across jQuery, jQuery UI and jQuery mobile.

just submitted thia comment as a jQuery 1.7 Roadmap Proposal

-roger

comment:3 Changed 8 years ago by john

Type: enhancementfeature

comment:4 Changed 8 years ago by john

Keywords: 1.7-discuss added

Nominating ticket for 1.7 discussion.

comment:5 Changed 8 years ago by Rick Waldron

Description: modified (diff)

-1, Plugin

comment:6 Changed 8 years ago by jaubourg

-1,

comment:7 Changed 8 years ago by timmywil

-1, plugin

comment:8 Changed 8 years ago by dmethvin

Description: modified (diff)

-1, We don't need it internally, so it should be a plugin. See also underscore.js, backbone.js, JavascriptMVC, or SproutCore.

comment:9 Changed 8 years ago by sgehrig@…

yep, jQuery doesn't need it. but jQuery widget (and other larger frameworks) would need an implementation like this. it's really recommended that the jQuery core contains a class implementation. your roadmap for Milestone 1.7 contains a point "2.generic subclassing" which may correspond to our suggestion.

comment:10 Changed 8 years ago by pascal

Hi I have a question concerning your implementation. Why are you adding your function to the prototype ($.fn) instead of the object ($). I think it would be better to have $.pubClass(...) as with $.widget(...) instead of $.fn.pubClass. And I don't see a reason to have this method in every jQuery object. (For example $("body").pubClass(...) dosn't make sens, or does it?)

Tanks and Best

comment:11 Changed 8 years ago by sgehrig@…

i agree, you can also assign the functions to $.pubClass (it's the more convenient way).

but i strongly recommend to assign the classes to $.fn (as the namespace function does) because with this solution the classes are available in all jQuery contexts.

comment:12 Changed 8 years ago by john

Description: modified (diff)

-1

comment:13 Changed 8 years ago by addyosmani

-1

comment:14 Changed 8 years ago by ajpiano

Description: modified (diff)

-1

comment:15 Changed 8 years ago by pjand

+1

comment:16 Changed 8 years ago by scottgonzalez

Description: modified (diff)

-1, we don't need a minimal class system, we need stateful plugins to have consistent APIs

comment:17 Changed 8 years ago by Rick Waldron

Milestone: 1.next1.7
Resolution: wontfix
Status: openclosed

Closing per 1.7 roadmap meeting resolution

Note: See TracTickets for help on using tickets.