Skip to content

Commit 3b620c5

Browse files
authored
Merge branch 'jquery:main' into master
2 parents 854b1e4 + 0c5becc commit 3b620c5

File tree

7 files changed

+170
-41
lines changed

7 files changed

+170
-41
lines changed

.mailmap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Eric Hynds <eric@hynds.net>
3434
Ethan Romba <ethanromba@gmail.com> <ethan.romba@parivedasolutions.com>
3535
EungJun Yi <semtlenori@gmail.com>
3636
Eyal Kobrigo <kobrigo@hotmail.com>
37+
Felix Nagel <info@felixnagel.com> <fnagel@users.noreply.github.com>
3738
Filippo Cavallarin <filippo.cavallarin@codseq.it> <poplix@papuasia.org>
3839
Florian Gutmann <f.gutmann@chronimo.com> <blackfeet@gmx.at>
3940
Genie <386@mail.com>

AUTHORS.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,3 +363,5 @@ sakshi87 <53863764+sakshi87@users.noreply.github.com>
363363
Mikolaj Wolicki <wolicki.mikolaj@gmail.com>
364364
Patrick McKay <patrick.mckay@vumc.org>
365365
c-lambert <58025159+c-lambert@users.noreply.github.com>
366+
Josep Sanz <josepsanzcamp@gmail.com>
367+
Ben Mullins <benm@umich.edu>

tests/unit/autocomplete/core.js

Lines changed: 69 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ QUnit.test( "simultaneous searches (#9334)", function( assert ) {
293293
} );
294294

