Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
J
jquery
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
夏彬
jquery
Commits
a763ae72
Commit
a763ae72
authored
Dec 09, 2012
by
Richard Gibson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix #11115: Normalize boolean attributes/properties. Close gh-1066.
parent
55a8ba52
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
116 additions
and
95 deletions
+116
-95
attributes.js
src/attributes.js
+50
-33
support.js
src/support.js
+1
-1
attributes.js
test/unit/attributes.js
+50
-58
selector.js
test/unit/selector.js
+10
-2
traversing.js
test/unit/traversing.js
+5
-1
No files found.
src/attributes.js
View file @
a763ae72
...
...
@@ -3,8 +3,10 @@ var nodeHook, boolHook,
rreturn
=
/
\r
/g
,
rfocusable
=
/^
(?:
input|select|textarea|button|object
)
$/i
,
rclickable
=
/^
(?:
a|area
)
$/i
,
rboolean
=
/^
(?:
autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected
)
$/i
,
getSetAttribute
=
jQuery
.
support
.
getSetAttribute
;
rboolean
=
/^
(?:
checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped
)
$/i
,
ruseDefault
=
/^
(?:
checked|selected
)
$/i
,
getSetAttribute
=
jQuery
.
support
.
getSetAttribute
,
getSetInput
=
jQuery
.
support
.
input
;
jQuery
.
fn
.
extend
({
attr
:
function
(
name
,
value
)
{
...
...
@@ -338,26 +340,31 @@ jQuery.extend({
},
removeAttr
:
function
(
elem
,
value
)
{
var
name
,
propName
,
isBool
,
var
name
,
propName
,
i
=
0
,
attrNames
=
value
&&
value
.
match
(
core_rnotwhite
);
if
(
attrNames
&&
elem
.
nodeType
===
1
)
{
while
(
(
name
=
attrNames
[
i
++
])
)
{
propName
=
jQuery
.
propFix
[
name
]
||
name
;
isBool
=
rboolean
.
test
(
name
);
// Boolean attributes get special treatment (#10870)
if
(
rboolean
.
test
(
name
)
)
{
// Set corresponding property to false for boolean attributes
// Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
if
(
!
getSetAttribute
&&
ruseDefault
.
test
(
name
)
)
{
elem
[
jQuery
.
camelCase
(
"default-"
+
name
)
]
=
elem
[
propName
]
=
false
;
}
else
{
elem
[
propName
]
=
false
;
}
// See #9699 for explanation of this approach (setting first, then removal)
// Do not do this for boolean attributes (see #10870)
if
(
!
isBool
)
{
}
else
{
jQuery
.
attr
(
elem
,
name
,
""
);
}
elem
.
removeAttribute
(
getSetAttribute
?
name
:
propName
);
// Set corresponding property to false for boolean attributes
if
(
isBool
&&
propName
in
elem
)
{
elem
[
propName
]
=
false
;
}
elem
.
removeAttribute
(
getSetAttribute
?
name
:
propName
);
}
}
},
...
...
@@ -449,36 +456,48 @@ jQuery.extend({
// Hook for boolean attributes
boolHook
=
{
get
:
function
(
elem
,
name
)
{
// Align boolean attributes with corresponding properties
// Fall back to attribute presence where some booleans are not supported
var
attrNode
,
property
=
jQuery
.
prop
(
elem
,
name
);
return
property
===
true
||
typeof
property
!==
"boolean"
&&
(
attrNode
=
elem
.
getAttributeNode
(
name
)
)
&&
attrNode
.
nodeValue
!==
false
?
var
// Use .prop to determine if this attribute is understood as boolean
prop
=
jQuery
.
prop
(
elem
,
name
),
// Fetch it accordingly
attr
=
typeof
prop
===
"boolean"
&&
elem
.
getAttribute
(
name
),
detail
=
typeof
prop
===
"boolean"
?
getSetInput
&&
getSetAttribute
?
attr
!=
null
:
// oldIE fabricates an empty string for missing boolean attributes
// and conflates checked/selected into attroperties
ruseDefault
.
test
(
name
)
?
elem
[
jQuery
.
camelCase
(
"default-"
+
name
)
]
:
!!
attr
:
// fetch an attribute node for properties not recognized as boolean
elem
.
getAttributeNode
(
name
);
return
detail
&&
detail
.
value
!==
false
?
name
.
toLowerCase
()
:
undefined
;
},
set
:
function
(
elem
,
value
,
name
)
{
var
propName
;
if
(
value
===
false
)
{
// Remove boolean attributes when set to false
jQuery
.
removeAttr
(
elem
,
name
);
}
else
{
// value is true since we know at this point it's type boolean and not false
// Set boolean attributes to the same name and set the DOM property
propName
=
jQuery
.
propFix
[
name
]
||
name
;
if
(
propName
in
elem
)
{
// Only set the IDL specifically if it already exists on the element
elem
[
propName
]
=
true
;
}
}
else
if
(
getSetInput
&&
getSetAttribute
||
!
ruseDefault
.
test
(
name
)
)
{
// IE<8 needs the *property* name
elem
.
setAttribute
(
!
getSetAttribute
&&
jQuery
.
propFix
[
name
]
||
name
,
name
);
elem
.
setAttribute
(
name
,
name
.
toLowerCase
()
);
// Use defaultChecked and defaultSelected for oldIE
}
else
{
elem
[
jQuery
.
camelCase
(
"default-"
+
name
)
]
=
true
;
}
return
name
;
}
};
// fix oldIE value attroperty
if
(
!
getSet
Attribute
||
!
jQuery
.
support
.
value
Attribute
)
{
if
(
!
getSet
Input
||
!
getSet
Attribute
)
{
jQuery
.
attrHooks
.
value
=
{
get
:
function
(
elem
,
name
)
{
var
ret
=
elem
.
getAttributeNode
(
name
);
...
...
@@ -524,12 +543,10 @@ if ( !getSetAttribute ) {
ret
.
value
=
value
+=
""
;
// Break association with cloned elements (#9646)
if
(
name
!==
"value"
&&
value
!==
elem
.
getAttribute
(
name
)
)
{
elem
.
setAttribute
(
name
,
value
);
}
return
value
;
// Break association with cloned elements by also using setAttribute (#9646)
return
name
===
"value"
||
value
===
elem
.
getAttribute
(
name
)
?
value
:
undefined
;
}
};
...
...
src/support.js
View file @
a763ae72
...
...
@@ -122,7 +122,7 @@ jQuery.support = (function() {
// Check if we can trust getAttribute("value")
input
=
document
.
createElement
(
"input"
);
input
.
setAttribute
(
"value"
,
""
);
support
.
valueAttribute
=
input
.
getAttribute
(
"value"
)
===
""
;
support
.
input
=
input
.
getAttribute
(
"value"
)
===
""
;
// Check if an input maintains its value after becoming a radio
input
.
value
=
"t"
;
...
...
test/unit/attributes.js
View file @
a763ae72
...
...
@@ -123,7 +123,7 @@ test( "attr(String)", function() {
optgroup
.
appendChild
(
option
);
select
.
appendChild
(
optgroup
);
equal
(
jQuery
(
option
).
attr
(
"selected"
),
"selected"
,
"Make sure that a single option is selected, even when in an optgroup."
);
equal
(
jQuery
(
option
).
prop
(
"selected"
),
true
,
"Make sure that a single option is selected, even when in an optgroup."
);
var
$img
=
jQuery
(
"<img style='display:none' width='215' height='53' src='data/1x1.jpg'/>"
).
appendTo
(
"body"
);
equal
(
$img
.
attr
(
"width"
),
"215"
,
"Retrieve width attribute an an element with display:none."
);
...
...
@@ -247,13 +247,14 @@ test( "attr(Hash)", function() {
});
test
(
"attr(String, Object)"
,
function
()
{
expect
(
79
);
expect
(
67
);
var
div
=
jQuery
(
"div"
).
attr
(
"foo"
,
"bar"
),
i
=
0
,
fail
=
false
;
for
(
var
i
=
0
;
i
<
div
.
size
()
;
i
++
)
{
if
(
div
.
get
(
i
).
getAttribute
(
"foo"
)
!
=
"bar"
)
{
for
(
;
i
<
div
.
length
;
i
++
)
{
if
(
div
[
i
].
getAttribute
(
"foo"
)
!=
=
"bar"
)
{
fail
=
i
;
break
;
}
...
...
@@ -272,6 +273,7 @@ test( "attr(String, Object)", function() {
equal
(
jQuery
(
"#name"
).
attr
(
"name"
),
"something"
,
"Set name attribute"
);
jQuery
(
"#name"
).
attr
(
"name"
,
null
);
equal
(
jQuery
(
"#name"
).
attr
(
"name"
),
undefined
,
"Remove name attribute"
);
var
$input
=
jQuery
(
"<input>"
,
{
name
:
"something"
,
id
:
"specified"
...
...
@@ -279,66 +281,55 @@ test( "attr(String, Object)", function() {
equal
(
$input
.
attr
(
"name"
),
"something"
,
"Check element creation gets/sets the name attribute."
);
equal
(
$input
.
attr
(
"id"
),
"specified"
,
"Check element creation gets/sets the id attribute."
);
jQuery
(
"#check2"
).
prop
(
"checked"
,
true
).
prop
(
"checked"
,
false
).
attr
(
"checked"
,
true
);
equal
(
document
.
getElementById
(
"check2"
).
checked
,
true
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
prop
(
"checked"
),
true
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
attr
(
"checked"
),
"checked"
,
"Set checked attribute"
);
jQuery
(
"#check2"
).
attr
(
"checked"
,
false
);
equal
(
document
.
getElementById
(
"check2"
).
checked
,
false
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
prop
(
"checked"
),
false
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
attr
(
"checked"
),
undefined
,
"Set checked attribute"
);
jQuery
(
"#text1"
).
attr
(
"readonly"
,
true
);
equal
(
document
.
getElementById
(
"text1"
).
readOnly
,
true
,
"Set readonly attribute"
);
equal
(
jQuery
(
"#text1"
).
prop
(
"readOnly"
),
true
,
"Set readonly attribute"
);
equal
(
jQuery
(
"#text1"
).
attr
(
"readonly"
),
"readonly"
,
"Set readonly attribute"
);
jQuery
(
"#text1"
).
attr
(
"readonly"
,
false
);
equal
(
document
.
getElementById
(
"text1"
).
readOnly
,
false
,
"Set readonly attribute"
);
equal
(
jQuery
(
"#text1"
).
prop
(
"readOnly"
),
false
,
"Set readonly attribute"
);
equal
(
jQuery
(
"#text1"
).
attr
(
"readonly"
),
undefined
,
"Set readonly attribute"
);
jQuery
(
"#check2"
).
prop
(
"checked"
,
true
);
equal
(
document
.
getElementById
(
"check2"
).
checked
,
true
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
prop
(
"checked"
),
true
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
attr
(
"checked"
),
"checked"
,
"Set checked attribute"
);
jQuery
(
"#check2"
).
prop
(
"checked"
,
false
);
equal
(
document
.
getElementById
(
"check2"
).
checked
,
false
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
prop
(
"checked"
),
false
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
attr
(
"checked"
),
undefined
,
"Set checked attribute"
);
jQuery
(
"#check2"
).
attr
(
"checked"
,
"checked"
);
equal
(
document
.
getElementById
(
"check2"
).
checked
,
true
,
"Set checked attribute with 'checked'"
);
equal
(
jQuery
(
"#check2"
).
prop
(
"checked"
),
true
,
"Set checked attribute"
);
equal
(
jQuery
(
"#check2"
).
attr
(
"checked"
),
"checked"
,
"Set checked attribute"
);
QUnit
.
reset
();
// As of fixing #11115, we make no promises about the effect of .attr on boolean properties
$input
=
jQuery
(
"#check2"
);
$input
.
prop
(
"checked"
,
true
).
prop
(
"checked"
,
false
).
attr
(
"checked"
,
true
);
equal
(
$input
.
attr
(
"checked"
),
"checked"
,
"Set checked (verified by .attr)"
);
$input
.
prop
(
"checked"
,
false
).
prop
(
"checked"
,
true
).
attr
(
"checked"
,
false
);
equal
(
$input
.
attr
(
"checked"
),
undefined
,
"Remove checked (verified by .attr)"
);
$input
=
jQuery
(
"#text1"
).
prop
(
"readOnly"
,
true
).
prop
(
"readOnly"
,
false
).
attr
(
"readonly"
,
true
);
equal
(
$input
.
attr
(
"readonly"
),
"readonly"
,
"Set readonly (verified by .attr)"
);
$input
.
prop
(
"readOnly"
,
false
).
prop
(
"readOnly"
,
true
).
attr
(
"readonly"
,
false
);
equal
(
$input
.
attr
(
"readonly"
),
undefined
,
"Remove readonly (verified by .attr)"
);
$input
=
jQuery
(
"#check2"
).
attr
(
"checked"
,
true
).
attr
(
"checked"
,
false
).
prop
(
"checked"
,
true
);
equal
(
$input
[
0
].
checked
,
true
,
"Set checked property (verified by native property)"
);
equal
(
$input
.
prop
(
"checked"
),
true
,
"Set checked property (verified by .prop)"
);
equal
(
$input
.
attr
(
"checked"
),
undefined
,
"Setting checked property doesn't affect checked attribute"
);
$input
.
attr
(
"checked"
,
false
).
attr
(
"checked"
,
true
).
prop
(
"checked"
,
false
);
equal
(
$input
[
0
].
checked
,
false
,
"Clear checked property (verified by native property)"
);
equal
(
$input
.
prop
(
"checked"
),
false
,
"Clear checked property (verified by .prop)"
);
equal
(
$input
.
attr
(
"checked"
),
"checked"
,
"Clearing checked property doesn't affect checked attribute"
);
$input
=
jQuery
(
"#check2"
).
attr
(
"checked"
,
false
).
attr
(
"checked"
,
"checked"
);
equal
(
$input
.
attr
(
"checked"
),
"checked"
,
"Set checked to 'checked' (verified by .attr)"
);
var
$radios
=
jQuery
(
"#checkedtest"
).
find
(
"input[type='radio']"
);
$radios
.
eq
(
1
).
click
();
equal
(
$radios
.
eq
(
1
).
prop
(
"checked"
),
true
,
"Second radio was checked when clicked"
);
equal
(
$radios
.
attr
(
"checked"
),
$radios
[
0
].
checked
?
"checked"
:
undefined
,
"Known booleans do not fall back to attribute presence (#10278)"
);
jQuery
(
"#text1"
).
prop
(
"readOnly"
,
true
);
equal
(
document
.
getElementById
(
"text1"
).
readOnly
,
true
,
"Set readonly attribute"
);
equal
(
jQuery
(
"#text1"
).
prop
(
"readOnly"
),
true
,
"Set readonly attribute"
);
equal
(
jQuery
(
"#text1"
).
attr
(
"readonly"
),
"readonly"
,
"Set readonly attribute"
);
jQuery
(
"#text1"
).
prop
(
"readOnly"
,
false
);
equal
(
document
.
getElementById
(
"text1"
).
readOnly
,
false
,
"Set readonly attribute"
);
equal
(
jQuery
(
"#text1"
).
prop
(
"readOnly"
),
false
,
"Set readonly attribute"
);
equal
(
jQuery
(
"#text1"
).
attr
(
"readonly"
),
undefined
,
"Set readonly attribute"
);
jQuery
(
"#name"
).
attr
(
"maxlength"
,
"5"
);
equal
(
document
.
getElementById
(
"name"
).
maxLength
,
5
,
"Set maxlength attribute"
);
jQuery
(
"#name"
).
attr
(
"maxLength"
,
"10"
);
equal
(
document
.
getElementById
(
"name"
).
maxLength
,
10
,
"Set maxlength attribute"
);
equal
(
$radios
.
eq
(
0
).
attr
(
"checked"
),
"checked"
,
"First radio is still [checked]"
);
$input
=
jQuery
(
"#text1"
).
attr
(
"readonly"
,
false
).
prop
(
"readOnly"
,
true
);
equal
(
$input
[
0
].
readOnly
,
true
,
"Set readonly property (verified by native property)"
);
equal
(
$input
.
prop
(
"readOnly"
),
true
,
"Set readonly property (verified by .prop)"
);
$input
.
attr
(
"readonly"
,
true
).
prop
(
"readOnly"
,
false
);
equal
(
$input
[
0
].
readOnly
,
false
,
"Clear readonly property (verified by native property)"
);
equal
(
$input
.
prop
(
"readOnly"
),
false
,
"Clear readonly property (verified by .prop)"
);
$input
=
jQuery
(
"#name"
).
attr
(
"maxlength"
,
"5"
);
equal
(
$input
[
0
].
maxLength
,
5
,
"Set maxlength (verified by native property)"
);
$input
.
attr
(
"maxLength"
,
"10"
);
equal
(
$input
[
0
].
maxLength
,
10
,
"Set maxlength (verified by native property)"
);
// HTML5 boolean attributes
var
$text
=
jQuery
(
"#text1"
).
attr
({
"autofocus"
:
true
,
"required"
:
true
});
equal
(
$text
.
attr
(
"autofocus"
),
"autofocus"
,
"
Set boolean attributes to the same name
"
);
equal
(
$text
.
attr
(
"autofocus"
,
false
).
attr
(
"autofocus"
),
undefined
,
"Setting autofocus
attribute
to false removes it"
);
equal
(
$text
.
attr
(
"required"
),
"required"
,
"
Set boolean attributes to the same name
"
);
equal
(
$text
.
attr
(
"autofocus"
),
"autofocus"
,
"
Reading autofocus attribute yields 'autofocus'
"
);
equal
(
$text
.
attr
(
"autofocus"
,
false
).
attr
(
"autofocus"
),
undefined
,
"Setting autofocus to false removes it"
);
equal
(
$text
.
attr
(
"required"
),
"required"
,
"
Reading required attribute yields 'required'
"
);
equal
(
$text
.
attr
(
"required"
,
false
).
attr
(
"required"
),
undefined
,
"Setting required attribute to false removes it"
);
var
$details
=
jQuery
(
"<details open></details>"
).
appendTo
(
"#qunit-fixture"
);
...
...
@@ -368,13 +359,14 @@ test( "attr(String, Object)", function() {
strictEqual
(
$elem
.
attr
(
"nonexisting"
),
undefined
,
"attr(name, value) works correctly on comment and text nodes (bug #7500)."
);
});
// Register the property name to avoid generating a new global when testing window
Globals
.
register
(
"nonexisting"
);
jQuery
.
each
(
[
window
,
document
,
obj
,
"#firstp"
],
function
(
i
,
elem
)
{
// use iframeCallback to avoid generating a new global when testing window
var
oldVal
=
elem
.
iframeCallback
,
var
oldVal
=
elem
.
nonexisting
,
$elem
=
jQuery
(
elem
);
strictEqual
(
$elem
.
attr
(
"nonexisting"
),
undefined
,
"attr works correctly for non existing attributes (bug #7500)."
);
equal
(
$elem
.
attr
(
"
iframeCallback"
,
"foo"
).
attr
(
"iframeCallback
"
),
"foo"
,
"attr falls back to prop on unsupported arguments"
);
elem
.
iframeCallback
=
oldVal
;
equal
(
$elem
.
attr
(
"
nonexisting"
,
"foo"
).
attr
(
"nonexisting
"
),
"foo"
,
"attr falls back to prop on unsupported arguments"
);
elem
.
nonexisting
=
oldVal
;
});
var
table
=
jQuery
(
"#table"
).
append
(
"<tr><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr>"
),
...
...
test/unit/selector.js
View file @
a763ae72
...
...
@@ -31,7 +31,7 @@ test("class - jQuery only", function() {
});
test
(
"attributes - jQuery only"
,
function
()
{
expect
(
4
);
expect
(
6
);
t
(
"Find elements with a tabindex attribute"
,
"[tabindex]"
,
[
"listWithTabIndex"
,
"foodWithNegativeTabIndex"
,
"linkWithTabIndex"
,
"linkWithNegativeTabIndex"
,
"linkWithNoHrefWithTabIndex"
,
"linkWithNoHrefWithNegativeTabIndex"
]
);
...
...
@@ -53,6 +53,14 @@ test("attributes - jQuery only", function() {
ok
(
jQuery
(
"<input type='text' value='12600'/>"
).
prop
(
"value"
,
"option"
).
is
(
":input[value='12600']"
),
":input[value=foo] selects text input by attribute"
);
// #11115
ok
(
jQuery
(
"<input type='checkbox' checked='checked'/>"
).
prop
(
"checked"
,
false
).
is
(
"[checked]"
),
"[checked] selects by attribute (positive)"
);
ok
(
!
jQuery
(
"<input type='checkbox'/>"
).
prop
(
"checked"
,
true
).
is
(
"[checked]"
),
"[checked] selects by attribute (negative)"
);
});
if
(
jQuery
.
css
)
{
...
...
@@ -83,7 +91,7 @@ test("disconnected nodes", function() {
var
$opt
=
jQuery
(
"<option></option>"
).
attr
(
"value"
,
"whipit"
).
appendTo
(
"#qunit-fixture"
).
detach
();
equal
(
$opt
.
val
(),
"whipit"
,
"option value"
);
equal
(
$opt
.
is
(
":selected"
),
false
,
"unselected option"
);
$opt
.
attr
(
"selected"
,
true
);
$opt
.
prop
(
"selected"
,
true
);
equal
(
$opt
.
is
(
":selected"
),
true
,
"selected option"
);
var
$div
=
jQuery
(
"<div/>"
);
...
...
test/unit/traversing.js
View file @
a763ae72
...
...
@@ -329,7 +329,11 @@ test("not(Selector|undefined)", function() {
equal
(
jQuery
(
"#qunit-fixture > p#ap > a"
).
not
(
"#google"
).
length
,
2
,
"not('selector')"
);
deepEqual
(
jQuery
(
"p"
).
not
(
".result"
).
get
(),
q
(
"firstp"
,
"ap"
,
"sndp"
,
"en"
,
"sap"
,
"first"
),
"not('.class')"
);
deepEqual
(
jQuery
(
"p"
).
not
(
"#ap, #sndp, .result"
).
get
(),
q
(
"firstp"
,
"en"
,
"sap"
,
"first"
),
"not('selector, selector')"
);
deepEqual
(
jQuery
(
"#form option"
).
not
(
"option.emptyopt:contains('Nothing'),[selected],[value='1']"
).
get
(),
q
(
"option1c"
,
"option1d"
,
"option2c"
,
"option3d"
,
"option3e"
,
"option4e"
,
"option5b"
),
"not('complex selector')"
);
deepEqual
(
jQuery
(
"#form option"
).
not
(
"option.emptyopt:contains('Nothing'),optgroup *,[value='1']"
).
get
(),
q
(
"option1c"
,
"option1d"
,
"option2c"
,
"option2d"
,
"option3c"
,
"option3d"
,
"option3e"
,
"option4d"
,
"option4e"
,
"option5a"
,
"option5b"
),
"not('complex selector')"
);
deepEqual
(
jQuery
(
"#ap *"
).
not
(
"code"
).
get
(),
q
(
"google"
,
"groups"
,
"anchor1"
,
"mark"
),
"not('tag selector')"
);
deepEqual
(
jQuery
(
"#ap *"
).
not
(
"code, #mark"
).
get
(),
q
(
"google"
,
"groups"
,
"anchor1"
),
"not('tag, ID selector')"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment