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
7f94a5cc
Commit
7f94a5cc
authored
Feb 03, 2013
by
Rick Waldron
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
2.0: Rewrite data.js (Incl. event, manipulation, tests)
parent
ed0e2d1e
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
354 additions
and
358 deletions
+354
-358
data.js
src/data.js
+214
-227
event.js
src/event.js
+2
-2
manipulation.js
src/manipulation.js
+31
-27
onbeforeunload.html
test/data/onbeforeunload.html
+20
-0
testrunner.js
test/data/testrunner.js
+40
-34
data.js
test/unit/data.js
+36
-2
event.js
test/unit/event.js
+11
-66
No files found.
src/data.js
View file @
7f94a5cc
var
rbrace
=
/
(?:\{[\s\S]
*
\}
|
\[[\s\S]
*
\])
$/
,
var
data_user
,
data_priv
,
rbrace
=
/
(?:\{[\s\S]
*
\}
|
\[[\s\S]
*
\])
$/
,
rmultiDash
=
/
([
A-Z
])
/g
;
rmultiDash
=
/
([
A-Z
])
/g
;
function
internalData
(
elem
,
name
,
data
,
pvt
)
{
function
Data
()
{
if
(
!
jQuery
.
acceptData
(
elem
)
)
{
// Nodes|Objects
return
;
this
.
owners
=
[];
}
// Data objects
this
.
cache
=
[];
var
thisCache
,
ret
,
}
internalKey
=
jQuery
.
expando
,
getByName
=
typeof
name
===
"string"
,
// We have to handle DOM nodes and JS objects differently because IE6-7
// can't GC object references properly across the DOM-JS boundary
isNode
=
elem
.
nodeType
,
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
cache
=
isNode
?
jQuery
.
cache
:
elem
,
// Only defining an ID for JS objects if its cache already exists allows
// the code to shortcut on the same path as a DOM node with no cache
id
=
isNode
?
elem
[
internalKey
]
:
elem
[
internalKey
]
&&
internalKey
;
// Avoid doing any more work than we need to when trying to get data on an
// object that has no data at all
if
(
(
!
id
||
!
cache
[
id
]
||
(
!
pvt
&&
!
cache
[
id
].
data
))
&&
getByName
&&
data
===
undefined
)
{
return
;
}
if
(
!
id
)
{
Data
.
index
=
function
(
array
,
node
)
{
// Only DOM nodes need a new unique ID for each element since their data
return
array
.
indexOf
(
node
);
// ends up in the global cache
};
if
(
isNode
)
{
elem
[
internalKey
]
=
id
=
core_deletedIds
.
pop
()
||
jQuery
.
guid
++
;
}
else
{
id
=
internalKey
;
}
}
if
(
!
cache
[
id
]
)
{
cache
[
id
]
=
{};
// Avoids exposing jQuery metadata on plain JS objects when the object
Data
.
prototype
=
{
// is serialized using JSON.stringify
add
:
function
(
owner
)
{
if
(
!
isNode
)
{
this
.
owners
.
push
(
owner
);
cache
[
id
].
toJSON
=
jQuery
.
noop
;
return
(
this
.
cache
[
this
.
owners
.
length
-
1
]
=
{});
},
set
:
function
(
owner
,
data
,
value
)
{
var
prop
,
index
=
Data
.
index
(
this
.
owners
,
owner
);
// If there is no entry for this "owner", create one inline
// and set the index as though an owner entry had always existed
if
(
index
===
-
1
)
{
this
.
add
(
owner
);
index
=
this
.
owners
.
length
-
1
;
}
}
}
// Handle: [ owner, key, value ] args
if
(
typeof
data
===
"string"
)
{
this
.
cache
[
index
][
data
]
=
value
;
// An object can be passed to jQuery.data instead of a key/value pair; this gets
// Handle: [ owner, { properties } ] args
// shallow copied over onto the existing cache
if
(
typeof
name
===
"object"
||
typeof
name
===
"function"
)
{
if
(
pvt
)
{
cache
[
id
]
=
jQuery
.
extend
(
cache
[
id
],
name
);
}
else
{
}
else
{
cache
[
id
].
data
=
jQuery
.
extend
(
cache
[
id
].
data
,
name
);
// In the case where there was actually no "owner" entry and
}
// this.add( owner ) was called to create one, there will be
}
// a corresponding empty plain object in the cache.
if
(
jQuery
.
isEmptyObject
(
this
.
cache
[
index
]
)
)
{
thisCache
=
cache
[
id
]
;
this
.
cache
[
index
]
=
data
;
// jQuery data() is stored in a separate object inside the object's internal data
// Otherwise, copy the properties one-by-one to the cache object
// cache in order to avoid key collisions between internal data and user-defined
}
else
{
// data.
for
(
prop
in
data
)
{
if
(
!
pvt
)
{
this
.
cache
[
index
][
prop
]
=
data
[
prop
];
if
(
!
thisCache
.
data
)
{
}
thisCache
.
data
=
{};
}
}
}
return
this
;
},
get
:
function
(
owner
,
key
)
{
var
cache
,
index
=
Data
.
index
(
this
.
owners
,
owner
);
// A valid cache is found, or needs to be created.
// New entries will be added and return the current
// empty data object to be used as a return reference
// return this.add( owner );
// This logic was required by expectations made of the
// old data system.
cache
=
index
===
-
1
?
this
.
add
(
owner
)
:
this
.
cache
[
index
];
return
key
===
undefined
?
cache
:
cache
[
key
];
},
access
:
function
(
owner
,
key
,
value
)
{
if
(
value
===
undefined
&&
(
key
&&
typeof
key
!==
"object"
)
)
{
// Assume this is a request to read the cached data
return
this
.
get
(
owner
,
key
);
}
else
{
thisCache
=
thisCache
.
data
;
// If only an owner was specified, return the entire
}
// cache object.
if
(
key
===
undefined
)
{
if
(
data
!==
undefined
)
{
return
this
.
get
(
owner
);
thisCache
[
jQuery
.
camelCase
(
name
)
]
=
data
;
}
}
// Check for both converted-to-camel and non-converted data property names
// If a data property was specified
if
(
getByName
)
{
// First Try to find as-is property data
ret
=
thisCache
[
name
];
// Test for null|undefined property data
if
(
ret
==
null
)
{
// Try to find the camelCased property
// Allow setting or extending (existing objects) with an
ret
=
thisCache
[
jQuery
.
camelCase
(
name
)
];
// object of properties, or a key and val
this
.
set
(
owner
,
key
,
value
);
return
value
!==
undefined
?
value
:
key
;
}
}
}
else
{
// Otherwise, this is a read request.
ret
=
thisCache
;
return
this
.
get
(
owner
,
key
);
}
},
remove
:
function
(
owner
,
key
)
{
return
ret
;
var
i
,
l
,
name
,
}
camel
=
jQuery
.
camelCase
,
index
=
Data
.
index
(
this
.
owners
,
owner
),
function
internalRemoveData
(
elem
,
name
,
pvt
)
{
cache
=
this
.
cache
[
index
];
if
(
!
jQuery
.
acceptData
(
elem
)
)
{
return
;
}
var
thisCache
,
i
,
l
,
isNode
=
elem
.
nodeType
,
// See jQuery.data for more information
cache
=
isNode
?
jQuery
.
cache
:
elem
,
id
=
isNode
?
elem
[
jQuery
.
expando
]
:
jQuery
.
expando
;
// If there is already no cache entry for this object, there is no
// purpose in continuing
if
(
!
cache
[
id
]
)
{
return
;
}
if
(
name
)
{
thisCache
=
pvt
?
cache
[
id
]
:
cache
[
id
].
data
;
if
(
thisCache
)
{
// Support array or space separated string names for data keys
if
(
!
jQuery
.
isArray
(
name
)
)
{
// try the string as a key before any manipulation
if
(
name
in
thisCache
)
{
name
=
[
name
];
}
else
{
// split the camel cased version by spaces unless a key with the spaces exists
if
(
key
===
undefined
)
{
name
=
jQuery
.
camelCase
(
name
);
cache
=
{};
if
(
name
in
thisCache
)
{
}
else
{
name
=
[
name
];
if
(
cache
)
{
// Support array or space separated string of keys
if
(
!
Array
.
isArray
(
key
)
)
{
// Try the string as a key before any manipulation
//
if
(
key
in
cache
)
{
name
=
[
key
];
}
else
{
}
else
{
name
=
name
.
split
(
" "
);
// Split the camel cased version by spaces unless a key with the spaces exists
name
=
camel
(
key
);
name
=
name
in
cache
?
[
name
]
:
name
.
split
(
" "
);
}
}
}
else
{
// If "name" is an array of keys...
// When data is initially created, via ("key", "val") signature,
// keys will be converted to camelCase.
// Since there is no way to tell _how_ a key was added, remove
// both plain key and camelCase key. #12786
// This will only penalize the array argument path.
name
=
key
.
concat
(
key
.
map
(
camel
)
);
}
}
}
else
{
i
=
0
;
// If "name" is an array of keys...
l
=
name
.
length
;
// When data is initially created, via ("key", "val") signature,
// keys will be converted to camelCase.
// Since there is no way to tell _how_ a key was added, remove
// both plain key and camelCase key. #12786
// This will only penalize the array argument path.
name
=
name
.
concat
(
jQuery
.
map
(
name
,
jQuery
.
camelCase
)
);
}
for
(
i
=
0
,
l
=
name
.
length
;
i
<
l
;
i
++
)
{
delete
thisCache
[
name
[
i
]
];
}
// If there is no data left in the cache, we want to continue
for
(
;
i
<
l
;
i
++
)
{
// and let the cache object itself get destroyed
delete
cache
[
name
[
i
]
];
if
(
!
(
pvt
?
isEmptyDataObject
:
jQuery
.
isEmptyObject
)(
thisCache
)
)
{
}
return
;
}
}
}
}
}
this
.
cache
[
index
]
=
cache
;
},
hasData
:
function
(
owner
)
{
var
index
=
Data
.
index
(
this
.
owners
,
owner
);
// See jQuery.data for more information
if
(
index
>
-
1
)
{
if
(
!
pvt
)
{
return
!
jQuery
.
isEmptyObject
(
this
.
cache
[
index
]
);
delete
cache
[
id
].
data
;
}
return
false
;
},
discard
:
function
(
owner
)
{
var
index
=
Data
.
index
(
this
.
owners
,
owner
);
// Don't destroy the parent cache unless the internal data object
if
(
index
>=
0
)
{
// had been the only thing left in it
this
.
owners
.
splice
(
index
,
1
);
if
(
!
isEmptyDataObject
(
cache
[
id
]
)
)
{
this
.
cache
.
splice
(
index
,
1
);
return
;
}
}
return
this
;
}
}
};
// This will be used by remove()/cleanData() in manipulation to sever
// remaining references to node objects. One day we'll replace the dual
// arrays with a WeakMap and this won't be an issue.
// (Splices the data objects out of the internal cache arrays)
function
data_discard
(
owner
)
{
data_user
.
discard
(
owner
);
data_priv
.
discard
(
owner
);
}
// Destroy the cache
// These may be used throughout the jQuery core codebase
if
(
isNode
)
{
data_user
=
new
Data
();
jQuery
.
cleanData
(
[
elem
],
true
);
data_priv
=
new
Data
();
// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
}
else
if
(
jQuery
.
support
.
deleteExpando
||
cache
!=
cache
.
window
)
{
delete
cache
[
id
];
// When all else fails, null
}
else
{
cache
[
id
]
=
null
;
}
}
jQuery
.
extend
({
jQuery
.
extend
({
cache
:
{},
// This is no longer relevant to jQuery core, but must remain
// supported for the sake of jQuery 1.9.x API surface compatibility.
acceptData
:
function
()
{
return
true
;
},
// Unique for each copy of jQuery on the page
// Unique for each copy of jQuery on the page
// Non-digits removed to match rinlinejQuery
// Non-digits removed to match rinlinejQuery
expando
:
"jQuery"
+
(
core_version
+
Math
.
random
()
).
replace
(
/
\D
/g
,
""
),
expando
:
"jQuery"
+
(
core_version
+
Math
.
random
()
).
replace
(
/
\D
/g
,
""
),
// The following elements throw uncatchable exceptions if you
// attempt to add expando properties to them.
noData
:
{
"embed"
:
true
,
// Ban all objects except for Flash (which handle expandos)
"object"
:
"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
,
"applet"
:
true
},
hasData
:
function
(
elem
)
{
hasData
:
function
(
elem
)
{
elem
=
elem
.
nodeType
?
jQuery
.
cache
[
elem
[
jQuery
.
expando
]
]
:
elem
[
jQuery
.
expando
];
return
data_user
.
hasData
(
elem
)
||
data_priv
.
hasData
(
elem
);
return
!!
elem
&&
!
isEmptyDataObject
(
elem
);
},
},
data
:
function
(
elem
,
name
,
data
)
{
data
:
function
(
elem
,
name
,
data
)
{
return
internalData
(
elem
,
name
,
data
);
return
data_user
.
access
(
elem
,
name
,
data
);
},
},
removeData
:
function
(
elem
,
name
)
{
removeData
:
function
(
elem
,
name
)
{
return
internalRemoveData
(
elem
,
name
);
return
data_user
.
remove
(
elem
,
name
);
},
},
// For internal use only.
// TODO: Replace all calls to _data and _removeData with direct
// calls to
//
// data_priv.access( elem, name, data );
//
// data_priv.remove( elem, name );
//
_data
:
function
(
elem
,
name
,
data
)
{
_data
:
function
(
elem
,
name
,
data
)
{
return
internalData
(
elem
,
name
,
data
,
true
);
return
data_priv
.
access
(
elem
,
name
,
data
);
},
},
_removeData
:
function
(
elem
,
name
)
{
_removeData
:
function
(
elem
,
name
)
{
return
internalRemoveData
(
elem
,
name
,
true
);
return
data_priv
.
remove
(
elem
,
name
);
},
// A method for determining if a DOM node can handle the data expando
acceptData
:
function
(
elem
)
{
// Do not set data on non-element because it will not be cleared (#8335).
if
(
elem
.
nodeType
&&
elem
.
nodeType
!==
1
&&
elem
.
nodeType
!==
9
)
{
return
false
;
}
var
noData
=
elem
.
nodeName
&&
jQuery
.
noData
[
elem
.
nodeName
.
toLowerCase
()
];
// nodes accept data unless otherwise specified; rejection can be conditional
return
!
noData
||
noData
!==
true
&&
elem
.
getAttribute
(
"classid"
)
===
noData
;
}
}
});
});
...
@@ -245,20 +209,19 @@ jQuery.fn.extend({
...
@@ -245,20 +209,19 @@ jQuery.fn.extend({
// Gets all values
// Gets all values
if
(
key
===
undefined
)
{
if
(
key
===
undefined
)
{
if
(
this
.
length
)
{
if
(
this
.
length
)
{
data
=
jQuery
.
data
(
elem
);
data
=
data_user
.
get
(
elem
);
if
(
elem
.
nodeType
===
1
&&
!
jQuery
.
_data
(
elem
,
"parsed
Attrs"
)
)
{
if
(
elem
.
nodeType
===
1
&&
!
data_priv
.
get
(
elem
,
"hasData
Attrs"
)
)
{
attrs
=
elem
.
attributes
;
attrs
=
elem
.
attributes
;
for
(
;
i
<
attrs
.
length
;
i
++
)
{
for
(
;
i
<
attrs
.
length
;
i
++
)
{
name
=
attrs
[
i
].
name
;
name
=
attrs
[
i
].
name
;
if
(
!
name
.
indexOf
(
"data-"
)
)
{
if
(
name
.
indexOf
(
"data-"
)
===
0
)
{
name
=
jQuery
.
camelCase
(
name
.
slice
(
5
)
);
name
=
jQuery
.
camelCase
(
name
.
substring
(
5
)
);
dataAttr
(
elem
,
name
,
data
[
name
]
);
dataAttr
(
elem
,
name
,
data
[
name
]
);
}
}
}
}
jQuery
.
_data
(
elem
,
"parsed
Attrs"
,
true
);
data_priv
.
set
(
elem
,
"hasData
Attrs"
,
true
);
}
}
}
}
...
@@ -268,53 +231,94 @@ jQuery.fn.extend({
...
@@ -268,53 +231,94 @@ jQuery.fn.extend({
// Sets multiple values
// Sets multiple values
if
(
typeof
key
===
"object"
)
{
if
(
typeof
key
===
"object"
)
{
return
this
.
each
(
function
()
{
return
this
.
each
(
function
()
{
jQuery
.
data
(
this
,
key
);
data_user
.
set
(
this
,
key
);
});
});
}
}
return
jQuery
.
access
(
this
,
function
(
value
)
{
return
jQuery
.
access
(
this
,
function
(
value
)
{
var
data
,
camelKey
=
jQuery
.
camelCase
(
key
);
// Get the Data...
if
(
value
===
undefined
)
{
if
(
value
===
undefined
)
{
// Try to fetch any internally stored data first
return
elem
?
dataAttr
(
elem
,
key
,
jQuery
.
data
(
elem
,
key
)
)
:
null
;
// Attempt to get data from the cache
// with the key as-is
data
=
data_user
.
get
(
elem
,
key
);
if
(
data
!==
undefined
)
{
return
data
;
}
// Attempt to "discover" the data in
// HTML5 custom data-* attrs
data
=
dataAttr
(
elem
,
key
,
undefined
);
if
(
data
!==
undefined
)
{
return
data
;
}
// As a last resort, attempt to find
// the data by checking AGAIN, but with
// a camelCased key.
data
=
data_user
.
get
(
elem
,
camelKey
);
if
(
data
!==
undefined
)
{
return
data
;
}
// We tried really hard, but the data doesn't exist.
return
undefined
;
}
}
// Set the data...
this
.
each
(
function
()
{
this
.
each
(
function
()
{
jQuery
.
data
(
this
,
key
,
value
);
// First, attempt to store a copy or reference of any
// data that might've been store with a camelCased key.
var
data
=
data_user
.
get
(
this
,
camelKey
);
// For HTML5 data-* attribute interop, we have to
// store property names with dashes in a camelCase form.
// This might not apply to all properties...*
data_user
.
set
(
this
,
camelKey
,
value
);
// *... In the case of properties that might ACTUALLY
// have dashes, we need to also store a copy of that
// unchanged property.
if
(
/-/
.
test
(
key
)
&&
data
!==
undefined
)
{
data_user
.
set
(
this
,
key
,
value
);
}
});
});
},
null
,
value
,
arguments
.
length
>
1
,
null
,
true
);
},
null
,
value
,
arguments
.
length
>
1
,
null
,
true
);
},
},
removeData
:
function
(
key
)
{
removeData
:
function
(
key
)
{
return
this
.
each
(
function
()
{
return
this
.
each
(
function
()
{
jQuery
.
removeData
(
this
,
key
);
data_user
.
remove
(
this
,
key
);
});
});
}
}
});
});
function
dataAttr
(
elem
,
key
,
data
)
{
function
dataAttr
(
elem
,
key
,
data
)
{
var
name
;
// If nothing was found internally, try to fetch any
// If nothing was found internally, try to fetch any
// data from the HTML5 data-* attribute
// data from the HTML5 data-* attribute
if
(
data
===
undefined
&&
elem
.
nodeType
===
1
)
{
if
(
data
===
undefined
&&
elem
.
nodeType
===
1
)
{
var
name
=
"data-"
+
key
.
replace
(
rmultiDash
,
"-$1"
).
toLowerCase
();
name
=
"data-"
+
key
.
replace
(
rmultiDash
,
"-$1"
).
toLowerCase
();
data
=
elem
.
getAttribute
(
name
);
data
=
elem
.
getAttribute
(
name
);
if
(
typeof
data
===
"string"
)
{
if
(
typeof
data
===
"string"
)
{
try
{
try
{
data
=
data
===
"true"
?
true
:
data
=
data
===
"true"
?
true
:
data
===
"false"
?
false
:
data
===
"false"
?
false
:
data
===
"null"
?
null
:
data
===
"null"
?
null
:
// Only convert to a number if it doesn't change the string
// Only convert to a number if it doesn't change the string
+
data
+
""
===
data
?
+
data
:
+
data
+
""
===
data
?
+
data
:
rbrace
.
test
(
data
)
?
jQuery
.
parseJSON
(
data
)
:
rbrace
.
test
(
data
)
?
data
;
JSON
.
parse
(
data
)
:
data
;
}
catch
(
e
)
{}
}
catch
(
e
)
{}
// Make sure we set the data so it isn't changed later
// Make sure we set the data so it isn't changed later
jQuery
.
data
(
elem
,
key
,
data
);
data_user
.
set
(
elem
,
key
,
data
);
}
else
{
}
else
{
data
=
undefined
;
data
=
undefined
;
}
}
...
@@ -322,20 +326,3 @@ function dataAttr( elem, key, data ) {
...
@@ -322,20 +326,3 @@ function dataAttr( elem, key, data ) {
return
data
;
return
data
;
}
}
// checks a cache object for emptiness
function
isEmptyDataObject
(
obj
)
{
var
name
;
for
(
name
in
obj
)
{
// if the public data object is empty, the private is still empty
if
(
name
===
"data"
&&
jQuery
.
isEmptyObject
(
obj
[
name
]
)
)
{
continue
;
}
if
(
name
!==
"toJSON"
)
{
return
false
;
}
}
return
true
;
}
src/event.js
View file @
7f94a5cc
...
@@ -24,7 +24,7 @@ jQuery.event = {
...
@@ -24,7 +24,7 @@ jQuery.event = {
var
handleObjIn
,
eventHandle
,
tmp
,
var
handleObjIn
,
eventHandle
,
tmp
,
events
,
t
,
handleObj
,
events
,
t
,
handleObj
,
special
,
handlers
,
type
,
namespaces
,
origType
,
special
,
handlers
,
type
,
namespaces
,
origType
,
elemData
=
jQuery
.
_data
(
elem
);
elemData
=
data_priv
.
get
(
elem
);
// Don't attach events to noData or text/comment nodes (but allow plain objects)
// Don't attach events to noData or text/comment nodes (but allow plain objects)
if
(
!
elemData
)
{
if
(
!
elemData
)
{
...
@@ -130,7 +130,7 @@ jQuery.event = {
...
@@ -130,7 +130,7 @@ jQuery.event = {
var
j
,
origCount
,
tmp
,
var
j
,
origCount
,
tmp
,
events
,
t
,
handleObj
,
events
,
t
,
handleObj
,
special
,
handlers
,
type
,
namespaces
,
origType
,
special
,
handlers
,
type
,
namespaces
,
origType
,
elemData
=
jQuery
.
hasData
(
elem
)
&&
jQuery
.
_data
(
elem
);
elemData
=
data_priv
.
hasData
(
elem
)
&&
data_priv
.
get
(
elem
);
if
(
!
elemData
||
!
(
events
=
elemData
.
events
)
)
{
if
(
!
elemData
||
!
(
events
=
elemData
.
events
)
)
{
return
;
return
;
...
...
src/manipulation.js
View file @
7f94a5cc
...
@@ -328,7 +328,7 @@ jQuery.fn.extend({
...
@@ -328,7 +328,7 @@ jQuery.fn.extend({
for
(
i
=
0
;
i
<
hasScripts
;
i
++
)
{
for
(
i
=
0
;
i
<
hasScripts
;
i
++
)
{
node
=
scripts
[
i
];
node
=
scripts
[
i
];
if
(
rscriptType
.
test
(
node
.
type
||
""
)
&&
if
(
rscriptType
.
test
(
node
.
type
||
""
)
&&
!
jQuery
.
_data
(
node
,
"globalEval"
)
&&
jQuery
.
contains
(
doc
,
node
)
)
{
!
data_priv
.
access
(
node
,
"globalEval"
)
&&
jQuery
.
contains
(
doc
,
node
)
)
{
if
(
node
.
src
)
{
if
(
node
.
src
)
{
// Hope ajax is available...
// Hope ajax is available...
...
@@ -511,11 +511,9 @@ jQuery.extend({
...
@@ -511,11 +511,9 @@ jQuery.extend({
},
},
cleanData
:
function
(
elems
,
/* internal */
acceptData
)
{
cleanData
:
function
(
elems
,
/* internal */
acceptData
)
{
var
id
,
data
,
elem
,
type
,
var
data
,
elem
,
type
,
l
=
elems
.
length
,
l
=
elems
.
length
,
i
=
0
,
i
=
0
,
internalKey
=
jQuery
.
expando
,
cache
=
jQuery
.
cache
,
special
=
jQuery
.
event
.
special
;
special
=
jQuery
.
event
.
special
;
for
(
;
i
<
l
;
i
++
)
{
for
(
;
i
<
l
;
i
++
)
{
...
@@ -523,8 +521,7 @@ jQuery.extend({
...
@@ -523,8 +521,7 @@ jQuery.extend({
if
(
acceptData
||
jQuery
.
acceptData
(
elem
)
)
{
if
(
acceptData
||
jQuery
.
acceptData
(
elem
)
)
{
id
=
elem
[
internalKey
];
data
=
data_priv
.
access
(
elem
);
data
=
id
&&
cache
[
id
];
if
(
data
)
{
if
(
data
)
{
for
(
type
in
data
.
events
)
{
for
(
type
in
data
.
events
)
{
...
@@ -536,14 +533,10 @@ jQuery.extend({
...
@@ -536,14 +533,10 @@ jQuery.extend({
jQuery
.
removeEvent
(
elem
,
type
,
data
.
handle
);
jQuery
.
removeEvent
(
elem
,
type
,
data
.
handle
);
}
}
}
}
// Remove cache only if it was not already removed by jQuery.event.remove
if
(
cache
[
id
]
)
{
delete
cache
[
id
];
delete
elem
[
internalKey
];
}
}
}
}
}
// Discard any remaining `private` and `user` data
data_discard
(
elem
);
}
}
}
}
});
});
...
@@ -576,38 +569,49 @@ function setGlobalEval( elems, refElements ) {
...
@@ -576,38 +569,49 @@ function setGlobalEval( elems, refElements ) {
i
=
0
;
i
=
0
;
for
(
;
i
<
l
;
i
++
)
{
for
(
;
i
<
l
;
i
++
)
{
jQuery
.
_data
(
elems
[
i
],
"globalEval"
,
!
refElements
||
jQuery
.
_data
(
refElements
[
i
],
"globalEval"
)
);
data_priv
.
set
(
elems
[
i
],
"globalEval"
,
!
refElements
||
data_priv
.
get
(
refElements
[
i
],
"globalEval"
)
);
}
}
}
}
function
cloneCopyEvent
(
src
,
dest
)
{
function
cloneCopyEvent
(
src
,
dest
)
{
var
i
,
l
,
type
,
pdataOld
,
pdataCur
,
udataOld
,
udataCur
,
events
;
if
(
dest
.
nodeType
!==
1
||
!
jQuery
.
hasData
(
src
)
)
{
if
(
dest
.
nodeType
!==
1
)
{
return
;
return
;
}
}
var
i
,
l
,
type
,
// 1. Copy private data: events, handlers, etc.
oldData
=
jQuery
.
_data
(
src
),
if
(
data_priv
.
hasData
(
src
)
)
{
curData
=
jQuery
.
_data
(
dest
,
oldData
),
pdataOld
=
data_priv
.
access
(
src
);
events
=
oldData
.
events
;
pdataCur
=
jQuery
.
extend
(
{},
pdataOld
);
events
=
pdataOld
.
events
;
data_priv
.
set
(
dest
,
pdataCur
);
if
(
events
)
{
if
(
events
)
{
delete
curData
.
handle
;
delete
pdataCur
.
handle
;
curData
.
events
=
{};
pdataCur
.
events
=
{};
for
(
type
in
events
)
{
for
(
type
in
events
)
{
for
(
i
=
0
,
l
=
events
[
type
].
length
;
i
<
l
;
i
++
)
{
for
(
i
=
0
,
l
=
events
[
type
].
length
;
i
<
l
;
i
++
)
{
jQuery
.
event
.
add
(
dest
,
type
,
events
[
type
][
i
]
);
jQuery
.
event
.
add
(
dest
,
type
,
events
[
type
][
i
]
);
}
}
}
}
}
}
}
// make the cloned public data object a copy from the original
// 2. Copy user data
if
(
curData
.
data
)
{
if
(
data_user
.
hasData
(
src
)
)
{
curData
.
data
=
jQuery
.
extend
(
{},
curData
.
data
);
udataOld
=
data_user
.
access
(
src
);
udataCur
=
jQuery
.
extend
(
{},
udataOld
);
data_user
.
set
(
dest
,
udataCur
);
}
}
}
}
function
getAll
(
context
,
tag
)
{
function
getAll
(
context
,
tag
)
{
var
ret
=
context
.
getElementsByTagName
?
context
.
getElementsByTagName
(
tag
||
"*"
)
:
var
ret
=
context
.
getElementsByTagName
?
context
.
getElementsByTagName
(
tag
||
"*"
)
:
context
.
querySelectorAll
?
context
.
querySelectorAll
(
tag
||
"*"
)
:
context
.
querySelectorAll
?
context
.
querySelectorAll
(
tag
||
"*"
)
:
...
...
test/data/onbeforeunload.html
0 → 100644
View file @
7f94a5cc
<!doctype html>
<html>
<script
src=
"/dist/jquery.js"
></script>
<script>
function
report
(
event
)
{
var
payload
=
{
event
:
event
.
type
};
return
top
.
postMessage
(
JSON
.
stringify
(
payload
),
"*"
);
}
jQuery
(
window
).
on
(
"beforeunload"
,
function
(
event
)
{
report
(
event
);
}).
on
(
"load"
,
function
(
event
)
{
setTimeout
(
function
()
{
window
.
location
.
reload
();
},
50
);
});
</script>
</html>
test/data/testrunner.js
View file @
7f94a5cc
...
@@ -200,47 +200,53 @@ var Globals = (function() {
...
@@ -200,47 +200,53 @@ var Globals = (function() {
*/
*/
QUnit
.
expectJqData
=
function
(
elems
,
key
)
{
QUnit
.
expectJqData
=
function
(
elems
,
key
)
{
var
i
,
elem
,
expando
;
var
i
,
elem
,
expando
;
QUnit
.
current_testEnvironment
.
checkJqData
=
true
;
if
(
elems
.
jquery
&&
elems
.
toArray
)
{
// As of jQuery 2.0, there will be no "cache"-data is
elems
=
elems
.
toArray
();
// stored and managed completely below the API surface
}
if
(
jQuery
.
cache
)
{
if
(
!
jQuery
.
isArray
(
elems
)
)
{
QUnit
.
current_testEnvironment
.
checkJqData
=
true
;
elems
=
[
elems
];
}
for
(
i
=
0
;
i
<
elems
.
length
;
i
++
)
{
if
(
elems
.
jquery
&&
elems
.
toArray
)
{
elem
=
elems
[
i
];
elems
=
elems
.
toArray
();
}
// jQuery.data only stores data for nodes in jQuery.cache,
if
(
!
jQuery
.
isArray
(
elems
)
)
{
// for other data targets the data is stored in the object itself,
elems
=
[
elems
];
// in that case we can't test that target for memory leaks.
// But we don't have to since in that case the data will/must will
// be available as long as the object is not garbage collected by
// the js engine, and when it is, the data will be removed with it.
if
(
!
elem
.
nodeType
)
{
// Fixes false positives for dataTests(window), dataTests({}).
continue
;
}
}
expando
=
elem
[
jQuery
.
expando
];
for
(
i
=
0
;
i
<
elems
.
length
;
i
++
)
{
elem
=
elems
[
i
];
if
(
expando
===
undefined
)
{
// In this case the element exists fine, but
// jQuery.data only stores data for nodes in jQuery.cache,
// jQuery.data (or internal data) was never (in)directly
// for other data targets the data is stored in the object itself,
// called.
// in that case we can't test that target for memory leaks.
// Since this method was called it means some data was
// But we don't have to since in that case the data will/must will
// expected to be found, but since there is nothing, fail early
// be available as long as the object is not garbage collected by
// (instead of in teardown).
// the js engine, and when it is, the data will be removed with it.
notStrictEqual
(
expando
,
undefined
,
"Target for expectJqData must have an expando, for else there can be no data to expect."
);
if
(
!
elem
.
nodeType
)
{
}
else
{
// Fixes false positives for dataTests(window), dataTests({}).
if
(
expectedDataKeys
[
expando
]
)
{
continue
;
expectedDataKeys
[
expando
].
push
(
key
);
}
expando
=
elem
[
jQuery
.
expando
];
if
(
expando
===
undefined
)
{
// In this case the element exists fine, but
// jQuery.data (or internal data) was never (in)directly
// called.
// Since this method was called it means some data was
// expected to be found, but since there is nothing, fail early
// (instead of in teardown).
notStrictEqual
(
expando
,
undefined
,
"Target for expectJqData must have an expando, for else there can be no data to expect."
);
}
else
{
}
else
{
expectedDataKeys
[
expando
]
=
[
key
];
if
(
expectedDataKeys
[
expando
]
)
{
expectedDataKeys
[
expando
].
push
(
key
);
}
else
{
expectedDataKeys
[
expando
]
=
[
key
];
}
}
}
}
}
}
}
};
};
QUnit
.
config
.
urlConfig
.
push
(
{
QUnit
.
config
.
urlConfig
.
push
(
{
id
:
"jqdata"
,
id
:
"jqdata"
,
...
@@ -334,7 +340,7 @@ var Globals = (function() {
...
@@ -334,7 +340,7 @@ var Globals = (function() {
}
else
{
}
else
{
delete
jQuery
.
ajaxSettings
;
delete
jQuery
.
ajaxSettings
;
}
}
// Cleanup globals
// Cleanup globals
Globals
.
cleanup
();
Globals
.
cleanup
();
...
...
test/unit/data.js
View file @
7f94a5cc
...
@@ -6,6 +6,33 @@ test("expando", function(){
...
@@ -6,6 +6,33 @@ test("expando", function(){
equal
(
jQuery
.
expando
!==
undefined
,
true
,
"jQuery is exposing the expando"
);
equal
(
jQuery
.
expando
!==
undefined
,
true
,
"jQuery is exposing the expando"
);
});
});
test
(
"jQuery.data & removeData, expected returns"
,
function
()
{
expect
(
2
);
equal
(
jQuery
.
data
(
document
.
body
,
"hello"
,
"world"
),
"world"
,
"jQuery.data( elem, key, value ) returns value"
);
equal
(
jQuery
.
removeData
(
document
.
body
,
"hello"
),
undefined
,
"jQuery.removeData( elem, key, value ) returns undefined"
);
});
test
(
"jQuery._data & _removeData, expected returns"
,
function
()
{
expect
(
2
);
equal
(
jQuery
.
_data
(
document
.
body
,
"hello"
,
"world"
),
"world"
,
"jQuery.data( elem, key, value ) returns value"
);
equal
(
jQuery
.
_removeData
(
document
.
body
,
"hello"
),
undefined
,
"jQuery.removeData( elem, key, value ) returns undefined"
);
});
function
dataTests
(
elem
)
{
function
dataTests
(
elem
)
{
var
oldCacheLength
,
dataObj
,
internalDataObj
,
expected
,
actual
;
var
oldCacheLength
,
dataObj
,
internalDataObj
,
expected
,
actual
;
...
@@ -106,6 +133,10 @@ test("Data is not being set on comment and text nodes", function() {
...
@@ -106,6 +133,10 @@ test("Data is not being set on comment and text nodes", function() {
ok
(
!
jQuery
.
hasData
(
jQuery
(
"<span>text</span>"
).
contents
().
data
(
"foo"
,
0
)
)
);
ok
(
!
jQuery
.
hasData
(
jQuery
(
"<span>text</span>"
).
contents
().
data
(
"foo"
,
0
)
)
);
});
});
/*
// Since the new data system does not rely on exandos, limiting the type of
// nodes that can have data is no longer necessary. jQuery.acceptData is now irrelevant
// and should be removed from the library.
test("jQuery.acceptData", function() {
test("jQuery.acceptData", function() {
expect(9);
expect(9);
...
@@ -127,7 +158,7 @@ test("jQuery.acceptData", function() {
...
@@ -127,7 +158,7 @@ test("jQuery.acceptData", function() {
ok( !jQuery.acceptData( document.createComment("") ), "comment" );
ok( !jQuery.acceptData( document.createComment("") ), "comment" );
ok( !jQuery.acceptData( document.createTextNode("") ), "text" );
ok( !jQuery.acceptData( document.createTextNode("") ), "text" );
});
});
*/
test
(
".data()"
,
function
()
{
test
(
".data()"
,
function
()
{
expect
(
5
);
expect
(
5
);
...
@@ -424,7 +455,7 @@ if (window.JSON && window.JSON.stringify) {
...
@@ -424,7 +455,7 @@ if (window.JSON && window.JSON.stringify) {
}
}
test
(
"jQuery.data should follow html5 specification regarding camel casing"
,
function
()
{
test
(
"jQuery.data should follow html5 specification regarding camel casing"
,
function
()
{
expect
(
1
0
);
expect
(
1
2
);
var
div
=
jQuery
(
"<div id='myObject' data-w-t-f='ftw' data-big-a-little-a='bouncing-b' data-foo='a' data-foo-bar='b' data-foo-bar-baz='c'></div>"
)
var
div
=
jQuery
(
"<div id='myObject' data-w-t-f='ftw' data-big-a-little-a='bouncing-b' data-foo='a' data-foo-bar='b' data-foo-bar-baz='c'></div>"
)
.
prependTo
(
"body"
);
.
prependTo
(
"body"
);
...
@@ -445,6 +476,9 @@ test("jQuery.data should follow html5 specification regarding camel casing", fun
...
@@ -445,6 +476,9 @@ test("jQuery.data should follow html5 specification regarding camel casing", fun
equal
(
div
.
data
(
"fooBar"
),
"d"
,
"Verify updated data-* key"
);
equal
(
div
.
data
(
"fooBar"
),
"d"
,
"Verify updated data-* key"
);
equal
(
div
.
data
(
"foo-bar"
),
"d"
,
"Verify updated data-* key"
);
equal
(
div
.
data
(
"foo-bar"
),
"d"
,
"Verify updated data-* key"
);
equal
(
div
.
data
(
"fooBar"
),
"d"
,
"Verify updated data-* key (fooBar)"
);
equal
(
div
.
data
(
"foo-bar"
),
"d"
,
"Verify updated data-* key (foo-bar)"
);
div
.
remove
();
div
.
remove
();
});
});
...
...
test/unit/event.js
View file @
7f94a5cc
...
@@ -1371,75 +1371,20 @@ test("Submit event can be stopped (#11049)", function() {
...
@@ -1371,75 +1371,20 @@ test("Submit event can be stopped (#11049)", function() {
// Test beforeunload event only if it supported (i.e. not Opera)
// Test beforeunload event only if it supported (i.e. not Opera)
if
(
window
.
onbeforeunload
===
null
)
{
if
(
window
.
onbeforeunload
===
null
)
{
asyncTest
(
"on(beforeunload)"
,
4
,
function
()
{
asyncTest
(
"on(beforeunload)"
,
1
,
function
()
{
var
win
,
var
iframe
=
jQuery
(
jQuery
.
parseHTML
(
"<iframe src='data/onbeforeunload.html'><iframe>"
));
forIE6
=
0
,
fired
=
false
,
iframe
=
jQuery
(
"<iframe src='data/iframe.html' />"
);
iframe
.
appendTo
(
"#qunit-fixture"
).
one
(
"load"
,
function
()
{
win
=
this
.
contentWindow
||
this
.
contentDocument
;
jQuery
(
win
).
on
(
"beforeunload"
,
function
()
{
fired
=
true
;
ok
(
true
,
"beforeunload event is fired"
);
});
strictEqual
(
win
.
onbeforeunload
,
null
,
"onbeforeunload property on window object still equals null"
);
// In old Safari beforeunload event will not fire on iframes
jQuery
(
win
).
on
(
"unload"
,
function
()
{
if
(
!
fired
)
{
ok
(
true
,
"This is suppose to be true only in old Safari"
);
checker
();
}
});
jQuery
(
win
).
on
(
"beforeunload"
,
function
()
{
// On iframe in IE6 beforeunload event will not fire if event is binded through window object,
// nevertheless, test should continue
window
.
setTimeout
(
function
()
{
if
(
!
forIE6
)
{
checker
();
}
});
});
win
.
onbeforeunload
=
function
()
{
if
(
!
forIE6
)
{
forIE6
++
;
checker
();
}
};
function
checker
()
{
window
.
onmessage
=
function
(
event
)
{
ok
(
true
,
"window.onbeforeunload handler is called"
);
var
payload
=
JSON
.
parse
(
event
.
data
);
iframe
=
jQuery
(
"<iframe src='data/iframe.html' />"
);
iframe
.
appendTo
(
"#qunit-fixture"
).
one
(
"load"
,
function
()
{
ok
(
payload
.
event
,
"beforeunload"
,
"beforeunload event"
);
win
=
iframe
[
0
].
contentWindow
||
iframe
[
0
].
contentDocument
;
jQuery
(
win
).
on
(
"beforeunload"
,
function
()
{
iframe
.
remove
();
strictEqual
(
win
.
onbeforeunload
,
null
,
"Event handler is fired, even when onbeforeunload property on window is nulled"
);
window
.
onmessage
=
null
;
start
();
start
();
};
});
jQuery
(
win
).
on
(
"unload"
,
function
()
{
if
(
!
fired
)
{
jQuery
(
win
).
trigger
(
"beforeunload"
);
}
});
win
.
onbeforeunload
=
null
;
win
.
location
.
reload
();
});
}
win
.
location
.
reload
();
iframe
.
appendTo
(
"#qunit-fixture"
);
});
});
});
}
}
...
@@ -2567,7 +2512,7 @@ test( "Namespace preserved when passed an Event (#12739)", function() {
...
@@ -2567,7 +2512,7 @@ test( "Namespace preserved when passed an Event (#12739)", function() {
e
.
handled
=
true
;
e
.
handled
=
true
;
equal
(
e
.
namespace
,
"bar"
,
"namespace is bar"
);
equal
(
e
.
namespace
,
"bar"
,
"namespace is bar"
);
jQuery
(
e
.
target
).
find
(
"div"
).
each
(
function
()
{
jQuery
(
e
.
target
).
find
(
"div"
).
each
(
function
()
{
jQuery
(
this
).
triggerHandler
(
e
);
jQuery
(
this
).
triggerHandler
(
e
);
});
});
}
}
})
})
...
...
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