Run
Run

Reputation: 57176

Using Inheritance Patterns to Organize Large jQuery Applications - how to extend the plugin?

I found this working example of Inheritance Patterns that separates business logic and framework code. I'm tempted to use it as a boilerplate, but since it is an inheritance Pattern, then how can I extend the business logic (the methods in var Speaker)?

For instance, how can I extend a walk: method into it?

/**
 * Object Speaker
 * An object representing a person who speaks.
 */
var Speaker = {
    init: function(options, elem) {
        // Mix in the passed in options with the default options
        this.options = $.extend({},this.options,options);

        // Save the element reference, both as a jQuery
        // reference and a normal reference
        this.elem  = elem;
        this.$elem = $(elem);

        // Build the dom initial structure
        this._build();

        // return this so we can chain/use the bridge with less code.
        return this;
    },
    options: {
        name: "No name"
    },
    _build: function(){
        this.$elem.html('<h1>'+this.options.name+'</h1>');
    },
    speak: function(msg){
        // You have direct access to the associated and cached jQuery element
        this.$elem.append('<p>'+msg+'</p>');
    }
};


// Make sure Object.create is available in the browser (for our prototypal inheritance)
// Courtesy of Papa Crockford
// Note this is not entirely equal to native Object.create, but compatible with our use-case
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {} // optionally move this outside the declaration and into a closure if you need more speed.
        F.prototype = o;
        return new F();
    };
}

$.plugin = function(name, object) {
    $.fn[name] = function(options) {
        // optionally, you could test if options was a string
        // and use it to call a method name on the plugin instance.
        return this.each(function() {
            if ( ! $.data(this, name) ) {
                $.data(this, name, Object.create(object).init(options, this));
            }
        });
    };
};

// With the Speaker object, we could essentially do this:
$.plugin('speaker', Speaker);

Any ideas?

Upvotes: 0

Views: 1092

Answers (1)

Tomalak
Tomalak

Reputation: 338158

How about simply using JavaScript's regular prototype inheritance?

Consider this:

function Speaker(options, elem) {
    this.elem = $(elem)[0];
    this.options = $.extend(this.defaults, options);

    this.build();
}
Speaker.prototype = {
    defaults: {
        name: "No name"
    },
    build: function () {
        $('<h1>', {text: this.options.name}).appendTo(this.elem);
        return this;
    },
    speak: function(message) {
        $('<p>', {text: message}).appendTo(this.elem);
        return this;
    }
};

Now you can do:

var pp = new Speaker({name: "Porky Pig"}, $("<div>").appendTo("body"));
pp.speak("That's all folks!");

Speaker.prototype.walk = function (destination) {
    $('<p>', {
        text: this.options.name + " walks " + destination + ".",
        css: { color: "red" }
    }).appendTo(this.elem);
    return this;
}

pp.walk("off the stage");

Runnable version:

function Speaker(options, elem) {
    this.elem = $(elem)[0];
    this.options = $.extend(this.defaults, options);

    this.build();
}
Speaker.prototype = {
    defaults: {
        name: "No name"
    },
    build: function () {
        $('<h1>', {text: this.options.name}).appendTo(this.elem);
        return this;
    },
    speak: function(message) {
        $('<p>', {text: message}).appendTo(this.elem);
        return this;
    }
};

var pp = new Speaker({name: "Porky Pig"}, $("<div>").appendTo("body"));
pp.speak("That's all folks!");
   
Speaker.prototype.walk = function (destination) {
    $('<p>', {
        text: this.options.name + " walks " + destination + ".",
        css: { color: "red" }
    }).appendTo(this.elem);
    return this;
}

pp.walk("off the stage");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

Upvotes: 1

Related Questions