diff --git a/bower.json b/bower.json index 829a510..c403995 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-indeterminate", - "version": "1.1.0", + "version": "2.0.0", "description": "Tri-state indeterminate checkboxes in Angular", "main": "dist/angular-indeterminate.js", "authors": [ diff --git a/dist/angular-indeterminate.js b/dist/angular-indeterminate.js deleted file mode 100644 index d052d6e..0000000 --- a/dist/angular-indeterminate.js +++ /dev/null @@ -1,80 +0,0 @@ -(function() { - (function() { - return angular.module('ngIndeterminant', []).directive('indeterminate', function($parse) { - return { - restrict: 'A', - link: function(scope, elem, attrs) { - var disabledKey, falseValue, propKey, trueValue; - propKey = attrs.indeterminateKey || 'enabled'; - disabledKey = attrs.indeterminateDisabled || 'adminDisabled'; - trueValue = true; - falseValue = false; - if ((attrs.ngTrueValue != null) && (attrs.ngFalseValue != null)) { - trueValue = $parse(attrs.ngTrueValue)(scope); - falseValue = $parse(attrs.ngFalseValue)(scope); - } else if ((attrs.ngTrueValue != null) || (attrs.ngFalseValue != null)) { - throw new Error("Must have both ngTrueValue and ngFalseValue set"); - } - scope.$watch((function() { - var values; - values = scope.$eval(attrs.indeterminate); - return values.filter(function(v) { - return !v[disabledKey]; - }).filter(function(v) { - return v[propKey] === trueValue; - }).length + values.length; - }), function() { - var enabled, ref, values; - values = scope.$eval(attrs.indeterminate).filter(function(v) { - return !v[disabledKey]; - }); - enabled = values.filter(function(v) { - return v[propKey] === trueValue; - }); - elem[0].indeterminate = (0 < (ref = enabled.length) && ref < values.length); - if (enabled.length === values.length) { - return elem[0].checked = true; - } else { - return elem[0].checked = false; - } - }); - return elem.on('click', function(e) { - return scope.$apply(function() { - var enabled, i, item, j, len, len1, results, results1, values; - values = scope.$eval(attrs.indeterminate).filter(function(v) { - return !v[disabledKey]; - }); - enabled = values.filter(function(v) { - return v[propKey] === trueValue; - }); - if (enabled.length < values.length) { - results = []; - for (i = 0, len = values.length; i < len; i++) { - item = values[i]; - if (!item[disabledKey]) { - results.push(item[propKey] = trueValue); - } else { - results.push(void 0); - } - } - return results; - } else { - results1 = []; - for (j = 0, len1 = values.length; j < len1; j++) { - item = values[j]; - if (!item[disabledKey]) { - results1.push(item[propKey] = falseValue); - } else { - results1.push(void 0); - } - } - return results1; - } - }); - }); - } - }; - }); - })(); - -}).call(this); diff --git a/gulp-tasks/default.js b/gulp-tasks/default.js deleted file mode 100644 index 24b1bd4..0000000 --- a/gulp-tasks/default.js +++ /dev/null @@ -1,7 +0,0 @@ -var coffee = require('gulp-coffee'); - -module.exports = function() { - return this.gulp.src("src/*.coffee") - .pipe(coffee()) - .pipe(this.gulp.dest("dist")); -}; diff --git a/index.js b/index.js new file mode 100644 index 0000000..fd0b5de --- /dev/null +++ b/index.js @@ -0,0 +1,53 @@ +angular.module('ngIndeterminate', []) + .directive('indeterminate', ($parse) => { + return { + restrict: 'AE', + link: (scope, elem, attrs) => { + let propKey = attrs.indeterminateKey || 'enabled'; + let disabledKey = attrs.indeterminateDisabled || 'adminDisabled'; + let trueValue = true; + let falseValue = false; + if (attrs.ngTrueValue && attrs.ngFalseValue) { + trueValue = $parse(attrs.ngTrueValue)(scope); + falseValue = $parse(attrs.ngFalseValue)(scope); + } + else if (attrs.ngTrueValue || attrs.ngFalseValue) { + throw new Error('Must have both ngTrueValue and ngFalseValue set'); + } + + // Watch for changes to the list that comprises the indeterminate checkbox + scope.$watch(() => { + const values = scope.$eval(attrs.indeterminate); + return values.filter(v => !v[disabledKey]).filter(v => v[propKey] === trueValue).length + values.length; + }, () => { + const values = scope.$eval(attrs.indeterminate).filter(v => !v[disabledKey]); + const enabled = values.filter(v => v[propKey] === trueValue); + elem[0].indeterminate = 0 < enabled.length && enabled.length < values.length; + if (enabled.length === values.length) { + elem[0].checked = true; + } else { + elem[0].checked = false; + } + }); + + // Update the list when the indeterminate is clicked + elem.on('click', (e) => { + scope.$apply(() => { + const values = scope.$eval(attrs.indeterminate).filter(v => !v[disabledKey]); + const enabled = values.filter(v => v[propKey] === trueValue); + let setValue; + if (enabled.length < values.length) { + setValue = trueValue; + } else { + setValue = falseValue; + } + for (let i = 0; i < values.length; i++) { + if (!values[i][disabledKey]) values[i][propKey] = setValue; + } + }); + }); + }, + }; + }); + +if (typeof exports !== 'undefined' && typeof module !== 'undefined') module.exports = exports = 'ngIndeterminate'; diff --git a/karma.conf.js b/karma.conf.js index 58d2c9b..7929a67 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -7,17 +7,23 @@ module.exports = function(config) { 'node_modules/jquery/dist/jquery.js', 'node_modules/angular/angular.js', 'node_modules/angular-mocks/angular-mocks.js', - 'src/*.coffee', - 'tests/*.coffee' + 'index.js', + 'spec.js' ], reporters: ['coverage','spec','junit'], preprocessors: { - 'src/*.coffee': ['coverage'], - 'tests/*.coffee': ['coffee'] + '*.js': ['coverage', 'babel'], }, - coffeePreprocessor: { + babelPreprocessor: { options: { - sourceMap: true + presets: ['es2015'], + sourceMap: 'inline' + }, + filename: function (file) { + return file.originalPath.replace(/\.js$/, '.es5.js'); + }, + sourceFileName: function (file) { + return file.originalPath; } }, junitReporter: { @@ -27,12 +33,6 @@ module.exports = function(config) { }, coverageReporter: { dir : 'coverage', - instrumenters: { - ibrik: require('ibrik') - }, - instrumenter: { - '**/*.coffee': 'ibrik' - }, reporters: [ { type: 'cobertura', subdir: '.'}, { type: 'html', subdir: '.' } diff --git a/package.json b/package.json index e0382e4..fbc8ecd 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,14 @@ { "name": "angular-indeterminate", - "version": "1.1.0", + "version": "2.0.0", "description": "Tri-state indeterminate checkboxes in Angular", "scripts": { "test": "gulp unit", - "precommit": "echo 'Running pre-commit tasks...'; gulp unit && gulp && git add dist" + "precommit": "echo 'Running pre-commit tasks...'; gulp unit" }, - "pre-commit": ["precommit"], + "pre-commit": [ + "precommit" + ], "repository": { "type": "git", "url": "git+https://github.com/tjsail33/angular-indeterminate.git" @@ -28,6 +30,7 @@ "devDependencies": { "angular": "^1.5.8", "angular-mocks": "^1.5.8", + "babel-preset-es2015": "^6.18.0", "gulp": "^3.9.1", "gulp-bump": "^2.4.0", "gulp-coffee": "^2.3.2", @@ -37,6 +40,7 @@ "jasmine": "^2.5.1", "jquery": "^3.1.0", "karma": "^1.3.0", + "karma-babel-preprocessor": "^6.0.1", "karma-coffee-preprocessor": "^1.0.1", "karma-coverage": "^1.1.1", "karma-jasmine": "^1.0.2", diff --git a/spec.js b/spec.js new file mode 100644 index 0000000..e8e1c48 --- /dev/null +++ b/spec.js @@ -0,0 +1,332 @@ +describe('Indeterminate Checkbox Directive', function() { + + beforeEach(module('ngIndeterminate')); + + beforeEach(inject(function($compile, $rootScope) { + this.rootScope = $rootScope;; + this.compile = $compile; + })); + + it('should create an indeterminate checkbox', function() { + const html = '
';; + const scope = this.rootScope.$new();; + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope);; + $('body').append(elem);; + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + scope.ctrl.list[0].enabled = true; + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + }); + + it('should create an indeterminate checkbox with custom indeterminateKey', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ checked: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ checked: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + scope.ctrl.list.push({ checked: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + scope.ctrl.list[0].checked = true + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + }); + + describe('custom ngTrueValue and ngFalseValue', function() { + it('should throw without ngTrueValue', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + trueValue: 'test', + }; + expect(() => this.compile(html)(scope)).toThrow(new Error("Must have both ngTrueValue and ngFalseValue set")); + }); + + it('should throw without ngFalseValue', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + trueValue: 'test', + }; + expect(() => this.compile(html)(scope)).toThrow(new Error("Must have both ngTrueValue and ngFalseValue set")); + }); + + it('should create an indeterminate checkbox', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + trueValue: 'test', + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: 0 }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: 1 }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + scope.ctrl.list.push({ enabled: 1 }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + scope.ctrl.list[0].enabled = 1; + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + }); + + it('should handle clicks', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + trueValue: 'test', + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: 'fv' }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: 'tv' }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + scope.ctrl.list.push({ enabled: 'tv' }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + elem.find('.indt').click() + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt')[0].checked).toBeTruthy(); + expect(scope.ctrl.list[0].enabled).toBe('tv'); + elem.find('.indt').click(); + expect(elem.find('.indt')[0].checked).toBeFalsy(); + expect(scope.ctrl.list[0].enabled).toBe('fv'); + expect(scope.ctrl.list[1].enabled).toBe('fv'); + expect(scope.ctrl.list[2].enabled).toBe('fv'); + }); + }); + + describe('should handle clicks', function() { + it('when indeterminate', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeTruthy(); + scope.ctrl.list.push({ enabled: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeFalsy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + expect(elem.find('.indt').is(':checked')).toBeFalsy(); + elem.find('.indt').click() + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(scope.ctrl.list[0].enabled).toBeTruthy(); + expect(elem.find('.indt').is(':checked')).toBeTruthy(); + }); + + it('when checked', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeTruthy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeTruthy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeTruthy(); + elem.find('.indt').click() + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeFalsy(); + expect(scope.ctrl.list[0].enabled).toBeFalsy(); + expect(scope.ctrl.list[1].enabled).toBeFalsy(); + }); + + it('when unchecked', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeTruthy(); + scope.ctrl.list.push({ enabled: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeFalsy(); + scope.ctrl.list.push({ enabled: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeFalsy(); + elem.find('.indt').click() + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt').is(':checked')).toBeTruthy(); + expect(scope.ctrl.list[0].enabled).toBeTruthy(); + expect(scope.ctrl.list[1].enabled).toBeTruthy(); + }); + }); + + describe('disabled child', function() { + + it('should handle state', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false, adminDisabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + scope.ctrl.list[1].enabled = true; + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + }); + + it('should handle click from indeterminate', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false, adminDisabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeTruthy(); + elem.find('.indt').click() + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt')[0].checked).toBeTruthy(); + expect(scope.ctrl.list[0].enabled).toBeFalsy(); + expect(scope.ctrl.list[1].enabled).toBeTruthy(); + expect(scope.ctrl.list[1].enabled).toBeTruthy(); + }); + + it('should handle click from unchecked', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false, adminDisabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt')[0].checked).toBeFalsy(); + elem.find('.indt').click() + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt')[0].checked).toBeTruthy(); + expect(scope.ctrl.list[0].enabled).toBeFalsy(); + expect(scope.ctrl.list[1].enabled).toBeTruthy(); + expect(scope.ctrl.list[1].enabled).toBeTruthy(); + }); + + it('should handle click from checked', function() { + const html = ''; + const scope = this.rootScope.$new(); + scope.ctrl = { + list: [], + }; + const elem = this.compile(html)(scope); + $('body').append(elem); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: false, adminDisabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + scope.ctrl.list.push({ enabled: true }); + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt')[0].checked).toBeTruthy(); + elem.find('.indt').click() + scope.$digest(); + expect(elem.find('.indt')[0].indeterminate).toBeFalsy(); + expect(elem.find('.indt')[0].checked).toBeFalsy(); + expect(scope.ctrl.list[0].enabled).toBeFalsy(); + expect(scope.ctrl.list[1].enabled).toBeFalsy(); + expect(scope.ctrl.list[1].enabled).toBeFalsy(); + }); + }); +}); diff --git a/src/angular-indeterminate.coffee b/src/angular-indeterminate.coffee deleted file mode 100644 index 0f951ab..0000000 --- a/src/angular-indeterminate.coffee +++ /dev/null @@ -1,39 +0,0 @@ -do -> - angular.module('ngIndeterminant', []).directive 'indeterminate', ($parse) -> - return { - restrict: 'A' - link: (scope, elem, attrs) -> - propKey = attrs.indeterminateKey or 'enabled' - disabledKey = attrs.indeterminateDisabled or 'adminDisabled' - trueValue = true - falseValue = false - if attrs.ngTrueValue? and attrs.ngFalseValue? - trueValue = $parse(attrs.ngTrueValue)(scope) - falseValue = $parse(attrs.ngFalseValue)(scope) - else if attrs.ngTrueValue? or attrs.ngFalseValue? - throw new Error "Must have both ngTrueValue and ngFalseValue set" - scope.$watch ( -> - values = scope.$eval(attrs.indeterminate) - values.filter((v) -> not v[disabledKey]).filter((v) -> v[propKey] is trueValue).length + values.length - ), -> - values = scope.$eval(attrs.indeterminate).filter((v) -> not v[disabledKey]) - enabled = values.filter((v) -> v[propKey] is trueValue) - elem[0].indeterminate = 0 < enabled.length < values.length - if enabled.length is values.length - elem[0].checked = true - else - elem[0].checked = false - - elem.on 'click', (e) -> - scope.$apply -> - values = scope.$eval(attrs.indeterminate).filter((v) -> not v[disabledKey]) - enabled = values.filter((v) -> v[propKey] is trueValue) - if enabled.length < values.length - for item in values - if not item[disabledKey] - item[propKey] = trueValue - else - for item in values - if not item[disabledKey] - item[propKey] = falseValue - } diff --git a/tests/angular-indeterminate.spec.coffee b/tests/angular-indeterminate.spec.coffee deleted file mode 100644 index 4625cc6..0000000 --- a/tests/angular-indeterminate.spec.coffee +++ /dev/null @@ -1,301 +0,0 @@ -describe 'Indeterminate Checkbox Directive', -> - - beforeEach module 'ngIndeterminant' - - beforeEach inject ($compile,$rootScope) -> - @rootScope = $rootScope - @compile = $compile - - it 'should create an indeterminate checkbox', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - scope.ctrl.list[0].enabled = true - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - - it 'should create an indeterminate checkbox with custom indeterminateKey', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { checked: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { checked: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - scope.ctrl.list.push { checked: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - scope.ctrl.list[0].checked = true - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - - describe 'custom ngTrueValue and ngFalseValue', -> - it 'should throw without ngTrueValue', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - trueValue: 'test' - expect(=> @compile(html)(scope)).toThrow(new Error "Must have both ngTrueValue and ngFalseValue set") - - it 'should throw without ngFalseValue', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - trueValue: 'test' - expect(=> @compile(html)(scope)).toThrow(new Error "Must have both ngTrueValue and ngFalseValue set") - - it 'should create an indeterminate checkbox', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - trueValue: 'test' - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: 0 } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: 1 } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - scope.ctrl.list.push { enabled: 1 } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - scope.ctrl.list[0].enabled = 1 - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - - it 'should handle clicks', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - trueValue: 'test' - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: 'fv' } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: 'tv' } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - scope.ctrl.list.push { enabled: 'tv' } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - elem.find('.indt').click() - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt')[0].checked).toBeTruthy() - expect(scope.ctrl.list[0].enabled).toBe 'tv' - elem.find('.indt').click() - expect(elem.find('.indt')[0].checked).toBeFalsy() - expect(scope.ctrl.list[0].enabled).toBe 'fv' - expect(scope.ctrl.list[1].enabled).toBe 'fv' - expect(scope.ctrl.list[2].enabled).toBe 'fv' - - describe 'should handle clicks', -> - it 'when indeterminate', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeTruthy() - scope.ctrl.list.push { enabled: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeFalsy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - expect(elem.find('.indt').is(':checked')).toBeFalsy() - elem.find('.indt').click() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(scope.ctrl.list[0].enabled).toBeTruthy() - expect(elem.find('.indt').is(':checked')).toBeTruthy() - - it 'when checked', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeTruthy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeTruthy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeTruthy() - elem.find('.indt').click() - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeFalsy() - expect(scope.ctrl.list[0].enabled).toBeFalsy() - expect(scope.ctrl.list[1].enabled).toBeFalsy() - - it 'when unchecked', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeTruthy() - scope.ctrl.list.push { enabled: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeFalsy() - scope.ctrl.list.push { enabled: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeFalsy() - elem.find('.indt').click() - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt').is(':checked')).toBeTruthy() - expect(scope.ctrl.list[0].enabled).toBeTruthy() - expect(scope.ctrl.list[1].enabled).toBeTruthy() - - describe 'disabled child', -> - - it 'should handle state', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false, adminDisabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - scope.ctrl.list[1].enabled = true - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - - it 'should handle click from indeterminate', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false, adminDisabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeTruthy() - elem.find('.indt').click() - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt')[0].checked).toBeTruthy() - expect(scope.ctrl.list[0].enabled).toBeFalsy() - expect(scope.ctrl.list[1].enabled).toBeTruthy() - expect(scope.ctrl.list[1].enabled).toBeTruthy() - - it 'should handle click from unchecked', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false, adminDisabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt')[0].checked).toBeFalsy() - elem.find('.indt').click() - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt')[0].checked).toBeTruthy() - expect(scope.ctrl.list[0].enabled).toBeFalsy() - expect(scope.ctrl.list[1].enabled).toBeTruthy() - expect(scope.ctrl.list[1].enabled).toBeTruthy() - - it 'should handle click from checked', -> - html = '' - scope = @rootScope.$new() - scope.ctrl = - list: [] - elem = @compile(html)(scope) - $('body').append(elem) - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: false, adminDisabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - scope.ctrl.list.push { enabled: true } - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt')[0].checked).toBeTruthy() - elem.find('.indt').click() - scope.$digest() - expect(elem.find('.indt')[0].indeterminate).toBeFalsy() - expect(elem.find('.indt')[0].checked).toBeFalsy() - expect(scope.ctrl.list[0].enabled).toBeFalsy() - expect(scope.ctrl.list[1].enabled).toBeFalsy() - expect(scope.ctrl.list[1].enabled).toBeFalsy()