1 /* 2 Copyright 2008-2021 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 * Event namespace 51 * @namespace 52 */ 53 JXG.EventEmitter = { 54 /** 55 * Holds the registered event handlers. 56 * @type Object 57 */ 58 eventHandlers: {}, 59 60 /** 61 * Events can be suspended to prevent endless loops. 62 * @type Object 63 */ 64 suspended: {}, 65 66 /** 67 * Triggers all event handlers of this element for a given event. 68 * @param {Array} event 69 * @param {Array} args The arguments passed onto the event handler 70 * @returns Reference to the object. 71 */ 72 trigger: function (event, args) { 73 var i, j, h, evt, len1, len2; 74 75 len1 = event.length; 76 for (j = 0; j < len1; j++) { 77 evt = this.eventHandlers[event[j]]; 78 79 if (!this.suspended[event[j]]) { 80 this.suspended[event[j]] = true; 81 82 if (evt) { 83 len2 = evt.length; 84 85 for (i = 0; i < len2; i++) { 86 h = evt[i]; 87 h.handler.apply(h.context, args); 88 } 89 } 90 91 this.suspended[event[j]] = false; 92 } 93 } 94 95 return this; 96 }, 97 98 /** 99 * Register a new event handler. For a list of possible events see documentation 100 * of the elements and objects implementing 101 * the {@link EventEmitter} interface. 102 * @param {String} event 103 * @param {Function} handler 104 * @param {Object} [context] The context the handler will be called in, default is the element itself. 105 * @returns Reference to the object. 106 */ 107 on: function (event, handler, context) { 108 if (!Type.isArray(this.eventHandlers[event])) { 109 this.eventHandlers[event] = []; 110 } 111 112 context = Type.def(context, this); 113 114 this.eventHandlers[event].push({ 115 handler: handler, 116 context: context 117 }); 118 119 return this; 120 }, 121 122 /** 123 * Unregister an event handler. 124 * @param {String} event 125 * @param {Function} [handler] 126 * @returns Reference to the object. 127 */ 128 off: function (event, handler) { 129 var i; 130 131 if (!event || !Type.isArray(this.eventHandlers[event])) { 132 return this; 133 } 134 135 if (handler) { 136 i = Type.indexOf(this.eventHandlers[event], handler, 'handler'); 137 if (i > -1) { 138 this.eventHandlers[event].splice(i, 1); 139 } 140 141 if (this.eventHandlers[event].length === 0) { 142 delete this.eventHandlers[event]; 143 } 144 } else { 145 delete this.eventHandlers[event]; 146 } 147 148 return this; 149 }, 150 151 /** 152 * @description Implements the functionality from this interface in the given object. 153 * All objects getting their event handling 154 * capabilities from this method should document it by adding 155 * the <tt>on, off, triggerEventHandlers</tt> via the 156 * borrows tag as methods to their documentation: 157 * <pre>@borrows JXG.EventEmitter#on as this.on</pre> 158 * @param {Object} o 159 */ 160 eventify: function (o) { 161 o.eventHandlers = {}; 162 o.on = this.on; 163 o.off = this.off; 164 o.triggerEventHandlers = this.trigger; 165 o.trigger = this.trigger; 166 o.suspended = {}; 167 } 168 }; 169 170 return JXG.EventEmitter; 171 }); 172