From c87ee3ba902d2980a0e5569e4ff0be415163f0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 16 Nov 2016 14:42:34 -0500 Subject: [PATCH] Widget: Improve `remove` event bindings for `classes` options Fixes #15078 Fixes #15082 Fixes #15095 Fixes #15136 Fixes #15152 --- ui/widget.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/ui/widget.js b/ui/widget.js index 726f70735c9..f876757129a 100644 --- a/ui/widget.js +++ b/ui/widget.js @@ -493,11 +493,29 @@ $.Widget.prototype = { classes: this.options.classes || {} }, options ); + function bindRemoveEvent() { + options.element.each( function( _, element ) { + var isTracked = $.map( that.classesElementLookup, function( elements ) { + return elements; + } ) + .some( function( elements ) { + return elements.is( element ); + } ); + + if ( !isTracked ) { + that._on( $( element ), { + remove: "_untrackClassesElement" + } ); + } + } ); + } + function processClassString( classes, checkOption ) { var current, i; for ( i = 0; i < classes.length; i++ ) { current = that.classesElementLookup[ classes[ i ] ] || $(); if ( options.add ) { + bindRemoveEvent(); current = $( $.unique( current.get().concat( options.element.get() ) ) ); } else { current = $( current.not( options.element ).get() ); @@ -510,10 +528,6 @@ $.Widget.prototype = { } } - this._on( options.element, { - "remove": "_untrackClassesElement" - } ); - if ( options.keys ) { processClassString( options.keys.match( /\S+/g ) || [], true ); } @@ -531,6 +545,8 @@ $.Widget.prototype = { that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); } } ); + + this._off( $( event.target ) ); }, _removeClass: function( element, keys, extra ) { @@ -611,7 +627,7 @@ $.Widget.prototype = { _off: function( element, eventName ) { eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; - element.off( eventName ).off( eventName ); + element.off( eventName ); // Clear the stack to avoid memory leaks (#10056) this.bindings = $( this.bindings.not( element ).get() );