diff options
| -rw-r--r-- | src/jqLite.js | 8 | ||||
| -rw-r--r-- | src/service/compiler.js | 10 | ||||
| -rw-r--r-- | test/directive/ngNonBindableSpec.js | 2 | ||||
| -rw-r--r-- | test/service/compilerSpec.js | 49 |
4 files changed, 39 insertions, 30 deletions
diff --git a/src/jqLite.js b/src/jqLite.js index dd793ab2..96dda112 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -310,6 +310,14 @@ var BOOLEAN_ATTR = {}; forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) { BOOLEAN_ATTR[lowercase(value)] = value; }); +var BOOLEAN_ELEMENTS = {}; +forEach('input,select,option,textarea,button'.split(','), function(value) { + BOOLEAN_ELEMENTS[uppercase(value)] = true; +}); + +function isBooleanAttr(element, name) { + return BOOLEAN_ELEMENTS[element.nodeName] && BOOLEAN_ATTR[name.toLowerCase()]; +} forEach({ data: JQLiteData, diff --git a/src/service/compiler.js b/src/service/compiler.js index cefc2d81..8aba28e4 100644 --- a/src/service/compiler.js +++ b/src/service/compiler.js @@ -381,10 +381,10 @@ function $CompileProvider($provide) { attrs[nName] = value = trim((msie && name == 'href') ? decodeURIComponent(node.getAttribute(name, 2)) : attr.value); - if (BOOLEAN_ATTR[nName]) { + if (isBooleanAttr(node, nName)) { attrs[nName] = true; // presence means true } - addAttrInterpolateDirective(directives, value, nName) + addAttrInterpolateDirective(node, directives, value, nName) addDirective(directives, nName, 'A', maxPriority); } @@ -852,11 +852,11 @@ function $CompileProvider($provide) { } - function addAttrInterpolateDirective(directives, value, name) { + function addAttrInterpolateDirective(node, directives, value, name) { var interpolateFn = $interpolate(value, true); if (SIDE_EFFECT_ATTRS[name]) { name = SIDE_EFFECT_ATTRS[name]; - if (BOOLEAN_ATTR[name]) { + if (isBooleanAttr(node, name)) { value = true; } } else if (!interpolateFn) { @@ -921,7 +921,7 @@ function $CompileProvider($provide) { * @param {string=} attrName Optional none normalized name. Defaults to key. */ function attrSetter(key, value, attrName) { - var booleanKey = BOOLEAN_ATTR[key.toLowerCase()]; + var booleanKey = isBooleanAttr(this.$element[0], key.toLowerCase()); if (booleanKey) { value = toBoolean(value); diff --git a/test/directive/ngNonBindableSpec.js b/test/directive/ngNonBindableSpec.js index 4f69528b..1f7bf25d 100644 --- a/test/directive/ngNonBindableSpec.js +++ b/test/directive/ngNonBindableSpec.js @@ -10,7 +10,7 @@ describe('ng-non-bindable', function() { }); - iit('should prevent compilation of the owning element and its children', + it('should prevent compilation of the owning element and its children', inject(function($rootScope, $compile) { element = $compile('<div ng-non-bindable text="{{name}}"><span ng-bind="name"></span></div>')($rootScope); $rootScope.name = 'misko'; diff --git a/test/service/compilerSpec.js b/test/service/compilerSpec.js index b42b871a..28c91492 100644 --- a/test/service/compilerSpec.js +++ b/test/service/compilerSpec.js @@ -1226,20 +1226,39 @@ describe('$compile', function() { }); - it('should read boolean attributes as boolean', function() { + it('should read boolean attributes as boolean only on control elements', function() { + var value; + module(function($compileProvider) { + $compileProvider.directive({ + input: valueFn({ + restrict: 'ECA', + link:function(scope, element, attr) { + value = attr.required; + } + }) + }); + }); + inject(function($rootScope, $compile) { + element = $compile('<input required></input>')($rootScope); + expect(value).toEqual(true); + }); + }); + + it('should read boolean attributes as text on non-controll elements', function() { + var value; module(function($compileProvider) { $compileProvider.directive({ div: valueFn({ restrict: 'ECA', link:function(scope, element, attr) { - element.text(attr.required); + value = attr.required; } }) }); }); inject(function($rootScope, $compile) { - element = $compile('<div required></div>')($rootScope); - expect(element.text()).toEqual('true'); + element = $compile('<div required="some text"></div>')($rootScope); + expect(value).toEqual('some text'); }); }); @@ -1262,24 +1281,6 @@ describe('$compile', function() { }); - it('should read boolean attributes as boolean', function() { - module(function($compileProvider) { - $compileProvider.directive({ - div: valueFn({ - restrict: 'ECA', - link: function(scope, element, attr) { - element.text(attr.required); - } - }) - }); - }); - inject(function($rootScope, $compile) { - element = $compile('<div required></div>')($rootScope); - expect(element.text()).toEqual('true'); - }); - }); - - it('should create new instance of attr for each template stamping', function() { module(function($compileProvider, $provide) { var state = { first: [], second: [] }; @@ -1335,7 +1336,7 @@ describe('$compile', function() { var attr; beforeEach(function(){ module(function($compileProvider) { - $compileProvider.directive('div', valueFn({ + $compileProvider.directive('input', valueFn({ restrict: 'ECA', link: function(scope, element, attr) { scope.attr = attr; @@ -1343,7 +1344,7 @@ describe('$compile', function() { })); }); inject(function($compile, $rootScope) { - element = $compile('<div></div>')($rootScope); + element = $compile('<input></input>')($rootScope); attr = $rootScope.attr; expect(attr).toBeDefined(); }); |
