From d8e37078600089839f82f0e84022f1087e1fd3f2 Mon Sep 17 00:00:00 2001 From: Wesley Cho Date: Sat, 22 Nov 2014 19:21:59 -0800 Subject: [PATCH] feat($compile): add support for ng-attr with camelCased attributes SVG attributes are case sensitive and some have upper case letters in them This change ensures that we can identify these, when being used with the `ng-attr` directive, by encoding upper case letters with a preceding underscore. For example to apply `ng-attr` to the `viewBox` attribute we could write `ng-attr-view_box` - or any of the other variants: `ng:attr:view_box`, `data-ng-attr-view_box`, etc. Closes #9845 Closes #10194 --- docs/content/guide/directive.ngdoc | 9 +++++++ src/ng/compile.js | 5 +++- test/ng/compileSpec.js | 38 ++++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/docs/content/guide/directive.ngdoc b/docs/content/guide/directive.ngdoc index 643a3b44..a82e6994 100644 --- a/docs/content/guide/directive.ngdoc +++ b/docs/content/guide/directive.ngdoc @@ -174,6 +174,15 @@ For example, we could fix the example above by instead writing: ``` +If one wants to modify a camelcased attribute (SVG elements have valid camelcased attributes), such as `viewBox` on the `svg` element, one can use underscores to denote that the attribute to bind to is naturally camelcased. + +For example, to bind to `viewBox`, we can write: + +```html + + +``` + ## Creating Directives diff --git a/src/ng/compile.js b/src/ng/compile.js index b4d573e1..41083149 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1420,7 +1420,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // support ngAttr attribute binding ngAttrName = directiveNormalize(name); if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) { - name = snake_case(ngAttrName.substr(6), '-'); + name = name.replace(PREFIX_REGEXP, '') + .substr(8).replace(/_(.)/g, function(match, letter) { + return letter.toUpperCase(); + }); } var directiveNName = ngAttrName.replace(/(Start|End)$/, ''); diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 9509e90b..1e4717ad 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -6542,16 +6542,21 @@ describe('$compile', function() { expect(element.attr('href')).toBe('test/test'); })); - it('should work if they are prefixed with x- or data-', inject(function($compile, $rootScope) { + it('should work if they are prefixed with x- or data- and different prefixes', inject(function($compile, $rootScope) { $rootScope.name = "Misko"; - element = $compile('')($rootScope); + element = $compile('')($rootScope); expect(element.attr('test2')).toBeUndefined(); expect(element.attr('test3')).toBeUndefined(); expect(element.attr('test4')).toBeUndefined(); + expect(element.attr('test5')).toBeUndefined(); + expect(element.attr('test6')).toBeUndefined(); $rootScope.$digest(); expect(element.attr('test2')).toBe('Misko'); expect(element.attr('test3')).toBe('Misko'); expect(element.attr('test4')).toBe('Misko'); + expect(element.attr('test5')).toBe('Misko'); + expect(element.attr('test6')).toBe('Misko'); })); describe('when an attribute has a dash-separated name', function() { @@ -6619,6 +6624,35 @@ describe('$compile', function() { }); + describe('when an attribute has an underscore-separated name', function() { + + it('should work with different prefixes', inject(function($compile, $rootScope) { + $rootScope.dimensions = "0 0 0 0"; + element = $compile('')($rootScope); + expect(element.attr('viewBox')).toBeUndefined(); + $rootScope.$digest(); + expect(element.attr('viewBox')).toBe('0 0 0 0'); + })); + + it('should work if they are prefixed with x- or data-', inject(function($compile, $rootScope) { + $rootScope.dimensions = "0 0 0 0"; + $rootScope.number = 0.42; + $rootScope.scale = 1; + element = $compile('' + + '' + + '' + + '' + + '' + + '')($rootScope); + expect(element.attr('viewBox')).toBeUndefined(); + $rootScope.$digest(); + expect(element.attr('viewBox')).toBe('0 0 0 0'); + expect(element.find('filter').attr('filterUnits')).toBe('0.42'); + expect(element.find('feDiffuseLighting').attr('surfaceScale')).toBe('1'); + expect(element.find('feSpecularLighting').attr('surfaceScale')).toBe('1'); + })); + }); + describe('multi-element directive', function() { it('should group on link function', inject(function($compile, $rootScope) { $rootScope.show = false;