fix(svg): normalize class access for SVG

This commit is contained in:
Misko Hevery 2012-03-12 16:49:28 -07:00
parent 317adb36a4
commit 48096048cf
2 changed files with 31 additions and 10 deletions

View file

@ -247,7 +247,7 @@ function $CompileProvider($provide) {
var element = cloneConnectFn var element = cloneConnectFn
? JQLitePrototype.clone.call(templateElement) // IMPORTANT!!! ? JQLitePrototype.clone.call(templateElement) // IMPORTANT!!!
: templateElement; : templateElement;
element.data('$scope', scope).addClass('ng-scope'); safeAddClass(element.data('$scope', scope), 'ng-scope');
if (cloneConnectFn) cloneConnectFn(element, scope); if (cloneConnectFn) cloneConnectFn(element, scope);
if (linkingFn) linkingFn(scope, element, element); if (linkingFn) linkingFn(scope, element, element);
return element; return element;
@ -258,6 +258,15 @@ function $CompileProvider($provide) {
throw Error("Unsupported '" + mode + "' for '" + localName + "'."); throw Error("Unsupported '" + mode + "' for '" + localName + "'.");
} }
function safeAddClass(element, className) {
try {
element.addClass(className);
} catch(e) {
// ignore, since it means that we are trying to set class on
// SVG element, where class name is read-only.
}
}
/** /**
* Compile function matches each node in nodeList against the directives. Once all directives * Compile function matches each node in nodeList against the directives. Once all directives
* for a particular node are collected their compile functions are executed. The compile * for a particular node are collected their compile functions are executed. The compile
@ -387,12 +396,14 @@ function $CompileProvider($provide) {
// use class as directive // use class as directive
className = node.className; className = node.className;
while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { if (isString(className)) {
nName = directiveNormalize(match[2]); while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
if (addDirective(directives, nName, 'C', maxPriority)) { nName = directiveNormalize(match[2]);
attrs[nName] = trim(match[3]); if (addDirective(directives, nName, 'C', maxPriority)) {
attrs[nName] = trim(match[3]);
}
className = className.substr(match.index + match[0].length);
} }
className = className.substr(match.index + match[0].length);
} }
break; break;
case 3: /* Text Node */ case 3: /* Text Node */
@ -459,10 +470,10 @@ function $CompileProvider($provide) {
if (directiveValue = directive.scope) { if (directiveValue = directive.scope) {
assertNoDuplicate('isolated scope', newIsolatedScopeDirective, directive, element); assertNoDuplicate('isolated scope', newIsolatedScopeDirective, directive, element);
if (isObject(directiveValue)) { if (isObject(directiveValue)) {
element.addClass('ng-isolate-scope'); safeAddClass(element, 'ng-isolate-scope');
newIsolatedScopeDirective = directive; newIsolatedScopeDirective = directive;
} }
element.addClass('ng-scope'); safeAddClass(element, 'ng-scope');
newScopeDirective = newScopeDirective || directive; newScopeDirective = newScopeDirective || directive;
} }
@ -725,7 +736,7 @@ function $CompileProvider($provide) {
// copy the new attributes on the old attrs object // copy the new attributes on the old attrs object
forEach(src, function(value, key) { forEach(src, function(value, key) {
if (key == 'class') { if (key == 'class') {
element.addClass(value); safeAddClass(element, value);
} else if (key == 'style') { } else if (key == 'style') {
element.attr('style', element.attr('style') + ';' + value); element.attr('style', element.attr('style') + ';' + value);
} else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
@ -837,7 +848,7 @@ function $CompileProvider($provide) {
var parent = node.parent(), var parent = node.parent(),
bindings = parent.data('$binding') || []; bindings = parent.data('$binding') || [];
bindings.push(interpolateFn); bindings.push(interpolateFn);
parent.data('$binding', bindings).addClass('ng-binding'); safeAddClass(parent.data('$binding', bindings), 'ng-binding');
scope.$watch(interpolateFn, function(value) { scope.$watch(interpolateFn, function(value) {
node[0].nodeValue = value; node[0].nodeValue = value;
}); });

View file

@ -138,6 +138,16 @@ describe('$compile', function() {
})); }));
it('should ignore not set CSS classes on SVG elements', inject(function($compile, $rootScope, log) {
if (!window.SVGElement) return;
// According to spec SVG element className property is readonly, but only FF
// implements it this way which causes compile exceptions.
element = $compile('<svg><text>{{1}}</text></svg>')($rootScope);
$rootScope.$digest();
expect(element.text()).toEqual('1');
}));
it('should allow directives in comments', inject( it('should allow directives in comments', inject(
function($compile, $rootScope, log) { function($compile, $rootScope, log) {
element = $compile('<div>0<!-- directive: log angular -->1</div>')($rootScope); element = $compile('<div>0<!-- directive: log angular -->1</div>')($rootScope);