環境
- jQuery 3.3.1
以下のHTMLを使います。
<input type="text" required value="test"> <!-- valid -->
<input type="text" required> <!-- invalid(requiedなのにvalueがない) -->
<input type="text" required disabled>
See the Pen $("input:enabled:invalid ")の確認 by yuji38kwmt (@yuji38kwmt) on CodePen.
問題
以下のJavaScriptをChromeで実行したところ、$("input:enabled:invalid").length
でSyntax Errorが発生しました。
$("input:enabled:invalid").length; //⇒Syntax Error ("1"を期待していた)
$("input:enabled").length; //⇒2
$("input:invalid").length; //⇒1
$("input.not-exists:enabled:invalid").length; //⇒0("input.not-exists"は存在しない要素)
Error: Syntax error, unrecognized expression: unsupported pseudo: invalid
at Function.Sizzle.error (jquery-3.3.1.js:1541)
at PSEUDO (jquery-3.3.1.js:1888)
at matcherFromTokens (jquery-3.3.1.js:2437)
at Sizzle.compile (jquery-3.3.1.js:2591)
at Sizzle.select (jquery-3.3.1.js:2677)
at Function.Sizzle [as find] (jquery-3.3.1.js:845)
at jQuery.fn.init.find (jquery-3.3.1.js:2873)
at new jQuery.fn.init (jquery-3.3.1.js:2983)
at jQuery (jquery-3.3.1.js:139)
at sample.html:36
他のブラウザで検証した結果
ブラウザ | 結果 |
---|---|
Google Chrome 65.0.3325.181 | NG |
Internet Explorer 11.309.16299.0 | NG |
Microsoft Edge 41.16299.248.0 | OK |
Firefox 59.0.1 | OK |
エラーの調査
"PSEUDO": function( pseudo, argument ) {
// pseudo-class names are case-insensitive
// http://www.w3.org/TR/selectors/#pseudo-classes
// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
// Remember that setFilters inherits from pseudos
var args,
fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
Sizzle.error( "unsupported pseudo: " + pseudo );
// The user may use createPseudo to indicate that
// arguments are needed to create the filter function
// just as Sizzle does
if ( fn[ expando ] ) {
return fn( argument );
}
// But maintain support for old signatures
if ( fn.length > 1 ) {
args = [ pseudo, pseudo, "", argument ];
return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
markFunction(function( seed, matches ) {
var idx,
matched = fn( seed, argument ),
i = matched.length;
while ( i-- ) {
idx = indexOf( seed, matched[i] );
seed[ idx ] = !( matches[ idx ] = matched[i] );
}
}) :
function( elem ) {
return fn( elem, 0, args );
};
}
return fn;
}
at PSEUDO (jquery-3.3.1.js:1888)
は、以下の処理です。
var args,
fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
Sizzle.error( "unsupported pseudo: " + pseudo );
Expr.pseudos[ pseudo ]
, Expr.setFilters[ pseudo.toLowerCase() ]
がundefined or nullのため、Sizzle.error
が呼ばれたようです。
以下の場合、1888行目の処理を通りませんでした。
- Firefoxで、
$("input:enabled:invalid").length
を実行したとき - Chromeで、
$("input:invalid").length
を実行したとき
これ以上のことは分かりませんでした。
【補足】document.querySelectorAll
の場合
Chromeでエラーは発生しませんでした。
document.querySelectorAll("input:enabled").length; //⇒2
document.querySelectorAll("input:invalid").length; //⇒1
document.querySelectorAll("input:enabled:invalid").length; //⇒1
【補足】 CSSの場合
期待通りの結果でした(CodePen参照)。
input:enabled {
border-left-color: red;
}
input:invalid {
border-right-color: red;
}
input:enabled:invalid {
border-top-color: red;
}
そもそもやりたかったこと
Enabled/Disabledが切り替わるテキストボックスに対して、入力チェックをしたいです。
そのため、$("input:enabled:invalid")
と記述しました。
しかし$("input:invalid")
でDisabledのテキストボックスが除外されたので、$("input:invalid")
で私のやりたいことは実現できました。
感想
GitHubにIssueを出して、回答をいただきました。
https://github.com/jquery/jquery/issues/4021
Thank you for opening an issue! However, the :invalid selector is not officially supported in jQuery. It works natively, but Sizzle doesn't trust native qSA with :enabled/:disabled due to a certain qSA bug in Chrome. There are a couple workarounds.
そもそもjQueryは:invalid
をサポートしていませんでした。
確かに公式サイトに:invalid
は掲載されていませんね。
https://api.jquery.com/category/selectors/
-
qSA
はdocument.querySelectorAll
のことだと思います。
$("input").filter(":invalid")
でも同様のエラーが発生します。