Prevent DOM node expandos _countedByPrototype and _prototypeEventID from being serialized into (inner|outer)HTML in IE. Closes #10909. [dcpedit, Tobie Langel, Andrew Dupont]
This commit is contained in:
parent
794457da75
commit
a1ec25cddb
|
@ -1,5 +1,7 @@
|
|||
*SVN*
|
||||
|
||||
* Prevent DOM node expandos _countedByPrototype and _prototypeEventID from being serialized into (inner|outer)HTML in IE. Closes #10909. [dcpedit, Tobie Langel, Andrew Dupont]
|
||||
|
||||
* Make Ajax.Request#isSameOrigin JavaScript Lint compliant. [Andrew Dupont]
|
||||
|
||||
* Properly serialize form fields with names that collide with built-in JS properties (like "length" or "toString"). Closes #9609. [gryn, kangax]
|
||||
|
|
|
@ -128,11 +128,11 @@ Event.extend = (function() {
|
|||
|
||||
Object.extend(Event, (function() {
|
||||
var cache = Event.cache;
|
||||
|
||||
|
||||
function getEventID(element) {
|
||||
if (element._eventID) return element._eventID;
|
||||
if (element._prototypeEventID) return element._prototypeEventID[0];
|
||||
arguments.callee.id = arguments.callee.id || 1;
|
||||
return element._eventID = ++arguments.callee.id;
|
||||
return element._prototypeEventID = [++arguments.callee.id];
|
||||
}
|
||||
|
||||
function getDOMEventName(eventName) {
|
||||
|
|
|
@ -312,14 +312,15 @@ Object.extend(Selector, {
|
|||
|
||||
// marks an array of nodes for counting
|
||||
mark: function(nodes) {
|
||||
var _true = Prototype.emptyFunction;
|
||||
for (var i = 0, node; node = nodes[i]; i++)
|
||||
node._counted = true;
|
||||
node._countedByPrototype = _true;
|
||||
return nodes;
|
||||
},
|
||||
|
||||
unmark: function(nodes) {
|
||||
for (var i = 0, node; node = nodes[i]; i++)
|
||||
node._counted = undefined;
|
||||
node._countedByPrototype = undefined;
|
||||
return nodes;
|
||||
},
|
||||
|
||||
|
@ -327,15 +328,15 @@ Object.extend(Selector, {
|
|||
// "ofType" flag indicates whether we're indexing for nth-of-type
|
||||
// rather than nth-child
|
||||
index: function(parentNode, reverse, ofType) {
|
||||
parentNode._counted = true;
|
||||
parentNode._countedByPrototype = Prototype.emptyFunction;
|
||||
if (reverse) {
|
||||
for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
|
||||
var node = nodes[i];
|
||||
if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
|
||||
if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
|
||||
}
|
||||
} else {
|
||||
for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
|
||||
if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
|
||||
if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -344,8 +345,8 @@ Object.extend(Selector, {
|
|||
if (nodes.length == 0) return nodes;
|
||||
var results = [], n;
|
||||
for (var i = 0, l = nodes.length; i < l; i++)
|
||||
if (!(n = nodes[i])._counted) {
|
||||
n._counted = true;
|
||||
if (!(n = nodes[i])._countedByPrototype) {
|
||||
n._countedByPrototype = Prototype.emptyFunction;
|
||||
results.push(Element.extend(n));
|
||||
}
|
||||
return Selector.handlers.unmark(results);
|
||||
|
@ -547,7 +548,7 @@ Object.extend(Selector, {
|
|||
var h = Selector.handlers, results = [], indexed = [], m;
|
||||
h.mark(nodes);
|
||||
for (var i = 0, node; node = nodes[i]; i++) {
|
||||
if (!node.parentNode._counted) {
|
||||
if (!node.parentNode._countedByPrototype) {
|
||||
h.index(node.parentNode, reverse, ofType);
|
||||
indexed.push(node.parentNode);
|
||||
}
|
||||
|
@ -585,7 +586,7 @@ Object.extend(Selector, {
|
|||
var exclusions = new Selector(selector).findElements(root);
|
||||
h.mark(exclusions);
|
||||
for (var i = 0, results = [], node; node = nodes[i]; i++)
|
||||
if (!node._counted) results.push(node);
|
||||
if (!node._countedByPrototype) results.push(node);
|
||||
h.unmark(exclusions);
|
||||
return results;
|
||||
},
|
||||
|
@ -618,12 +619,20 @@ Object.extend(Selector, {
|
|||
'~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
|
||||
'|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
|
||||
},
|
||||
|
||||
split: function(expression) {
|
||||
var expressions = [];
|
||||
expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
|
||||
expressions.push(m[1].strip());
|
||||
});
|
||||
return expressions;
|
||||
},
|
||||
|
||||
matchElements: function(elements, expression) {
|
||||
var matches = $$(expression), h = Selector.handlers;
|
||||
h.mark(matches);
|
||||
for (var i = 0, results = [], element; element = elements[i]; i++)
|
||||
if (element._counted) results.push(element);
|
||||
if (element._countedByPrototype) results.push(element);
|
||||
h.unmark(matches);
|
||||
return results;
|
||||
},
|
||||
|
@ -636,11 +645,7 @@ Object.extend(Selector, {
|
|||
},
|
||||
|
||||
findChildElements: function(element, expressions) {
|
||||
var exprs = expressions.join(',');
|
||||
expressions = [];
|
||||
exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
|
||||
expressions.push(m[1].strip());
|
||||
});
|
||||
expressions = Selector.split(expressions.join(','));
|
||||
var results = [], h = Selector.handlers;
|
||||
for (var i = 0, l = expressions.length, selector; i < l; i++) {
|
||||
selector = new Selector(expressions[i].strip());
|
||||
|
@ -651,13 +656,22 @@ Object.extend(Selector, {
|
|||
});
|
||||
|
||||
if (Prototype.Browser.IE) {
|
||||
// IE returns comment nodes on getElementsByTagName("*").
|
||||
// Filter them out.
|
||||
Selector.handlers.concat = function(a, b) {
|
||||
for (var i = 0, node; node = b[i]; i++)
|
||||
if (node.tagName !== "!") a.push(node);
|
||||
return a;
|
||||
};
|
||||
Object.extend(Selector.handlers, {
|
||||
// IE returns comment nodes on getElementsByTagName("*").
|
||||
// Filter them out.
|
||||
concat: function(a, b) {
|
||||
for (var i = 0, node; node = b[i]; i++)
|
||||
if (node.tagName !== "!") a.push(node);
|
||||
return a;
|
||||
},
|
||||
|
||||
// IE improperly serializes _countedByPrototype in (inner|outer)HTML.
|
||||
unmark: function(nodes) {
|
||||
for (var i = 0, node; node = nodes[i]; i++)
|
||||
node.removeAttribute('_countedByPrototype');
|
||||
return nodes;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function $$() {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<div id="outer" style="display: none">
|
||||
<p id="inner">One two three <span id="span">four</span></p>
|
||||
</div>
|
||||
<div id="container"><div></div></div>
|
||||
|
||||
<!-- Tests follow -->
|
||||
<script type="text/javascript" language="javascript" charset="utf-8">
|
||||
|
@ -174,7 +175,7 @@
|
|||
var span = $("span"), observer = function() { }, eventID;
|
||||
|
||||
span.observe("test:somethingHappened", observer);
|
||||
eventID = span._eventID;
|
||||
eventID = span._prototypeEventID;
|
||||
|
||||
assert(Event.cache[eventID]);
|
||||
assert(Object.isArray(Event.cache[eventID]["test:somethingHappened"]));
|
||||
|
@ -240,6 +241,12 @@
|
|||
assertElementMatches(event.findElement('p'), 'p#inner');
|
||||
assertEqual(null, event.findElement('div.does_not_exist'));
|
||||
assertElementMatches(event.findElement('.does_not_exist, span'), 'span#span');
|
||||
}},
|
||||
|
||||
testEventIDDuplication: function() { with(this) {
|
||||
$('container').down().observe("test:somethingHappened", Prototype.emptyFunction);
|
||||
$('container').innerHTML += $('container').innerHTML;
|
||||
assertUndefined($('container').down(1)._prototypeEventID);
|
||||
}}
|
||||
});
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
<input type="hidden" id="commaChild" name="foo" value="#commaOne,#commaTwo" />
|
||||
<input type="hidden" id="commaTwo" name="foo2" value="oops" />
|
||||
</form>
|
||||
|
||||
<div id="counted_container"><div class="is_counted"></div></div>
|
||||
</div> <!-- #fixtures -->
|
||||
|
||||
<!-- Log output -->
|
||||
|
@ -442,8 +442,29 @@
|
|||
assert(typeof results[0].show == 'function');
|
||||
assert(typeof results[1].show == 'function');
|
||||
assert(typeof results[2].show == 'function');
|
||||
}},
|
||||
|
||||
testCountedIsNotAnAttribute: function() { with(this) {
|
||||
var el = $('list');
|
||||
Selector.handlers.mark([el]);
|
||||
assert(!el.innerHTML.include("_counted"));
|
||||
Selector.handlers.unmark([el]);
|
||||
assert(!el.innerHTML.include("_counted"));
|
||||
}},
|
||||
|
||||
testCopiedNodesGetIncluded: function(){ with(this) {
|
||||
assertElementsMatch(
|
||||
Selector.matchElements($('counted_container').descendants(), 'div'),
|
||||
'div.is_counted'
|
||||
);
|
||||
$('counted_container').innerHTML += $('counted_container').innerHTML;
|
||||
assertElementsMatch(
|
||||
Selector.matchElements($('counted_container').descendants(), 'div'), 'div.is_counted',
|
||||
'div.is_counted'
|
||||
);
|
||||
}}
|
||||
});
|
||||
|
||||
// ]]>
|
||||
</script>
|
||||
</body>
|
||||
|
|
Loading…
Reference in New Issue