@@ -24,6 +24,7 @@ var Events = {
2424 if ( plotObj . _ev instanceof EventEmitter ) return plotObj ;
2525
2626 var ev = new EventEmitter ( ) ;
27+ var internalEv = new EventEmitter ( ) ;
2728
2829 /*
2930 * Assign to plot._ev while we still live in a land
@@ -32,6 +33,16 @@ var Events = {
3233 */
3334 plotObj . _ev = ev ;
3435
36+ /*
37+ * Create a second event handler that will manage events *internally*.
38+ * This allows parts of plotly to respond to thing like relayout without
39+ * having to use the user-facing event handler. They cannot peacefully
40+ * coexist on the same handler because a user invoking
41+ * plotObj.removeAllListeners() would detach internal events, breaking
42+ * plotly.
43+ */
44+ plotObj . _internalEv = internalEv ;
45+
3546 /*
3647 * Assign bound methods from the ev to the plot object. These methods
3748 * will reference the 'this' of plot._ev even though they are methods
@@ -46,6 +57,15 @@ var Events = {
4657 plotObj . removeListener = ev . removeListener . bind ( ev ) ;
4758 plotObj . removeAllListeners = ev . removeAllListeners . bind ( ev ) ;
4859
60+ /*
61+ * Create funtions for managing internal events. These are *only* triggered
62+ * by the mirroring of external events via the emit function.
63+ */
64+ plotObj . _internalOn = internalEv . on . bind ( internalEv ) ;
65+ plotObj . _internalOnce = internalEv . once . bind ( internalEv ) ;
66+ plotObj . _removeInternalListener = internalEv . removeListener . bind ( internalEv ) ;
67+ plotObj . _removeAllInternalListeners = internalEv . removeAllListeners . bind ( internalEv ) ;
68+
4969 /*
5070 * We must wrap emit to continue to support JQuery events. The idea
5171 * is to check to see if the user is using JQuery events, if they are
@@ -58,6 +78,7 @@ var Events = {
5878 }
5979
6080 ev . emit ( event , data ) ;
81+ internalEv . emit ( event , data ) ;
6182 } ;
6283
6384 return plotObj ;
@@ -70,6 +91,7 @@ var Events = {
7091 * triggerHandler for backwards compatibility.
7192 */
7293 triggerHandler : function ( plotObj , event , data ) {
94+ var i ;
7395 var jQueryHandlerValue ;
7496 var nodeEventHandlerValue ;
7597 /*
@@ -98,10 +120,24 @@ var Events = {
98120 /*
99121 * Call all the handlers except the last one.
100122 */
101- for ( var i = 0 ; i < handlers . length ; i ++ ) {
123+ for ( i = 0 ; i < handlers . length ; i ++ ) {
102124 handlers [ i ] ( data ) ;
103125 }
104126
127+ /* Do the same as for external-facing events, except trigger the same
128+ * events on the internal handlers. This does *not* affect the return
129+ * value. It simply mirrors triggers internally so that there's no
130+ * conflict with external user-defined events when plotly manages
131+ * events internally.
132+ */
133+ var internalHandlers = plotObj . _internalEv . _events [ event ] ;
134+ if ( internalHandlers ) {
135+ if ( typeof internalHandlers === 'function' ) internalHandlers = [ internalHandlers ] ;
136+ for ( i = 0 ; i < internalHandlers . length ; i ++ ) {
137+ internalHandlers [ i ] ( data ) ;
138+ }
139+ }
140+
105141 /*
106142 * Now call the final handler and collect its value
107143 */
@@ -124,6 +160,13 @@ var Events = {
124160 delete plotObj . removeAllListeners ;
125161 delete plotObj . emit ;
126162
163+ delete plotObj . _ev ;
164+ delete plotObj . _internalEv ;
165+ delete plotObj . _internalOn ;
166+ delete plotObj . _internalOnce ;
167+ delete plotObj . _removeInternalListener ;
168+ delete plotObj . _removeAllInternalListeners ; ;
169+
127170 return plotObj ;
128171 }
129172
0 commit comments