API Docs for:
Show:

File: src/core/mixin.js

window.multigraph.util.namespace("window.multigraph.core", function (ns) {
    "use strict";

    /**
     * @module multigraph
     * @submodule core
     */

    /**
     * The Mixin model provides a convenient way for Jermaine
     * applications to "mix in" additional functionality to a model,
     * from outside the model's initial definition.
     * 
     * The ability to add features (methods and/or attributes) to a
     * Jermaine model outside its initial definition already exists in
     * Jermaine -- this Mixin model does not actually add new
     * functionality to Jermaine; it just provides a convenient
     * pattern for grouping additional features together and applying
     * them to a model as a group.
     * 
     * The Mixin model maintains an internal list of functions, called
     * mixin functions, and provides an add() method for adding a
     * function to that list.
     * 
     * The apply() method calls all of the mixinfunctions that have been
     * added to the list, passing each one the same arguments
     * that were passed to the apply() function itself.
     * 
     * That's it.  That's all the Mixin class does.  It's up to you to
     * put whatever jermaine-model-extending code you want in the
     * mixin functions you add to the Mixin; the Mixin simply serves
     * as a place to hold them all, and a convenient way to execute
     * them all at once.
     *
     * @class Mixin
     * @for Mixin
     * @author mbp
     */
    var Mixin = new window.jermaine.Model("Mixin", function () {

        /**
         * The internal list of functions to be applied.
         *
         * @property mixinfuncs
         * @private
         * @type {}
         * @author mbp
         */
        this.hasMany("mixinfuncs");

        /**
         * Internal value for tracking whether apply() has been called
         * for this Mixin.
         *
         * @property applied
         * @type {}
         * @private
         * @author mbp
         */
        this.hasA("applied").which.isA("boolean").defaultsTo(false);

        /**
         * Adds a function to this Mixin's mixin list.  Does not check
         * to see if the function is already on the list -- just blindly
         * appends the given function to the list.
         *
         * @method add
         * @param {} func
         * @author mbp
         */
        this.respondsTo("add", function (mixinfunc) {
            this.mixinfuncs().add(mixinfunc);
        });

        /**
         * Call each of this Mixin's mixin functions.  Any
         * arguments passed to apply() will be passed through to each
         * mixin function called.
         * 
         * apply() checks to see whether it has ever been called
         * before for this Mixin, and only executes the mixin
         * functions if this is the first call to apply(); calls to
         * apply() after the first one will have no effect.  (This is
         * true even if additional mixin functions are added after
         * apply() is called; the Mixin maintains a single internal
         * Boolean value that tracks whether apply() has been called.)
         *
         * @method apply
         * @author mbp
         */
        this.respondsTo("apply", function () {
            if (! this.applied()) {
                var i;
                for (i=0; i<this.mixinfuncs().size(); ++i) {
                    this.mixinfuncs().at(i).apply(this, arguments);
                }
            }
            this.applied(true);
        });


        /**
         * Just like apply(), but forces the mixin functions to be called
         * regardless of whether apply() was previously called for this
         * Mixin.
         *
         * @method reapply
         * @author mbp
         */
        this.respondsTo("reapply", function () {
            this.applied(false);
            this.apply.apply(this,arguments);
        });


   });

    ns.Mixin = Mixin;

});