Skip to content

Commit 89af4c2

Browse files
committed
Widget: Untrack classes elements when they are removed from the DOM
Fixes #15043 Closes gh-1744
1 parent 7b7b9b6 commit 89af4c2

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

tests/unit/widget/classes.js

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ QUnit.module( "widget factory classes", {
1515
},
1616
_create: function() {
1717
this.span = $( "<span>" )
18+
.add( "<span>" )
19+
.add( "<span>" )
1820
.appendTo( this.element );
1921

2022
this.element.wrap( "<div>" );
@@ -68,9 +70,9 @@ function elementHasClasses( widget, method, assert ) {
6870
"_" + method + "Class works with ( null, extra" + toggle + " )" );
6971
assert.hasClasses( widget.parent(), "ui-classes-widget ui-theme-widget",
7072
"_" + method + "Class works with ( element, null, extra" + toggle + " )" );
71-
assert.hasClasses( widget.find( "span" ), "ui-classes-span ui-core-span",
73+
assert.hasClasses( widget.find( "span" )[ 0 ], "ui-classes-span ui-core-span",
7274
"_" + method + "Class works with ( element, keys, extra" + toggle + " )" );
73-
assert.hasClasses( widget.find( "span" ), "ui-core-span-null",
75+
assert.hasClasses( widget.find( "span" )[ 0 ], "ui-core-span-null",
7476
"_" + method + "Class works with ( element, keys, null" + toggle + " )" );
7577
}
7678
function elementLacksClasses( widget, method, assert ) {
@@ -84,9 +86,9 @@ function elementLacksClasses( widget, method, assert ) {
8486
"_" + method + "Class works with ( null, extra" + toggle + " )" );
8587
assert.lacksClasses( widget.parent(), "ui-classes-widget ui-theme-widget",
8688
"_" + method + "Class works with ( element, null, extra" + toggle + " )" );
87-
assert.lacksClasses( widget.find( "span" ), "ui-classes-span ui-core-span",
89+
assert.lacksClasses( widget.find( "span" )[ 0 ], "ui-classes-span ui-core-span",
8890
"_" + method + "Class works with ( element, keys, extra" + toggle + " )" );
89-
assert.lacksClasses( widget.find( "span" ), "ui-core-span-null",
91+
assert.lacksClasses( widget.find( "span" )[ 0 ], "ui-core-span-null",
9092
"_" + method + "Class works with ( element, keys, null" + toggle + " )" );
9193
}
9294

@@ -113,7 +115,7 @@ QUnit.test( ".option() - classes setter", function( assert ) {
113115
"Setting to empty value leaves structure class" );
114116
assert.lacksClasses( testWidget.element, "ui-theme-element-2",
115117
"Setting empty value removes previous value classes" );
116-
assert.hasClasses( testWidget.span, "ui-classes-span custom-theme-span",
118+
assert.hasClasses( testWidget.span[ 0 ], "ui-classes-span custom-theme-span",
117119
"Adding a class to an empty value works as expected" );
118120
assert.hasClasses( testWidget.wrapper, "ui-classes-widget custom-theme-widget",
119121
"Appending a class to the current value works as expected" );
@@ -144,4 +146,34 @@ QUnit.test( "._add/_remove/_toggleClass()", function( assert ) {
144146
elementLacksClasses( widget, "remove", assert );
145147
} );
146148

149+
QUnit.test( "Classes elements are untracked as they are removed from the DOM", function( assert ) {
150+
assert.expect( 9 );
151+
152+
var widget = $( "#widget" ).classesWidget();
153+
var instance = widget.classesWidget( "instance" );
154+
155+
assert.equal( instance.classesElementLookup[ "ui-classes-span" ].length, 3,
156+
"Widget is tracking 3 ui-classes-span elements" );
157+
assert.equal( instance.classesElementLookup[ "ui-core-span-null" ].length, 3,
158+
"Widget is tracking 3 ui-core-span-null elements" );
159+
assert.equal( instance.classesElementLookup[ "ui-core-span" ].length, 3,
160+
"Widget is tracking 3 ui-core-span elements" );
161+
162+
widget.find( "span" ).eq( 0 ).remove();
163+
assert.equal( instance.classesElementLookup[ "ui-classes-span" ].length, 2,
164+
"After removing 1 span from dom 2 ui-classes-span elements are tracked" );
165+
assert.equal( instance.classesElementLookup[ "ui-core-span-null" ].length, 2,
166+
"After removing 1 span from dom 2 ui-core-span-null elements are tracked" );
167+
assert.equal( instance.classesElementLookup[ "ui-core-span" ].length, 2,
168+
"After removing 1 span from dom 2 ui-core-span elements are tracked" );
169+
170+
widget.find( "span" ).remove();
171+
assert.equal( instance.classesElementLookup[ "ui-classes-span" ].length, 0,
172+
"No ui-classes-span elements are tracked after removing all spans" );
173+
assert.equal( instance.classesElementLookup[ "ui-core-span-null" ].length, 0,
174+
"No ui-core-span-null elements are tracked after removing all spans" );
175+
assert.equal( instance.classesElementLookup[ "ui-core-span" ].length, 0,
176+
"No ui-core-span elements are tracked after removing all spans" );
177+
} );
178+
147179
} );

ui/widget.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,10 @@ $.Widget.prototype = {
514514
}
515515
}
516516

517+
this._on( options.element, {
518+
"remove": "_untrackClassesElement"
519+
} );
520+
517521
if ( options.keys ) {
518522
processClassString( options.keys.match( /\S+/g ) || [], true );
519523
}
@@ -524,6 +528,15 @@ $.Widget.prototype = {
524528
return full.join( " " );
525529
},
526530

531+
_untrackClassesElement: function( event ) {
532+
var that = this;
533+
$.each( that.classesElementLookup, function( key, value ) {
534+
if ( $.inArray( event.target, value ) !== -1 ) {
535+
that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
536+
}
537+
} );
538+
},
539+
527540
_removeClass: function( element, keys, extra ) {
528541
return this._toggleClass( element, keys, extra, false );
529542
},

0 commit comments

Comments
 (0)