295295
QUnit.test( "ARIA", function( assert ) {
296+
var ready = assert.async();
296297
assert.expect( 13 );
297298
var element = $( "#autocomplete" ).autocomplete( {
298299
source: [ "java", "javascript" ]
@@ -308,43 +309,51 @@ QUnit.test( "ARIA", function( assert ) {
308309
"Live region's role attribute must be status" );
309310

310311
element.autocomplete( "search", "j" );
311-
assert.equal( liveRegion.children().first().text(),
312-
"2 results are available, use up and down arrow keys to navigate.",
313-
"Live region for multiple values" );
312+
setTimeout( function() {
313+
assert.equal( liveRegion.children().first().text(),
314+
"2 results are available, use up and down arrow keys to navigate.",
315+
"Live region for multiple values" );
314316

315-
element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
316-
assert.equal( liveRegion.children().filter( ":visible" ).text(), "java",
317-
"Live region changed on keydown to announce the highlighted value" );
317+
element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
318+
setTimeout( function() {
319+
assert.equal( liveRegion.children().filter( ":visible" ).text(), "java",
320+
"Live region changed on keydown to announce the highlighted value" );
318321

319-
element.one( "autocompletefocus", function( event ) {
320-
event.preventDefault();
321-
} );
322-
element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
323-
assert.equal( liveRegion.children().filter( ":visible" ).text(), "javascript",
324-
"Live region updated when default focus is prevented" );
325-
326-
element.autocomplete( "search", "javas" );
327-
assert.equal( liveRegion.children().filter( ":visible" ).text(),
328-
"1 result is available, use up and down arrow keys to navigate.",
329-
"Live region for one value" );
330-
331-
element.autocomplete( "search", "z" );
332-
assert.equal( liveRegion.children().filter( ":visible" ).text(), "No search results.",
333-
"Live region for no values" );
334-
335-
assert.equal( liveRegion.children().length, 5,
336-
"Should be five children in the live region after the above" );
337-
assert.equal( liveRegion.children().filter( ":visible" ).length, 1,
338-
"Only one should be still visible" );
339-
assert.ok( liveRegion.children().filter( ":visible" )[ 0 ] === liveRegion.children().last()[ 0 ],
340-
"The last one should be the visible one" );
341-
342-
element.autocomplete( "destroy" );
343-
assert.equal( liveRegion.parent().length, 0,
344-
"The liveRegion should be detached after destroy" );
322+
element.one( "autocompletefocus", function( event ) {
323+
event.preventDefault();
324+
} );
325+
element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
326+
setTimeout( function() {
327+
assert.equal( liveRegion.children().filter( ":visible" ).text(), "javascript",
328+
"Live region updated when default focus is prevented" );
329+
element.autocomplete( "search", "javas" );
330+
setTimeout( function() {
331+
assert.equal( liveRegion.children().filter( ":visible" ).text(),
332+
"1 result is available, use up and down arrow keys to navigate.",
333+
"Live region for one value" );
334+
element.autocomplete( "search", "z" );
335+
setTimeout( function() {
336+
assert.equal( liveRegion.children().filter( ":visible" ).text(), "No search results.",
337+
"Live region for no values" );
338+
assert.equal( liveRegion.children().length, 1,
339+
"Should be one child in the live region after the above" );
340+
assert.equal( liveRegion.children().filter( ":visible" ).length, 1,
341+
"Only one should be still visible" );
342+
assert.ok( liveRegion.children().filter( ":visible" )[ 0 ] === liveRegion.children().last()[ 0 ],
343+
"The last one should be the visible one" );
344+
element.autocomplete( "destroy" );
345+
assert.equal( liveRegion.parent().length, 0,
346+
"The liveRegion should be detached after destroy" );
347+
ready();
348+
}, 110 );
349+
}, 110 );
350+
}, 110 );
351+
}, 110 );
352+
}, 110 );
345353
} );
346354

347355
QUnit.test( "ARIA, aria-label announcement", function( assert ) {
356+
var ready = assert.async();
348357
assert.expect( 1 );
349358
$.widget( "custom.catcomplete", $.ui.autocomplete, {
350359
_renderMenu: function( ul, items ) {
@@ -361,8 +370,11 @@ QUnit.test( "ARIA, aria-label announcement", function( assert ) {
361370
liveRegion = element.catcomplete( "instance" ).liveRegion;
362371
element.catcomplete( "search", "a" );
363372
element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
364-
assert.equal( liveRegion.children().filter( ":visible" ).text(), "People : anders andersson",
365-
"Live region changed on keydown to announce the highlighted value's aria-label attribute" );
373+
setTimeout( function() {
374+
assert.equal( liveRegion.children().filter( ":visible" ).text(), "People : anders andersson",
375+
"Live region changed on keydown to announce the highlighted value's aria-label attribute" );
376+
ready();
377+
}, 110 );
366378
} );
367379

368380
QUnit.test( "ARIA, init on detached input", function( assert ) {
@@ -431,4 +443,27 @@ QUnit.test( "Close on click outside when focus remains", function( assert ) {
431443
} );
432444
} );
433445

446+
QUnit.test( "extra listeners created during typing (trac-15082, trac-15095)", function( assert ) {
447+
assert.expect( 2 );
448+
449+
var origRemoveListenersCount;
450+
var element = $( "#autocomplete" ).autocomplete( {
451+
source: [ "java", "javascript" ],
452+
delay: 0
453+
} );
454+
455+
element.val( "j" ).autocomplete( "search", "j" );
456+
origRemoveListenersCount = jQuery._data( element[ 0 ], "events" ).remove.length;
457+
458+
element.val( "ja" ).autocomplete( "search", "ja" );
459+
assert.equal( jQuery._data( element[ 0 ], "events" ).remove.length,
460+
origRemoveListenersCount,
461+
"No extra listeners after typing multiple letters" );
462+
463+
element.val( "jav" ).autocomplete( "search", "jav" );
464+
assert.equal( jQuery._data( element[ 0 ], "events" ).remove.length,
465+
origRemoveListenersCount,
466+
"No extra listeners after typing multiple letters" );
467+
} );
468+
434469
} );

tests/unit/selectmenu/core.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,4 +404,34 @@ QUnit.test( "Options with hidden attribute should not be rendered", function( as
404404
} );
405405
} );
406406

407+
QUnit.test( "extra listeners created after selection (trac-15078, trac-15152)", function( assert ) {
408+
assert.expect( 3 );
409+
410+
var origRemoveListenersCount;
411+
var element = $( "#speed" ).selectmenu();
412+
var menu = element.selectmenu( "widget" );
413+
414+
element.val( "Slow" );
415+
element.selectmenu( "refresh" );
416+
origRemoveListenersCount = jQuery._data( menu[ 0 ], "events" ).remove.length;
417+
418+
element.val( "Fast" );
419+
element.selectmenu( "refresh" );
420+
assert.equal( jQuery._data( menu[ 0 ], "events" ).remove.length,
421+
origRemoveListenersCount,
422+
"No extra listeners after typing multiple letters" );
423+
424+
element.val( "Faster" );
425+
element.selectmenu( "refresh" );
426+
assert.equal( jQuery._data( menu[ 0 ], "events" ).remove.length,
427+
origRemoveListenersCount,
428+
"No extra listeners after typing multiple letters" );
429+
430+
element.val( "Slow" );
431+
element.selectmenu( "refresh" );
432+
assert.equal( jQuery._data( menu[ 0 ], "events" ).remove.length,
433+
origRemoveListenersCount,
434+
"No extra listeners after typing multiple letters" );
435+
} );
436+
407437
} );

tests/unit/tabs/core.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,4 +675,56 @@ QUnit.test( "#4033 - IE expands hash to full url and misinterprets tab as ajax",
675675
state( assert, element, 1 );
676676
} );
677677

678+
679+
QUnit.test( "extra listeners created when tabs are added/removed (trac-15136)", function( assert ) {
680+
assert.expect( 3 );
681+
682+
var origRemoveListenersCount;
683+
var element = $( "#tabs1" ).tabs();
684+
var tabCounter = 10;
685+
686+
function addTab() {
687+
var label = "Tab " + tabCounter;
688+
var id = "tabs-" + tabCounter;
689+
var li = $(
690+
"<li>" +
691+
" <a href='#" + id + "'>" + label + "</a> " +
692+
" <span class='ui-icon ui-icon-close' role='presentation'>Remove Tab</span>" +
693+
"</li>"
694+
);
695+
var tabContentHtml = "Tab " + tabCounter + " content.";
696+
697+
element.find( ".ui-tabs-nav" ).append( li );
698+
element.append( "<div id='" + id + "'><p>" + tabContentHtml + "</p></div>" );
699+
element.tabs( "refresh" );
700+
tabCounter++;
701+
}
702+
703+
function removeLastTab() {
704+
element.find( ".ui-icon-close" ).last().trigger( "click" );
705+
}
706+
707+
origRemoveListenersCount = jQuery._data( element[ 0 ], "events" ).remove.length;
708+
709+
addTab();
710+
assert.equal( jQuery._data( element[ 0 ], "events" ).remove.length,
711+
origRemoveListenersCount,
712+
"No extra listeners after adding a new tab" );
713+
714+
addTab();
715+
addTab();
716+
addTab();
717+
assert.equal( jQuery._data( element[ 0 ], "events" ).remove.length,
718+
origRemoveListenersCount,
719+
"No extra listeners after adding multiple tabs" );
720+
721+
removeLastTab();
722+
removeLastTab();
723+
removeLastTab();
724+
removeLastTab();
725+
assert.equal( jQuery._data( element[ 0 ], "events" ).remove.length,
726+
origRemoveListenersCount,
727+
"No extra listeners after removing all the extra tabs" );
728+
} );
729+
678730
} );

