5

I'm trying to add a method to a jQuery object that has the same name (but different parameter set) as another method.

What I've got so far:

jQuery.fn.insertBefore = function(elem, duration)
{
    this.css("display", "none");
    this.insertBefore(elem);
    this.toggle(duration);
}

However, this code (specifically the this.insertBefore(where); line) calls this same function, and not the jQuery insertBefore() function, as desired. What do I need to do in order to add this function to the jQuery object, and have it overload (not overwrite) the existing function?

EDIT: Solution

(function ($)
{
    var oldInsertBefore = $.fn.insertBefore;
    jQuery.fn.insertBefore = function(elem, duration)
    {
        if (duration === undefined)
        {
            oldInsertBefore.call(this, elem);
            return;
        }

        this.css("display", "none");
        this.insertBefore(elem);
        this.toggle(duration);
    }
})(jQuery);

4 Answers 4

6

You back up original function before overwriting. Something like this:

(function($){
    var oldInsertBefore = $.fn.insertBefore;
    jQuery.fn.insertBefore = function(elem, duration)
    {
        oldInsertBefore.apply(this, arguments);
        this.css("display", "none");
        this.insertBefore(elem);
        this.toggle(duration);
    }
})(jQuery);
Sign up to request clarification or add additional context in comments.

3 Comments

Would this call the rest of the new insertBefore function every time? Or would it somehow be able to tell when to call the old one vs. the new one?
After this code executes, original insertBefore will be replaced. You, in your replaced version, decide when to call original version.
I would apply something like if( typeof duration == 'undefined' ) { oldInsertBefore.apply(this, arguments); return; }
4

you can use $.sub()

(function($){
    var sub$ = $.sub();

    sub$.fn.insertBefore = function(where, duration) {
       this.css("display", "none");
       this.insertBefore(where);
       this.toggle(duration);
    }

    /* you can use this plugin in this scope or you could also
       return sub$ and call the plugin outside */
})(jQuery);

description of $.sub():

Creates a new copy of jQuery whose properties and methods can be modified without affecting the original jQuery object.

from http://api.jquery.com/jQuery.sub/

Comments

0

From a technical perspective JavaScript doesn't let you do define separate functions with the same name, but different arguments. You can only have one function with the same name, though it doesn't care how many arguments come through. All of the solutions posted above take advantage of that, but just end up renaming the original function and calling it. Unless there's a really good reason I'd suggest giving your custom method a different name so that it doesn't conflict with the existing function. Imagine someone else trying to add to your code-base and not realizing that a standard jQuery method was overwritten.

Your own method can accept any number of arguments, which can be accessed via the arguments object. You can do things like arguments.length or just check if your arguments exist to figure out how many / which arguments were passed, (see: https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments).

It's more standard in jQuery to just pass in an options object when you're making a custom plugin, as explained here.

Why are you trying to do this exactly?

Comments

0

Searching for a solution to overcome some issue I landed here but found out that I never need overloading in any kind. Using jQuery in an own JS-class I've this code:

class myClass
{
    appendMessage(elementObj, message) {
        ...
    }

    appendOrReplaceMessage(elementObj, message) {
        let that = this;
        let elObj = elementObj;
        let msg = message;
        if (elementObj.parent().find('span.error').length) {
            this.disableNextButton(elementObj);
            elementObj.parent().find('span.error').each(function(index, element) {
                $(element).hide({
                    duration: 300,
                    complete: (function() {
                        $(element).remove();
                        that.appendMessage(elObj, msg);
                    })
                })
            });
        } else {
            this.appendMessage(elementObj, message);
        }
    }
}

The challenge in this code was that inside the each-function the variable this has another meaning than outside. So I couldn't use the context of the outer class to call the method this.appendMessage(). After adding the declarations inside the method appendOrReplaceMessage() I could use the outer object as that and the declared variables also are all available inside the each-function.

This doesn't answer the question but shows perhaps a way to circumvent the problem.


Related to the problem in the question it keeps to mention that the jQuery-function before() allows using a function as callback, while this option is not given in the jquery-function insertBefore(). Using the right function is essential to avoid the over-complicated code obviously. So the code of the question could be used like this, some adjustments have to be made probably to get it working like desired:

before((function(index){
        this.css("display", "none");
        this.insertBefore(elem);
        this.toggle(duration);
}));

My first codeblock beside explanation might be helpful to get the values of the variables elem and duration inside the before() function.

jQuery API - before()
jQuery API - insertBefore()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.