      1 /*
      2     Copyright 2008-2013
      3         Matthias Ehmann,
      4         Michael Gerhaeuser,
      5         Carsten Miller,
      6         Bianca Valentin,
      7         Alfred Wassermann,
      8         Peter Wilfahrt
      9
     10     This file is part of JSXGraph.
     11
     12     JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
     13
     14     You can redistribute it and/or modify it under the terms of the
     15
     16       * GNU Lesser General Public License as published by
     17         the Free Software Foundation, either version 3 of the License, or
     18         (at your option) any later version
     19       OR
     20       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
     21
     22     JSXGraph is distributed in the hope that it will be useful,
     23     but WITHOUT ANY WARRANTY; without even the implied warranty of
     24     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     25     GNU Lesser General Public License for more details.
     26
     27     You should have received a copy of the GNU Lesser General Public License and
     28     the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
     29     and <http://opensource.org/licenses/MIT/>.
     30  */
     31
     32
     33 /*global JXG: true, define: true*/
     34 /*jslint nomen: true, plusplus: true*/
     35
     36 /* depends:
     37  jxg
     38  utils/type
     39  */
     40
     41 /**
     42  * @fileoverview In this file the EventEmitter interface is defined.
     43  */
     44
     45 define(['jxg', 'utils/type'], function (JXG, Type) {
     46
     47     "use strict";
     48
     49     /**
     50      * @namespace
     51      */
     52     JXG.EventEmitter = {
     53         /**
     54          * Holds the registered event handlers.
     55          * @name JXG.EventEmitter#eventHandlers
     56          * @type Object
     57          */
     58         eventHandlers: {},
     59
     60         /**
     61          * Events can be suspended to prevent endless loops.
     62          * @name JXG.EventEmitter#suspended
     63          * @type Object
     64          */
     65         suspended: {},
     66
     67         /**
     68          * Triggers all event handlers of this element for a given event.
     69          * @name JXG.EventEmitter#triggerEventHandlers
     70          * @function
     71          * @param {Array} event
     72          * @param {Array} args The arguments passed onto the event handler
     73          * @returns Reference to the object.
     74          */
     75         trigger: function (event, args) {
     76             var i, j, h, evt, len1, len2;
     77
     78             len1 = event.length;
     79             for (j = 0; j < len1; j++) {
     80                 evt = this.eventHandlers[event[j]];
     81
     82                 if (!this.suspended[event[j]]) {
     83                     this.suspended[event[j]] = true;
     84
     85                     if (evt) {
     86                         len2 = evt.length;
     87
     88                         for (i = 0; i < len2; i++) {
     89                             h = evt[i];
     90                             h.handler.apply(h.context, args);
     91                         }
     92                     }
     93
     94                     this.suspended[event[j]] = false;
     95                 }
     96             }
     97
     98             return this;
     99         },
    100
    101         /**
    102          * Register a new event handler. For a list of possible events see documentation of the elements and objects implementing
    103          * the {@link EventEmitter} interface.
    104          * @name JXG.EventEmitter#on
    105          * @function
    106          * @param {String} event
    107          * @param {Function} handler
    108          * @param {Object} [context] The context the handler will be called in, default is the element itself.
    109          * @returns Reference to the object.
    110          */
    111         on: function (event, handler, context) {
    112             if (!Type.isArray(this.eventHandlers[event])) {
    113                 this.eventHandlers[event] = [];
    114             }
    115
    116             context = Type.def(context, this);
    117
    118             this.eventHandlers[event].push({
    119                 handler: handler,
    120                 context: context
    121             });
    122
    123             return this;
    124         },
    125
    126         /**
    127          * Unregister an event handler.
    128          * @name JXG.EventEmitter#off
    129          * @function
    130          * @param {String} event
    131          * @param {Function} [handler]
    132          * @returns Reference to the object.
    133          */
    134         off: function (event, handler) {
    135             var i;
    136
    137             if (!event || !Type.isArray(this.eventHandlers[event])) {
    138                 return this;
    139             }
    140
    141             if (handler) {
    142                 i = Type.indexOf(this.eventHandlers[event], handler, 'handler');
    143                 if (i > -1) {
    144                     this.eventHandlers[event].splice(i, 1);
    145                 }
    146
    147                 if (this.eventHandlers[event].length === 0) {
    148                     delete this.eventHandlers[event];
    149                 }
    150             } else {
    151                 delete this.eventHandlers[event];
    152             }
    153
    154             return this;
    155         },
    156
    157         /**
    158          * @description Implements the functionality from this interface in the given object. All objects getting their event handling
    159          * capabilities from this method should document it by adding the <tt>on, off, triggerEventHandlers</tt> via the
    160          * borrows tag as methods to their documentation: <pre>@borrows JXG.EventEmitter#on as this.on</pre>
    161          * @name JXG.EventEmitter#eventify
    162          * @function
    163          * @param {Object} o
    164          */
    165         eventify: function (o) {
    166             o.eventHandlers = {};
    167             o.on = this.on;
    168             o.off = this.off;
    169             o.triggerEventHandlers = this.trigger;
    170             o.trigger = this.trigger;
    171             o.suspended = {};
    172         }
    173     };
    174
    175     return JXG.EventEmitter;
    176 });
    177