Selector: Make empty attribute selectors work in IE again

qSA in IE 11/Edge often (but not always) don't find elements with an empty
name attribute selector (`[name=""]`). Detect that & fall back to Sizzle
traversal.

Interestingly, IE 10 & older don't seem to have the issue.

Fixes gh-4435
Closes gh-4510
This commit is contained in:
Michał Gołębiowski-Owczarek 2019-11-18 22:10:55 +01:00 committed by GitHub
parent d0ce00cdfa
commit 05184cc448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 9 deletions

View File

@ -5,6 +5,7 @@ import documentElement from "./var/documentElement.js";
import indexOf from "./var/indexOf.js";
import pop from "./var/pop.js";
import push from "./var/push.js";
import whitespace from "./selector/var/whitespace.js";
import rbuggyQSA from "./selector/rbuggyQSA.js";
import support from "./selector/support.js";
@ -41,9 +42,6 @@ var i,
// Regular expressions
// https://www.w3.org/TR/css3-selectors/#whitespace
whitespace = "[\\x20\\t\\r\\n\\f]",
// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",

View File

@ -1,8 +1,10 @@
import document from "../var/document.js";
import isIE from "../var/isIE.js";
import whitespace from "./var/whitespace.js";
var rbuggyQSA = [],
testEl = document.createElement( "div" );
testEl = document.createElement( "div" ),
input = document.createElement( "input" );
testEl.innerHTML = "<a href=''></a>";
@ -19,6 +21,18 @@ if ( isIE ) {
rbuggyQSA.push( ":enabled", ":disabled" );
}
// Support: IE 11+, Edge 15 - 18+
// IE 11/Edge don't find elements on a `[name='']` query in some cases.
// Adding a temporary attribute to the document before the selection works
// around the issue.
// Interestingly, IE 10 & older don't seem to have the issue.
input.setAttribute( "name", "" );
testEl.appendChild( input );
if ( !testEl.querySelectorAll( "[name='']" ).length ) {
rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
whitespace + "*(?:''|\"\")" );
}
rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
export default rbuggyQSA;

View File

@ -0,0 +1,2 @@
// https://www.w3.org/TR/css3-selectors/#whitespace
export default "[\\x20\\t\\r\\n\\f]";

View File

@ -116,6 +116,11 @@ Z</textarea>
<input type="radio" name="R1" value="2" />
<input type="text" name="My Name" value="me" />
<input type="reset" name="reset" value="NO" />
<div class="empty-name-container">
<div id="empty-name-parent">
<input type="text" id="name-empty" name="" value="" />
</div>
</div>
<select name="S1">
<option value="abc">ABC</option>
<option value="abc">ABC</option>

File diff suppressed because one or more lines are too long

View File

@ -1255,7 +1255,7 @@ QUnit.test( "addClass(Array)", function( assert ) {
} );
QUnit.test( "addClass(Function) with incoming value", function( assert ) {
assert.expect( 57 );
assert.expect( 59 );
var pass, i,
div = jQuery( "#qunit-fixture div" ),
old = div.map( function() {
@ -1330,7 +1330,7 @@ QUnit.test( "removeClass(Array) - simple", function( assert ) {
} );
QUnit.test( "removeClass(Function) with incoming value", function( assert ) {
assert.expect( 57 );
assert.expect( 59 );
var $divs = jQuery( "#qunit-fixture div" ).addClass( "test" ), old = $divs.map( function() {
return jQuery( this ).attr( "class" );

View File

@ -720,7 +720,7 @@ QUnit.test( "attributes - special characters", function( assert ) {
} );
QUnit.test( "attributes - others", function( assert ) {
assert.expect( 10 );
assert.expect( 14 );
var div = document.getElementById( "foo" );
@ -750,6 +750,17 @@ QUnit.test( "attributes - others", function( assert ) {
assert.ok( !jQuery( "<input type='checkbox'/>" ).prop( "checked", true ).is( "[checked]" ),
"[checked] selects by attribute (negative)"
);
assert.t( "empty name", "[name='']", [ "name-empty" ] );
assert.t( "prefixed empty name", "#empty-name-parent [name='']", [ "name-empty" ] );
var emptyNameContainer = jQuery( ".empty-name-container" );
assert.deepEqual( emptyNameContainer.find( "[name='']" ).get(),
q( "name-empty" ),
"empty name with context" );
assert.deepEqual( emptyNameContainer.find( "#empty-name-parent [name='']" ).get(),
q( "name-empty" ),
"prefixed empty name with context" );
} );
QUnit.test( "pseudo - (parent|empty)", function( assert ) {
@ -1257,7 +1268,7 @@ QUnit[ QUnit.jQuerySelectorsPos ? "test" : "skip" ]( "pseudo - position", functi
assert.t( "Check element position", "#qunit-fixture div div:eq(0)", [ "nothiddendivchild" ] );
assert.t( "Check element position", "#select1 option:eq(3)", [ "option1d" ] );
assert.t( "Check element position", "#qunit-fixture div div:eq(10)", [ "names-group" ] );
assert.t( "Check element position", "#qunit-fixture div div:eq(10)", [ "no-clone-exception" ] );
assert.t( "Check element position", "#qunit-fixture div div:first", [ "nothiddendivchild" ] );
assert.t( "Check element position", "#qunit-fixture div > div:first", [ "nothiddendivchild" ] );
assert.t( "Check element position", "#qunit-fixture div:first a:first", [ "yahoo" ] );