0

I'm extending the jquery.contentcarousel plugin, and I've reached a specific point where I'm defining new functions via __prototype__. I shrunk the code down to demonstrate the essential part:

(function($) {
    var   aux      = {
    navigate : function(){
        //...
      },
    }
    methods = {
        init     : function( options ) {

            return this.each(function() {

                var $el        = $(this);

                //THIS IS THE SLIPPERY LINE:
                $el.__proto__.scrollOneLeft = function() {
                    aux.navigate( -1, $el, $wrapper, $.extend(settings, {sliderSpeed: 10, sliderEasing: ''}), cache );
                };
            });

        }
    }

    $.fn.contentcarousel = function(method) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.contentcarousel' );
        }
    }; 

})(jQuery);

This works on the modern browsers, but the problem is that $el.__proto__ is not working in IE9 and IE10 (yet). I'm not a jQuery Ninja, so I guess that this isn't the proper solution anyway.

So my question is, how would you define a new method properly in this scenario?

Attila Fulop
  • 6,861
  • 2
  • 44
  • 50

1 Answers1

2

Yes this is not the proper way of doing this. jQuery has great extensibility capability, and this case is already covered in a cross-browser way.

You can define new functions on the jQuery array object, by:

jQuery.fn.asdfize = function () {
    this.html('asdf');
    return this; // for chainability
}

You can than use $('div').asdfize(); to replace all div's innerHTML with asdf.

This is basically what you need, as $(this) has the jQuery array object (jQuery.fn) as it's prototype.

The old jQuery wiki has a nice article about plugin authoring which covers this.

EDIT:

You have already done this in your code with $.fn.contentcarousel. How is this other case different?

EDIT2:

In this part of your code:

return this.each(function() {
    var $el = $(this);
    $el.__proto__.scrollOneLeft = function() { ... };
});

You overwrite the scrollOneLeft function in every iteration of each. It's probably not what you want!

You might want to define the function only once instead, but use this inside it as it will be the jQuery object you call it on.

vinczemarton
  • 7,756
  • 6
  • 54
  • 86
  • Hey SoonDead, thanks for the solution! It is working so far. I wouldn't say I understand it yet, so now I'm going to read about `$.fn` – Attila Fulop May 09 '13 at 12:21
  • Basically it's the [prototype of `$(this)`](http://stackoverflow.com/questions/4083351/what-does-jquery-fn-mean) :) – vinczemarton May 09 '13 at 12:28
  • Ok, so `$el` should be replaced with `this`? As I read in the plugins authoring guide it's wrapped unnecessarily (as `$this`) anyways, right? – Attila Fulop May 09 '13 at 12:32
  • `this` is the [object the function is called on](http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/). So `$(this)` would be unnecessary in the `scrollOneLeft` function yes, as it is already the jQuery object. But keep in mind that a lot of jQuery functions (like `.each()`) call their callback functions on the *raw DOM element*. Don't mix up these 2 cases. :) – vinczemarton May 09 '13 at 12:38