Tutorial 26.1 ngModel
******************************************INDEX.HTML*****************************************************
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-accessibility-ng-model-production</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="//code.angularjs.org/snapshot/angular-aria.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="ngAria_ngModelExample">
<form>
<custom-checkbox role="checkbox" ng-model="checked" required
aria-label="Custom checkbox" show-attrs>
Custom checkbox
</custom-checkbox>
</form>
<hr />
<b>Is checked:</b> {{ !!checked }}
</body>
</html>
******************************************INDEX.HTML*****************************************************
********************************************script.js***************************************************
(function(angular) {
'use strict';
angular.
module('ngAria_ngModelExample', ['ngAria']).
directive('customCheckbox', customCheckboxDirective).
directive('showAttrs', showAttrsDirective);
function customCheckboxDirective() {
return {
restrict: 'E',
require: 'ngModel',
transclude: true,
template:
'<span class="icon" aria-hidden="true"></span> ' +
'<ng-transclude></ng-transclude>',
link: function(scope, elem, attrs, ctrl) {
// Overwrite necessary `NgModelController` methods
ctrl.$isEmpty = isEmpty;
ctrl.$render = render;
// Bind to events
elem.on('click', function(event) {
event.preventDefault();
scope.$apply(toggleCheckbox);
});
elem.on('keypress', function(event) {
event.preventDefault();
if (event.keyCode === 32 || event.keyCode === 13) {
scope.$apply(toggleCheckbox);
}
});
// Helpers
function isEmpty(value) {
return !value;
}
function render() {
elem[ctrl.$viewValue ? 'addClass' : 'removeClass']('checked');
}
function toggleCheckbox() {
ctrl.$setViewValue(!ctrl.$viewValue);
ctrl.$render();
}
}
};
}
function showAttrsDirective($timeout) {
return function(scope, elem, attrs) {
var pre = document.createElement('pre');
elem.after(pre);
scope.$watchCollection(function() {
return Array.prototype.slice.call(elem[0].attributes).reduce(function(aggr, attr) {
if (attr.name !== attrs.$attr.showAttrs) aggr[attr.name] = attr.value;
return aggr;
}, {});
}, function(newValues) {
$timeout(function() {
pre.textContent = angular.toJson(newValues, 2);
});
});
};
}
})(window.angular);
********************************************script.js***************************************************
******************************************Protractor.js*****************************************************
var checkbox = element(by.css('custom-checkbox'));
var checkedCheckbox = element(by.css('custom-checkbox.checked'));
it('should have the `checked` class only when checked', function() {
expect(checkbox.isPresent()).toBe(true);
expect(checkedCheckbox.isPresent()).toBe(false);
checkbox.click();
expect(checkedCheckbox.isPresent()).toBe(true);
checkbox.click();
expect(checkedCheckbox.isPresent()).toBe(false);
});
it('should have the `aria-checked` attribute set to the appropriate value', function() {
expect(checkedCheckbox.isPresent()).toBe(false);
expect(checkbox.getAttribute('aria-checked')).toBe('false');
checkbox.click();
expect(checkedCheckbox.isPresent()).toBe(true);
expect(checkbox.getAttribute('aria-checked')).toBe('true');
checkbox.click();
expect(checkedCheckbox.isPresent()).toBe(false);
expect(checkbox.getAttribute('aria-checked')).toBe('false');
});
******************************************Protractor.js*****************************************************
********************************************style.css***************************************************
custom-checkbox {
cursor: pointer;
display: inline-block;
}
custom-checkbox .icon:before {
content: '\2610';
display: inline-block;
font-size: 2em;
line-height: 1;
speak: none;
vertical-align: middle;
}
custom-checkbox.checked .icon:before {
content: '\2611';
}
********************************************style.css***************************************************
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-accessibility-ng-model-production</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="//code.angularjs.org/snapshot/angular-aria.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="ngAria_ngModelExample">
<form>
<custom-checkbox role="checkbox" ng-model="checked" required
aria-label="Custom checkbox" show-attrs>
Custom checkbox
</custom-checkbox>
</form>
<hr />
<b>Is checked:</b> {{ !!checked }}
</body>
</html>
******************************************INDEX.HTML*****************************************************
********************************************script.js***************************************************
(function(angular) {
'use strict';
angular.
module('ngAria_ngModelExample', ['ngAria']).
directive('customCheckbox', customCheckboxDirective).
directive('showAttrs', showAttrsDirective);
function customCheckboxDirective() {
return {
restrict: 'E',
require: 'ngModel',
transclude: true,
template:
'<span class="icon" aria-hidden="true"></span> ' +
'<ng-transclude></ng-transclude>',
link: function(scope, elem, attrs, ctrl) {
// Overwrite necessary `NgModelController` methods
ctrl.$isEmpty = isEmpty;
ctrl.$render = render;
// Bind to events
elem.on('click', function(event) {
event.preventDefault();
scope.$apply(toggleCheckbox);
});
elem.on('keypress', function(event) {
event.preventDefault();
if (event.keyCode === 32 || event.keyCode === 13) {
scope.$apply(toggleCheckbox);
}
});
// Helpers
function isEmpty(value) {
return !value;
}
function render() {
elem[ctrl.$viewValue ? 'addClass' : 'removeClass']('checked');
}
function toggleCheckbox() {
ctrl.$setViewValue(!ctrl.$viewValue);
ctrl.$render();
}
}
};
}
function showAttrsDirective($timeout) {
return function(scope, elem, attrs) {
var pre = document.createElement('pre');
elem.after(pre);
scope.$watchCollection(function() {
return Array.prototype.slice.call(elem[0].attributes).reduce(function(aggr, attr) {
if (attr.name !== attrs.$attr.showAttrs) aggr[attr.name] = attr.value;
return aggr;
}, {});
}, function(newValues) {
$timeout(function() {
pre.textContent = angular.toJson(newValues, 2);
});
});
};
}
})(window.angular);
********************************************script.js***************************************************
******************************************Protractor.js*****************************************************
var checkbox = element(by.css('custom-checkbox'));
var checkedCheckbox = element(by.css('custom-checkbox.checked'));
it('should have the `checked` class only when checked', function() {
expect(checkbox.isPresent()).toBe(true);
expect(checkedCheckbox.isPresent()).toBe(false);
checkbox.click();
expect(checkedCheckbox.isPresent()).toBe(true);
checkbox.click();
expect(checkedCheckbox.isPresent()).toBe(false);
});
it('should have the `aria-checked` attribute set to the appropriate value', function() {
expect(checkedCheckbox.isPresent()).toBe(false);
expect(checkbox.getAttribute('aria-checked')).toBe('false');
checkbox.click();
expect(checkedCheckbox.isPresent()).toBe(true);
expect(checkbox.getAttribute('aria-checked')).toBe('true');
checkbox.click();
expect(checkedCheckbox.isPresent()).toBe(false);
expect(checkbox.getAttribute('aria-checked')).toBe('false');
});
******************************************Protractor.js*****************************************************
********************************************style.css***************************************************
custom-checkbox {
cursor: pointer;
display: inline-block;
}
custom-checkbox .icon:before {
content: '\2610';
display: inline-block;
font-size: 2em;
line-height: 1;
speak: none;
vertical-align: middle;
}
custom-checkbox.checked .icon:before {
content: '\2611';
}
********************************************style.css***************************************************
Comments
Post a Comment