fix(Angular): nodeName should always be lowercase

XHTML uses lowercase node names, while HTML often uses uppercase.  The
generally accepted convention is to always lowercase them.

Fixes #3987
This commit is contained in:
Yuri Sulyma
2013-11-12 17:46:11 -07:00
committed by Peter Bacon Darwin
parent ebff4c1fd2
commit dafb8a3cd1
9 changed files with 25 additions and 24 deletions

View File

@@ -615,12 +615,14 @@ function makeMap(str) {
if (msie < 9) {
nodeName_ = function(element) {
element = element.nodeName ? element : element[0];
return (element.scopeName && element.scopeName != 'HTML')
? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
return lowercase(
(element.scopeName && element.scopeName != 'HTML')
? element.scopeName + ':' + element.nodeName : element.nodeName
);
};
} else {
nodeName_ = function(element) {
return element.nodeName ? element.nodeName : element[0].nodeName;
return lowercase(element.nodeName ? element.nodeName : element[0].nodeName);
};
}
@@ -683,10 +685,10 @@ function arrayRemove(array, value) {
function isLeafNode (node) {
if (node) {
switch (node.nodeName) {
case "OPTION":
case "PRE":
case "TITLE":
switch (nodeName_(node)) {
case "option":
case "pre":
case "title":
return true;
}
}

View File

@@ -482,7 +482,7 @@ forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','),
});
var BOOLEAN_ELEMENTS = {};
forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
BOOLEAN_ELEMENTS[uppercase(value)] = true;
BOOLEAN_ELEMENTS[value] = true;
});
var ALIASED_ATTR = {
'ngMinlength' : 'minlength',
@@ -495,7 +495,7 @@ function getBooleanAttrName(element, name) {
var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
// booleanAttr is here twice to minimize DOM access
return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
}
function getAliasedAttrName(element, name) {
@@ -605,7 +605,7 @@ forEach({
val: function(element, value) {
if (isUndefined(value)) {
if (nodeName_(element) === 'SELECT' && element.multiple) {
if (element.multiple && nodeName_(element) === 'select') {
var result = [];
forEach(element.options, function (option) {
if (option.selected) {

View File

@@ -67,7 +67,7 @@ function $AnchorScrollProvider() {
function getFirstAnchor(list) {
var result = null;
forEach(list, function(element) {
if (!result && lowercase(element.nodeName) === 'a') result = element;
if (!result && nodeName_(element) === 'a') result = element;
});
return result;
}

View File

@@ -759,8 +759,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nodeName = nodeName_(this.$$element);
// sanitize a[href] and img[src] values
if ((nodeName === 'A' && key === 'href') ||
(nodeName === 'IMG' && key === 'src')) {
if ((nodeName === 'a' && key === 'href') ||
(nodeName === 'img' && key === 'src')) {
this[key] = value = $$sanitizeUri(value, key === 'src');
}
@@ -1030,7 +1030,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
case 1: /* Element */
// use the node name: <directive>
addDirective(directives,
directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
// iterate over the attributes
for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
@@ -1897,8 +1897,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var tag = nodeName_(node);
// maction[xlink:href] can source SVG. It's not limited to <maction>.
if (attrNormalizedName == "xlinkHref" ||
(tag == "FORM" && attrNormalizedName == "action") ||
(tag != "IMG" && (attrNormalizedName == "src" ||
(tag == "form" && attrNormalizedName == "action") ||
(tag != "img" && (attrNormalizedName == "src" ||
attrNormalizedName == "ngSrc"))) {
return $sce.RESOURCE_URL;
}
@@ -1912,7 +1912,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (!interpolateFn) return;
if (name === "multiple" && nodeName_(node) === "SELECT") {
if (name === "multiple" && nodeName_(node) === "select") {
throw $compileMinErr("selmulti",
"Binding to the 'multiple' attribute is not supported. Element: {0}",
startingTag(node));

View File

@@ -636,7 +636,7 @@ function $LocationProvider(){
var elm = jqLite(event.target);
// traverse the DOM up to find first A tag
while (lowercase(elm[0].nodeName) !== 'a') {
while (nodeName_(elm[0]) !== 'a') {
// ignore rewriting if no A tag (reached root element, or no parent - removed from document)
if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
}

View File

@@ -34,7 +34,6 @@
var inputType = (element.type) ? element.type.toLowerCase() : null,
nodeName = element.nodeName.toLowerCase();
if (!eventType) {
eventType = {
'text': 'change',

View File

@@ -377,7 +377,7 @@ angular.scenario.dsl('element', function() {
var href = elements.attr('href');
var eventProcessDefault = elements.trigger('click')[0];
if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {
if (href && elements[0].nodeName.toLowerCase() === 'a' && eventProcessDefault) {
this.application.navigateTo(href, function() {
done();
}, done);
@@ -394,7 +394,7 @@ angular.scenario.dsl('element', function() {
var href = elements.attr('href');
var eventProcessDefault = elements.trigger('dblclick')[0];
if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {
if (href && elements[0].nodeName.toLowerCase() === 'a' && eventProcessDefault) {
this.application.navigateTo(href, function() {
done();
}, done);

View File

@@ -951,7 +951,7 @@ describe('angular', function() {
var div = jqLite('<div xmlns:ngtest="http://angularjs.org/">' +
'<ngtest:foo ngtest:attr="bar"></ngtest:foo>' +
'</div>')[0];
expect(nodeName_(div.childNodes[0])).toBe('NGTEST:FOO');
expect(nodeName_(div.childNodes[0])).toBe('ngtest:foo');
expect(div.childNodes[0].getAttribute('ngtest:attr')).toBe('bar');
});
@@ -960,7 +960,7 @@ describe('angular', function() {
var div = jqLite('<div xmlns:ngtest="http://angularjs.org/">' +
'<ngtest:foo ngtest:attr="bar"></ng-test>' +
'</div>')[0];
expect(nodeName_(div.childNodes[0])).toBe('NGTEST:FOO');
expect(nodeName_(div.childNodes[0])).toBe('ngtest:foo');
expect(div.childNodes[0].getAttribute('ngtest:attr')).toBe('bar');
});
}

View File

@@ -4625,7 +4625,7 @@ describe('$compile', function() {
inject(function($compile, $rootScope) {
var element = jqLite('<div>before<div transclude></div>after</div>').contents();
expect(element.length).toEqual(3);
expect(nodeName_(element[1])).toBe('DIV');
expect(nodeName_(element[1])).toBe('div');
$compile(element)($rootScope);
expect(nodeName_(element[1])).toBe('#comment');
expect(nodeName_(comment)).toBe('#comment');