all files / montage/core/ target.js

95.65% Statements 22/23
85.71% Branches 12/14
87.5% Functions 7/8
95.65% Lines 22/23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186                                                                                                                                           35×                                             73×       73× 73×   73×                             196× 196× 196×   196×                         515× 513×                           39× 39×                       64× 64× 64× 64×                       28× 26× 26×              
var Montage = require("./core").Montage,
    defaultEventManager = require("./event/event-manager").defaultEventManager,
    MutableEvent = require("./event/mutable-event").MutableEvent;
 
/**
 * A Target is any object that can be a candidate for dispatching and receiving
 * events throughout what is typically considered the "component tree" of a
 * Montage application.
 *
 * @class Target
 * @extends Montage
 */
exports.Target = Montage.specialize( /** @lends Target.prototype */{
    /**
     * Whether or not this target can accept user focus and become the
     * activeTarget This matches up with the `document.activeElement` property
     * purpose-wise; Events from components that should be dispatched as
     * logically occurring at the point of user focus should be dispatched at
     * the activeTarget
     *
     * By default a target does not accept this responsibility.
     *
     * @type {boolean}
     * @default false
     */
    acceptsActiveTarget: {
        serializable: false,
        value: false
    },
 
    /**
     * Whether or not this is the activeTarget
     *
     * This is a getter and is not bindable. Bind to
     * `defaultEventManager.activeTarget == this`.
     *
     * @type {boolean}
     * @readonly
     */
    isActiveTarget: {
        get: function () {
            return this === defaultEventManager.activeTarget;
        }
    },
 
    /**
     * Called prior to this target becoming the activeTarget
     * @function
     * @param {Target} oldTarget the current activeTarget
     */
    willBecomeActiveTarget: {
        value: Function.noop
    },
 
    /**
     * Called after to this target became the activeTarget
     * @function
     */
    didBecomeActiveTarget: {
        value: Function.noop
    },
 
    /**
     * Ask this target to surrender its activeTarget status.
     * @function
     * @param {Target} newTarget the Target that is about to become the
     * `activeTarget`
     * @returns {boolean} Whether or not to surrender activeTarget status
     */
    surrendersActiveTarget: {
        value: function (newTarget) {
            return true;
        }
    },
 
    /**
     * Which target to distribute an event after this when distributing events
     * throughout a graph of targets.
     * @property {boolean} serializable
     * @property {Component} value
     */
    nextTarget: {
        serializable: false,
        value: null
    },
 
    /**
     * Dispatches the specified event with this target
     * as the event's proximal target
     * @function
     * @param {Event} event The event object to dispatch
     */
    dispatchEvent: {
        value: function (event) {
            var targettedEvent = (event instanceof MutableEvent)
                                ? event
                                : MutableEvent.fromEvent(event);
 
            targettedEvent.target = this;
            defaultEventManager.handleEvent(targettedEvent);
 
            return !event.defaultPrevented;
        }
    },
 
    /**
     * Creates and dispatches an event with the specified properties with this
     * target as the event's proximal target
     * @function
     * @param {string} type The type of the event to dispatch
     * @param {boolean} canBubble Whether or not the event can bubble
     * @param {boolean} cancelable Whether or not the event can be cancelled
     * @param {Object} detail The optional detail object of the event
     */
    dispatchEventNamed: {
        value: function (type, canBubble, cancelable, detail) {
            var event = MutableEvent.fromType(type, canBubble, cancelable, detail);
            event.target = this;
            defaultEventManager.handleEvent(event);
 
            return !event.defaultPrevented;
        }
    },
 
    /**
     * Adds an event listener to the object.
     * @function
     * @param {string} type The event type to listen for.
     * @param {object | function} listener The listener object or function.
     * @param {boolean} useCapture Specifies whether to listen for the event during the bubble or capture phases.
     */
    addEventListener: {
        value: function addEventListener(type, listener, useCapture) {
            if (listener) {
                defaultEventManager.registerEventListener(this, type, listener, useCapture);
            }
        }
    },
 
    /**
     * Removes an event listener from the object.
     * @function
     * @param {string} type The event type.
     * @param {object | function} listener The listener object or function.
     * @param {boolean} useCapture The phase of the event listener.
     */
    removeEventListener: {
        value: function removeEventListener(type, listener, useCapture) {
            Eif (listener) {
                defaultEventManager.unregisterEventListener(this, type, listener, useCapture);
            }
        }
    },
 
    /**
     * Load a Composer
     * @function
     * @param {Composer} composer
     */
    loadComposer: {
        value: function (composer) {
            Eif (composer && !composer._isLoaded) {
                composer._resolveDefaults();
                composer.load();
                composer._isLoaded = true;
            }
        }
    },
 
    /**
     * Unload a Composer
     * @function
     * @param {Composer} composer
     */
    unloadComposer: {
        value: function (composer) {
            if (composer && composer._isLoaded) {
                composer.unload();
                composer._isLoaded = false;
            }
        }
    }
 
});