1 /* 
  2     Copyright 2012
  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: you can redistribute it and/or modify
 13     it under the terms of the GNU Lesser General Public License as published by
 14     the Free Software Foundation, either version 3 of the License, or
 15     (at your option) any later version.
 16 
 17     JSXGraph is distributed in the hope that it will be useful,
 18     but WITHOUT ANY WARRANTY; without even the implied warranty of
 19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20     GNU Lesser General Public License for more details.
 21 
 22     You should have received a copy of the GNU Lesser General Public License
 23     along with JSXGraph.  If not, see <http://www.gnu.org/licenses/>.
 24 */
 25 
 26 /** 
 27  * @fileoverview In this file the EventEmitter interface is defined.
 28  */
 29 
 30 /**
 31  * @namespace
 32  */
 33 JXG.EventEmitter = {
 34     /**
 35      * Holds the registered event handlers.
 36      * @name JXG.EventEmitter#eventHandlers
 37      * @type Object
 38      */
 39     eventHandlers: {},
 40     
 41     /**
 42      * Triggers all event handlers of this element for a given event.
 43      * @name JXG.EventEmitter#triggerEventHandlers
 44      * @function
 45      * @param {String} event
 46      * @returns Reference to the object.
 47      */
 48     triggerEventHandlers: function (event) {
 49         var i, h, args = Array.prototype.slice.call(arguments, 1),
 50             j, evt, len1, len2;
 51 
 52         if (!JXG.isArray(event)) {
 53             event = [event];
 54         }
 55 
 56         len1 = event.length;
 57         for (j = 0; j < len1; j++) {
 58             evt = event[j];
 59             if (JXG.isArray(this.eventHandlers[evt])) {
 60                 len2 = this.eventHandlers[evt].length;
 61                 for (i = 0; i < len2; i++) {
 62                     h = this.eventHandlers[evt][i];
 63                     h.handler.apply(h.context, args);
 64                 }
 65             }
 66         }
 67         
 68         return this;
 69     },
 70 
 71     /**
 72      * Register a new event handler. For a list of possible events see documentation of the elements and objects implementing
 73      * the {@link EventEmitter} interface.
 74      * @name JXG.EventEmitter#on
 75      * @function
 76      * @param {String} event
 77      * @param {Function} handler
 78      * @param {Object} [context] The context the handler will be called in, default is the element itself.
 79      * @returns Reference to the object.
 80      */
 81     on: function (event, handler, context) {
 82         if (!JXG.isArray(this.eventHandlers[event])) {
 83             this.eventHandlers[event] = [];
 84         }
 85 
 86         context = JXG.def(context, this);
 87 
 88         this.eventHandlers[event].push({
 89             handler: handler,
 90             context: context
 91         });
 92         
 93         return this;
 94     },
 95 
 96     /**
 97      * Unregister an event handler.
 98      * @name JXG.EventEmitter#off
 99      * @function
100      * @param {String} event
101      * @param {Function} handler
102      * @returns Reference to the object.
103      */
104     off: function (event, handler) {
105         var i;
106 
107         if (!event || !JXG.isArray(this.eventHandlers[event])) {
108             return this;
109         }
110 
111         if (handler) {
112             i = JXG.indexOf(this.eventHandlers[event], handler, 'handler');
113             if (i > -1) {
114                 this.eventHandlers[event].splice(i, 1);
115             }
116         } else {
117             this.eventHandlers[event].length = 0;
118         }
119         
120         return this;
121     },
122 
123     /**
124      * @description Implements the functionality from this interface in the given object. All objects getting their event handling
125      * capabilities from this method should document it by adding the <tt>on, off, triggerEventHandlers</tt> via the
126      * borrows tag as methods to their documentation: <pre>@borrows JXG.EventEmitter#on as this.on</pre>
127      * @name JXG.EventEmitter#eventify
128      * @function
129      * @param {Object} o
130      */
131     eventify: function (o) {
132         o.eventHandlers = {};
133         o.on = this.on;
134         o.off = this.off;
135         o.triggerEventHandlers = this.triggerEventHandlers;
136     }
137 };
138