diff --git a/src/.jshintrc b/src/.jshintrc index 9500d330d7ab..dd5755a60896 100644 --- a/src/.jshintrc +++ b/src/.jshintrc @@ -26,6 +26,7 @@ "uppercase": false, "manualLowercase": false, "manualUppercase": false, + "camelcase": false, "isArrayLike": false, "forEach": false, "sortedKeys": false, diff --git a/src/Angular.js b/src/Angular.js index 09d7c4619b8d..68926a1758f5 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -19,6 +19,7 @@ uppercase: true, manualLowercase: true, manualUppercase: true, + camelcase: true, nodeName_: true, isArrayLike: true, forEach: true, @@ -108,6 +109,8 @@ */ var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; +var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; +var MOZ_HACK_REGEXP = /^moz([A-Z])/; // The name of a form control's ValidityState property. // This is used so that it's possible for internal tests to create mock ValidityStates. @@ -161,6 +164,24 @@ if ('i' !== 'I'.toLowerCase()) { uppercase = manualUppercase; } +/** + * @ngdoc function + * @name angular.camelcase + * @module ng + * @kind function + * + * @description Converts the specified string dash-separated to camelcase. + * @param {string} string String to be converted to camelcase. + * @returns {string} Camelcased string. + */ +var camelcase = function(name) { + return name. + replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }). + replace(MOZ_HACK_REGEXP, 'Moz$1'); +}; + var msie, // holds major version number for IE, or NaN if UA is not IE. diff --git a/src/AngularPublic.js b/src/AngularPublic.js index b81257b9fff7..4902120854b9 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -137,6 +137,7 @@ function publishExternalAPI(angular) { 'isDate': isDate, 'lowercase': lowercase, 'uppercase': uppercase, + 'camelcase': camelcase, 'callbacks': {counter: 0}, 'getTestability': getTestability, '$$minErr': minErr, diff --git a/src/jqLite.js b/src/jqLite.js index 1b7f638c2bb6..b542e9b06267 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -122,24 +122,9 @@ JQLite._data = function(node) { function jqNextId() { return ++jqId; } -var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; -var MOZ_HACK_REGEXP = /^moz([A-Z])/; var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"}; var jqLiteMinErr = minErr('jqLite'); -/** - * Converts snake_case to camelCase. - * Also there is special case for Moz prefix starting with upper case letter. - * @param name Name to normalize - */ -function camelCase(name) { - return name. - replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }). - replace(MOZ_HACK_REGEXP, 'Moz$1'); -} - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; var TAG_NAME_REGEXP = /<([\w:]+)/; @@ -577,7 +562,7 @@ forEach({ hasClass: jqLiteHasClass, css: function(element, name, value) { - name = camelCase(name); + name = camelcase(name); if (isDefined(value)) { element.style[name] = value; diff --git a/src/ng/compile.js b/src/ng/compile.js index 4d89e8795e2d..37847026146d 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -2495,7 +2495,7 @@ var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; * @param name Name to normalize */ function directiveNormalize(name) { - return camelCase(name.replace(PREFIX_REGEXP, '')); + return camelcase(name.replace(PREFIX_REGEXP, '')); } /** diff --git a/src/ng/sce.js b/src/ng/sce.js index 67be4997fb8f..c5e7524d9ad8 100644 --- a/src/ng/sce.js +++ b/src/ng/sce.js @@ -1033,13 +1033,13 @@ function $SceProvider() { forEach(SCE_CONTEXTS, function(enumValue, name) { var lName = lowercase(name); - sce[camelCase("parse_as_" + lName)] = function(expr) { + sce[camelcase("parse_as_" + lName)] = function(expr) { return parse(enumValue, expr); }; - sce[camelCase("get_trusted_" + lName)] = function(value) { + sce[camelcase("get_trusted_" + lName)] = function(value) { return getTrusted(enumValue, value); }; - sce[camelCase("trust_as_" + lName)] = function(value) { + sce[camelcase("trust_as_" + lName)] = function(value) { return trustAs(enumValue, value); }; }); diff --git a/src/ngAria/aria.js b/src/ngAria/aria.js index cc90170989f4..343a402c9af1 100644 --- a/src/ngAria/aria.js +++ b/src/ngAria/aria.js @@ -109,15 +109,8 @@ function $AriaProvider() { config = angular.extend(config, newConfig); }; - function camelCase(input) { - return input.replace(/-./g, function(letter, pos) { - return letter[1].toUpperCase(); - }); - } - - function watchExpr(attrName, ariaAttr, negate) { - var ariaCamelName = camelCase(ariaAttr); + var ariaCamelName = angular.camelcase(ariaAttr); return function(scope, elem, attr) { if (config[ariaCamelName] && !attr[ariaCamelName]) { scope.$watch(attr[attrName], function(boolVal) { @@ -178,7 +171,7 @@ function $AriaProvider() { this.$get = function() { return { config: function(key) { - return config[camelCase(key)]; + return config[angular.camelcase(key)]; }, $$watchExpr: watchExpr }; diff --git a/test/.jshintrc b/test/.jshintrc index 6bca8382f2d9..993f224e922d 100644 --- a/test/.jshintrc +++ b/test/.jshintrc @@ -24,6 +24,7 @@ "uppercase": false, "manualLowercase": false, "manualUppercase": false, + "camelcase": false, "isArrayLike": false, "forEach": false, "sortedKeys": false, diff --git a/test/AngularSpec.js b/test/AngularSpec.js index e63789100947..9138a9cb04dc 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -7,15 +7,47 @@ describe('angular', function() { dealoc(element); }); - describe('case', function() { + describe('lowercase', function() { it('should change case', function() { expect(lowercase('ABC90')).toEqual('abc90'); expect(manualLowercase('ABC90')).toEqual('abc90'); + }); + }); + + describe('uppercase', function() { + it('should change case', function() { expect(uppercase('abc90')).toEqual('ABC90'); expect(manualUppercase('abc90')).toEqual('ABC90'); }); }); + describe('camelcase', function() { + it('should change case', function() { + expect(camelcase('foo-bar')).toEqual('fooBar'); + expect(camelcase('foo-Bar')).toEqual('fooBar'); + }); + + it('should leave non-dashed strings alone', function() { + expect(camelcase('foo')).toBe('foo'); + expect(camelcase('')).toBe(''); + expect(camelcase('fooBar')).toBe('fooBar'); + }); + + + it('should covert dash-separated strings to camelCase', function() { + expect(camelcase('foo-bar')).toBe('fooBar'); + expect(camelcase('foo-bar-baz')).toBe('fooBarBaz'); + expect(camelcase('foo:bar_baz')).toBe('fooBarBaz'); + }); + + + it('should covert browser specific css properties', function() { + expect(camelcase('-moz-foo-bar')).toBe('MozFooBar'); + expect(camelcase('-webkit-foo-bar')).toBe('webkitFooBar'); + expect(camelcase('-webkit-foo-bar')).toBe('webkitFooBar'); + }); + }); + describe("copy", function() { it("should return same object", function() { var obj = {}; diff --git a/test/jqLiteSpec.js b/test/jqLiteSpec.js index 29848825a41a..764de76b34da 100644 --- a/test/jqLiteSpec.js +++ b/test/jqLiteSpec.js @@ -1965,30 +1965,6 @@ describe('jqLite', function() { }); }); - - describe('camelCase', function() { - it('should leave non-dashed strings alone', function() { - expect(camelCase('foo')).toBe('foo'); - expect(camelCase('')).toBe(''); - expect(camelCase('fooBar')).toBe('fooBar'); - }); - - - it('should covert dash-separated strings to camelCase', function() { - expect(camelCase('foo-bar')).toBe('fooBar'); - expect(camelCase('foo-bar-baz')).toBe('fooBarBaz'); - expect(camelCase('foo:bar_baz')).toBe('fooBarBaz'); - }); - - - it('should covert browser specific css properties', function() { - expect(camelCase('-moz-foo-bar')).toBe('MozFooBar'); - expect(camelCase('-webkit-foo-bar')).toBe('webkitFooBar'); - expect(camelCase('-webkit-foo-bar')).toBe('webkitFooBar'); - }); - }); - - describe('jqLiteDocumentLoaded', function() { function createMockWindow(readyState) {