Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jquery oop override method function

Hi I would like to know how can I override method function if my method is declared like this:

(function ($) {
    $.extend({
        tablesorter: new
        function () {
            function buildHeaders(table) {
                console.log('ORIGINAL HEADERS');
            }

            this.construct = function (settings) {
                return this.each(function () {
                    $headers = buildHeaders(this);
                });
            }
        }
    });

    $.fn.extend({
        tablesorter: $.tablesorter.construct
    });
})(jQuery);

My goal is to completely rewrite tablesorter buildHeaders function.

(function ($) {
    var originalMethod = $.fn.tablesorter;
    $.fn.tablesorter = function() {
        console.log('overiding');

        function buildHeaders(table) {
            console.log('OVERRIDE HEADERS');
        }
        originalMethod.apply(this, arguments);
    }
})(jQuery);

This doesn't work... Any help would be great. Thanks!

like image 221
nabizan Avatar asked Jun 11 '13 14:06

nabizan


2 Answers

Short Answer: No you can't.

Functions inside functions (i.e. buildHeaders is a function inside another function) are private and cannot be overridden. Take this simple example and guess the output:

// A very simple function inside a function
test = function() {
  function buildHeaders() {
    alert("original buildHeaders called");
  }

  buildHeaders();
}

// Now lets take a backup of the "test" function
oldTest = test;

// And try to override a private function
test = function() {
  function buildHeaders() {
    alert("duplicate buildHeaders called");
  }

  oldTest.apply(this, arguments);
}

// Call
test();

Guess the output?

Why?

I think you're trying this out from a Java (or similar) background, where you override actual methods. In Javascript, you don't override functions, you replace them. i.e.

function x() { }    // Original function
oldX = x            // Original function is now oldX
x = function() { }  // x is now a **NEW** function
                    // we did not override, we replaced

// At this point, oldX and x are two different functions
// You just swapped their names, but x is no longer the original x

This part is clear. Now on to the second part, Private/Local Variables:

function x() {
  var y = 0;
}
x();
alert(y); // No, you cannot access "y" from outside

But let's take:

function x() {
  y = 0;  // Without "var"
}
x();
alert(y); // Alerts "0"!!

If you give var y = 0 it becomes private inside that function. If you don't, it becomes global scoped (technically upper scoped, but let's leave that out for now).

Third part, functions inside functions are private by default. Going by that same example,

function x() {
  function y() { }
  // this is the same as saying:
  var y = function() { }
  // note "var y", so you can't override this from outside
}

So if you normally define a function inside a function, like function x() { function y() { } }, then y is private to x. Couple this with you can never override a function in javascript, you can only replace. So you will never be able to access or modify that y, except from within the original x function.

Only Alternative

You can replace a function with your custom implementation only if you have access to it. So you have to either edit the original function, or somehow you have to save a reference to buildHeaders outside the function. i.e. you have to do one of these:

// ...
tablesorter: new function() {
  this.buildHeaders = function() { }
  // ...
}

// and later, you can replace this:
tablesorter.buildHeaders = function() { // alternative code }

You will be able to override the function because its not private, and you have a handle to access it.

Edit: Minor grammar

like image 144
Subhas Avatar answered Oct 31 '22 20:10

Subhas


$.extend is not the correct way to extend jQuery, but a jQuery utility method. You should use $.fn.extend. Then it should work. If not try also to use

(function ($) {
  var originalMethod = $.fn.tablesorter;
  $.fn.extend({
    tablesorter: function() {
      console.log('overiding');

      function buildHeaders(table) {
        console.log('OVERRIDE HEADERS');
      }
      originalMethod.apply(this, arguments);
    }
  })
})(jQuery);

You can read more here: http://api.jquery.com/jQuery.fn.extend/

Hope this helps.

like image 1
jokklan Avatar answered Oct 31 '22 20:10

jokklan