Ben Carey
Ben Carey

Reputation: 16968

Extending jQuery, including the jQuery constructor in another object

Explanation

Firstly, I might be mixed up between the jQuery constructor and init functions, if so please ignore my terminology below.

I have an object called SineMacula, which, at the moment is simply acting as a namespace for a library of methods.

However, I am about to write some methods for the SineMacula object which I would like to act like jQuery extensions.

The complication arises here, instead of using the jQuery alias $, I would like to use the SineMacula object to run the jQuery construct. So effectively my code will look like this:

SineMacula('#test').dropdown();

instead of:

$('#test').dropdown();

However, I don't think this would be too hard if it wasn't for my next point:

I do not want to alias the whole of jQuery, I simply want the jQuery constructor to run when I call SineMacula('something'), and then apply any methods to the result of SineMacula('something')

My Question

The best way to ask this question is by illustrating. Is the following possible?

SineMacula('#test').someFunction(function(){
    // Do something here
    // The jQuery object must be passed in so that
    // $(this) refers to SineMacula('#test')
});

However, I do not want to be able to do this (fully alias jQuery):

SineMacula('#test').animate(); // A regular jQuery function

I am aware this is probably not possible, but felt it was worth asking :-)

UPDATE 1

Just to be clear, this is some of the code I am currently using for the SineMacula object:

/**
 * Sine Macula Javascript  API
 * The Sine Macula API contains all base functions for use throughout
 * all websites
 * @name class.sinemacula.js
 * @author Ben Carey
 * @version 1.0
 * @date 25/10/2012
 * @copyright (c) 2012 Sine Macula MMVIII Limited (sinemacula.co.uk)
 */

function SineMacula(){

    // Only proceed if jQuery has been loaded
    if(typeof jQuery=='undefined'){
        // jQuery has not been loaded
        console.log('jQuery has not been loaded');
    }else{

        /**
         * Sine Macula Load
         * Load the Sine Macula Libraries and Plugins
         * into the current document
         *
         * The options:
         * - package: the package of libraries to load
         * - packageURL: a remote source to load the package details from
         * - libraries: any additional libraries to load
         *
         * @param object options The options for the Sine Macula load
         */
        this.load = function(options){
            // Load Sine Macula Libraries here
        }
    }
};

/**
 * Overlay
 * Place an overlay on the page
 *
 * The options:
 * - wrapper: the wrapper to prepend to
 * - fade: indicate whether or not to fade the overlay
 * - fadeSpeed: the fade speed for the overlay fade
 * - opacity: the opacity to apply to the overlay
 * - color: the color to apply to the overlay
 * - callback: the callback to be called once the function has completed
 *
 * @param boolean showHide A boolean to indicate whether to show/hide the overlay
 * @param object options The options for the overlay
 */
SineMacula.prototype.overlay = function (showHide,options){
    // Process the overlay here
};

// All libraries are extended onto the SineMacula object

The SineMacula object is initiated at the top of each page like so:

<script src="//libraries.example.net/jsapi" language="javascript" type="text/javascript"></script>
<script language="javascript" type="text/javascript">

    var sm = new SineMacula();
    sm.load();

</script>

UPDATE 2 - Ignore Above

Right, I am finding it very hard to explain what I would like to achieve. I will do my best to accomplish this below in steps, ignore the content above.

Step 1

I have a class called SineMacula, this contains many methods that do all sorts of things. Think of it as a library like jQuery.

This is defined like so:

function SineMacula(){

    // Only proceed if jQuery has been loaded
    if(typeof jQuery=='undefined'){
        // jQuery has not been loaded
        console.log('jQuery has not been loaded');
    }else{
        this.load = function(options){
            // Load Sine Macula Libraries here
        }
    }
};

Step 2

The SineMacula class is initiated at the top of each page with the following code:

<script src="//libraries.example.net/jsapi" language="javascript" type="text/javascript"></script>
<script language="javascript" type="text/javascript">

    var sm = new SineMacula();

</script>

Step 3

The SineMacula object then loads any required libraries and extensions for the SineMacula object by calling e.g. sm.load({package:'all'}). This will dynamically load any extensions into the webpage.

Step 4

The extensions are defined like so:

SineMacula.prototype.doSomething = function(){
    // Do something here
}

Step 5 - This is where things get a little more complex

Up until now, the SineMacula object has been acting as a namespace for methods such as doSomething() etc.

I would now like to define methods that do more than just act as a function.

Where I would have called SineMacula.doSomething(), I would now like to be able to call SineMacula('#test').doSomething() where SineMacula('#test') acts the same as $('#test') in jQuery.

So I can access my functions like this:

SineMacula.doSomething('maybe parameters here');
SineMacula('selector').doSomethingElse('maybe parameters here');

In the same way that you can call:

$.ajax('parameters');
$('selector').animate('parameters');

So if an argument is passed to the SineMacula object then it is processed using the jQuery selector function and passed as the subject to the method being called.

For example:

// Call doSomethingElse on the #test element
SineMacula('#test').doSomethingElse();

// Within the doSomethingElse function $(this) relates to $('#test')

To summarise...

SineMacula('selector') acts as $('selector') if 'selector' is supplied, and this gets passed to the child method. But SineMacula is not an extension of jQuery. I do not want SineMacula to be an Alias of $.

Upvotes: 0

Views: 702

Answers (1)

Luca Rainone
Luca Rainone

Reputation: 16468

if I understand the question and if you can change SineMacula constructor

function SineMacula(){
     // add following 3 lines
     if(arguments.length>0) {
        return jQuery.call(null,arguments);
     }
    // Only proceed if jQuery has been loaded
    if(typeof jQuery=='undefined'){
        // jQuery has not been loaded
        console.log('jQuery has not been loaded');
    }else{

        this.load = function(options){
            // Load Sine Macula Libraries here
            console.log("ok load");
        }
    }
};

Upvotes: 1

Related Questions