github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/public/static/js/directives/directives.tristateCheckbox.js (about) 1 var directives = directives || {}; 2 3 directives.tristateCheckbox = angular.module('directives.tristateCheckbox', []); 4 5 directives.tristateCheckbox.directive('tristateCheckbox', function(){ 6 return { 7 require: '?ngModel', 8 link: function(scope, el, attrs, ctrl) { 9 // Tri-state checkboxes can be bound to an ng-model (like a regular 10 // checkbox) but instead of rendering according to just true/false, 11 // it renders according to 3 possible values for the model it's bound to 12 var truthy = true; // checked 13 var falsy = false; // unchecked 14 var nully = null; // indeterminate! 15 16 ctrl.$formatters = []; 17 ctrl.$parsers = []; 18 19 ctrl.$render = function() { 20 var d = ctrl.$viewValue; // gets the value bound via ng-model 21 22 // el is the actual DOM element bound to this instance of 23 // the directive - set its checked/indeterminate DOM properties 24 // according to the value in the model 25 el.data('checked', d); 26 switch(d){ 27 case truthy: 28 el.prop('indeterminate', false); 29 el.prop('checked', true); 30 break; 31 case falsy: 32 el.prop('indeterminate', false); 33 el.prop('checked', false); 34 break; 35 default: 36 el.prop('indeterminate', true); 37 } 38 }; 39 40 // Override the behavior for the click handler for the checkbox. 41 // This is the value that will actually get sent to the getter/setter 42 // function for ng-model, when that option is in effect. 43 el.bind('click', function() { 44 var d; 45 switch(el.data('checked')){ 46 case falsy: 47 d = truthy; 48 break; 49 case truthy: 50 d = nully; 51 break; 52 default: 53 d = falsy; 54 } 55 ctrl.$setViewValue(d); 56 scope.$apply(ctrl.$render); 57 }); 58 } 59 }; 60 })