ui/widget.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,8 @@ $.Widget.prototype = {
499499
}, options );
500500

501501
function bindRemoveEvent() {
502+
var nodesToBind = [];
503+
502504
options.element.each( function( _, element ) {
503505
var isTracked = $.map( that.classesElementLookup, function( elements ) {
504506
return elements;
@@ -508,11 +510,13 @@ $.Widget.prototype = {
508510
} );
509511

510512
if ( !isTracked ) {
511-
that._on( $( element ), {
512-
remove: "_untrackClassesElement"
513-
} );
513+
nodesToBind.push( element );
514514
}
515515
} );
516+
517+
that._on( $( nodesToBind ), {
518+
remove: "_untrackClassesElement"
519+
} );
516520
}
517521

518522
function processClassString( classes, checkOption ) {

ui/widgets/autocomplete.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ $.widget( "ui.autocomplete", {
6666

6767
requestIndex: 0,
6868
pending: 0,
69+
liveRegionTimer: null,
6970

7071
_create: function() {
7172

@@ -267,8 +268,10 @@ $.widget( "ui.autocomplete", {
267268
// Announce the value in the liveRegion
268269
label = ui.item.attr( "aria-label" ) || item.value;
269270
if ( label && String.prototype.trim.call( label ).length ) {
270-
this.liveRegion.children().hide();
271-
$( "<div>" ).text( label ).appendTo( this.liveRegion );
271+
clearTimeout( this.liveRegionTimer );
272+
this.liveRegionTimer = this._delay( function() {
273+
this.liveRegion.html( $( "<div>" ).text( label ) );
274+
}, 100 );
272275
}
273276
},
274277
menuselect: function( event, ui ) {
@@ -663,8 +666,10 @@ $.widget( "ui.autocomplete", $.ui.autocomplete, {
663666
} else {
664667
message = this.options.messages.noResults;
665668
}
666-
this.liveRegion.children().hide();
667-
$( "<div>" ).text( message ).appendTo( this.liveRegion );
669+
clearTimeout( this.liveRegionTimer );
670+
this.liveRegionTimer = this._delay( function() {
671+
this.liveRegion.html( $( "<div>" ).text( message ) );
672+
}, 100 );
668673
}
669674
} );
670675

0 commit comments

Comments
 (0)