diff --git a/CHANGELOG.md b/CHANGELOG.md
index c6ab167..f7c67dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,13 @@
CHANGELOG
=========
+## 0.5.2 (2017-04-19)
+
+- Update `bootstrap-switch` to `~3.3.4`
+- Fix `jquery` import in tests
+- Fix `npm` dependencies
+- Fix `README` headings
+
## 0.5.1 (2016-06-04)
- Make `switch-change` trigger when model changes
@@ -19,7 +26,7 @@ CHANGELOG
**BREAKING CHANGES:**
- Applications relying on `undefined` as the only indeterminate state
- may break if they consider `null` a falsy value. `null` is now an
+ may break if they consider `null` a falsy value. `null` is now an
indeterminate value.
## 0.4.1 (2015-06-15)
diff --git a/README.md b/README.md
index a10f7d7..1108f55 100644
--- a/README.md
+++ b/README.md
@@ -8,9 +8,9 @@ angular-bootstrap-switch
AngularJS directive for the [bootstrap-switch](https://github.com/nostalgiaz/bootstrap-switch) jQuery plugin.
-##Usage
+## Usage
-###Installation
+### Installation
```shell
$ bower install angular-bootstrap-switch
```
@@ -23,7 +23,7 @@ $ npm install angular-bootstrap-switch
This will install AngularJS, jQuery, and the original bootstrap-switch.
-###Registration
+### Registration
To be able to use the directive, you need to register the `angular-bootstrap-switch` module as a dependency:
@@ -33,7 +33,7 @@ angular.module('yourModule', ['frapontillo.bootstrap-switch'
]);
```
-###Directive
+### Directive
The directive can work on both element and attribute levels. The following example contains all of the supported attributes:
```html
@@ -63,9 +63,9 @@ The directive can work on both element and attribute levels. The following examp
Short doc for all of the attributes:
* `ng-model`, the value to bind the switch to
-* `type`, has to be one of `checkbox` and `radio`.
+* `type`, has to be one of `checkbox` and `radio`.
This value is mandatory and must be a string, as it cannot be changed once set (see [this answer on StackOverflow](http://stackoverflow.com/a/15155407/801065)).
-If you choose `radio`, be sure to follow the [AngularJS radio specs](https://docs.angularjs.org/api/ng/input/input%5Bradio%5D),
+If you choose `radio`, be sure to follow the [AngularJS radio specs](https://docs.angularjs.org/api/ng/input/input%5Bradio%5D),
meaning you have to specify the same `ngModel` and a different `value` or `ng-value` attribute for each radio
* `switch-active`, determines if the switch is enabled or not (changes the inner input's `disabled` attribute)
* `switch-readonly`, determines if the switch is read-only or not (changes the inner input's `readonly` attribute)
@@ -84,21 +84,21 @@ meaning you have to specify the same `ngModel` and a different `value` or `ng-va
* `switch-inverse`, inverts the on/off handles
* `switch-change`, evaluates an expression whenever the model value changes. Instead, `ng-change` will fire when view value changes (e.g from a click)
-###Migrating from bootstrap-switch~2
+### Migrating from bootstrap-switch~2
Read the [CHANGELOG](CHANGELOG.md#030-alpha1-2014-02-22) information to learn what's different in `0.3.0`.
-###Examples
+### Examples
The `example` folder shows a simple working demo of the switch.
-###Compatibility
+### Compatibility
IE8 requires you to attach the directive to an `` or ``. Due to some incompatibilities it is not possible to use a custom tag or `div` instead.
-##Development
+## Development
-###Test and build
+### Test and build
To build the directive yourself you need to have NodeJS. Then do the following:
@@ -110,18 +110,18 @@ $ grunt test-travis
$ grunt build
```
-###Contribute
+### Contribute
To contribute, please follow the generic [AngularJS Contributing Guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md), with the only exception to send the PR to the `develop` branch instead of `master`.
-##Author
+## Author
Francesco Pontillo ()
-##License
+## License
```
- Copyright 2014-2015-2016 Francesco Pontillo
+ Copyright 2014-2017 Francesco Pontillo
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/bower.json b/bower.json
index 356c9eb..204ae4f 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "angular-bootstrap-switch",
- "version": "0.5.1",
+ "version": "0.5.2",
"author": {
"name": "Francesco Pontillo",
"email": "francescopontillo@gmail.com",
@@ -22,7 +22,7 @@
"angular": ">=1.4.0",
"jquery": ">=1.9.0",
"bootstrap": ">=2.3.2",
- "bootstrap-switch": "3.3.2"
+ "bootstrap-switch": "~3.3.4"
},
"devDependencies": {
"angular-mocks": ">=1.4.0",
diff --git a/dist/angular-bootstrap-switch.js b/dist/angular-bootstrap-switch.js
index 1533ff9..70756d8 100644
--- a/dist/angular-bootstrap-switch.js
+++ b/dist/angular-bootstrap-switch.js
@@ -1,6 +1,6 @@
/**
* angular-bootstrap-switch
- * @version v0.5.1 - 2016-06-04
+ * @version v0.5.2 - 2017-04-19
* @author Francesco Pontillo (francescopontillo@gmail.com)
* @link https://github.com/frapontillo/angular-bootstrap-switch
* @license Apache License 2.0(http://www.apache.org/licenses/LICENSE-2.0.html)
diff --git a/dist/angular-bootstrap-switch.min.js b/dist/angular-bootstrap-switch.min.js
index 6d639b8..e1a26ea 100644
--- a/dist/angular-bootstrap-switch.min.js
+++ b/dist/angular-bootstrap-switch.min.js
@@ -1,6 +1,6 @@
/**
* angular-bootstrap-switch
- * @version v0.5.1 - 2016-06-04
+ * @version v0.5.2 - 2017-04-19
* @author Francesco Pontillo (francescopontillo@gmail.com)
* @link https://github.com/frapontillo/angular-bootstrap-switch
* @license Apache License 2.0(http://www.apache.org/licenses/LICENSE-2.0.html)
diff --git a/karma-chrome.conf.js b/karma-chrome.conf.js
index f438fec..48cbb21 100644
--- a/karma-chrome.conf.js
+++ b/karma-chrome.conf.js
@@ -15,7 +15,7 @@ module.exports = function(config) {
// list of files / patterns to load in the browser
files: [
- 'bower_components/jquery/dist/jquery.js',
+ 'bower_components/jquery/jquery.js',
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/bootstrap-switch/dist/js/bootstrap-switch.js',
diff --git a/karma.conf.js b/karma.conf.js
index d4d4789..04746db 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -15,7 +15,7 @@ module.exports = function(config) {
// list of files / patterns to load in the browser
files: [
- 'bower_components/jquery/dist/jquery.js',
+ 'bower_components/jquery/jquery.js',
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/bootstrap-switch/dist/js/bootstrap-switch.js',
diff --git a/package.json b/package.json
index 217ea47..86b032b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "angular-bootstrap-switch",
- "version": "0.5.1",
+ "version": "0.5.2",
"main": "dist/angular-bootstrap-switch.js",
"author": {
"name": "Francesco Pontillo",
@@ -13,7 +13,12 @@
"url": "git@github.com:frapontillo/angular-bootstrap-switch.git"
},
"license": "Apache-2.0",
- "dependencies": {},
+ "dependencies": {
+ "angular": ">=1.4.0",
+ "jquery": ">=1.9.0",
+ "bootstrap": ">=2.3.2",
+ "bootstrap-switch": "3.3.2"
+ },
"devDependencies": {
"grunt": "~0.4.5",
"grunt-contrib-clean": "~0.7.0",
diff --git a/src/directives/bsSwitch.js b/src/directives/bsSwitch.js
index 7e1f7f8..210e2d0 100644
--- a/src/directives/bsSwitch.js
+++ b/src/directives/bsSwitch.js
@@ -150,6 +150,12 @@ angular.module('frapontillo.bootstrap-switch')
controller.$setViewValue(controller.$modelValue);
} else {
controller.$setViewValue(viewValue);
+ controller.$formatters[0] = function(value) {
+ if (value === undefined || value === null) {
+ return value;
+ }
+ return angular.equals(value, getTrueValue());
+ };
}
}
};
@@ -176,6 +182,12 @@ angular.module('frapontillo.bootstrap-switch')
// When the model changes
controller.$render = function () {
initMaybe();
+
+ // WORKAROUND for https://github.com/Bttstrp/bootstrap-switch/issues/540
+ // to update model value when bootstrapSwitch is disabled we should
+ // re-enable it and only then update 'state'
+ element.bootstrapSwitch('disabled', '');
+
var newValue = controller.$modelValue;
if (newValue !== undefined && newValue !== null) {
element.bootstrapSwitch('state', newValue === getTrueValue(), true);
@@ -183,6 +195,10 @@ angular.module('frapontillo.bootstrap-switch')
element.bootstrapSwitch('indeterminate', true, true);
controller.$setViewValue(undefined);
}
+
+ // return initial value for "disabled"
+ setActive();
+
switchChange();
};
diff --git a/test/spec/directives/bsSwitchSpec.js b/test/spec/directives/bsSwitchSpec.js
index 41bdcdb..07cd1f0 100644
--- a/test/spec/directives/bsSwitchSpec.js
+++ b/test/spec/directives/bsSwitchSpec.js
@@ -391,6 +391,34 @@ describe('Directive: bsSwitch', function () {
it('should change the model, then deactivate the switch', inject(makeTestChangeModelThenDeactivate()));
it('should change the model, deactivate the switch (input)', inject(makeTestChangeModelThenDeactivate(true)));
+ // Test a model change when switch is deactivated
+ function makeTestChangeModelWhenSwitchIsDeactivated() {
+ return function () {
+ var element = compileDirective('active');
+ scope.model = false;
+ scope.isActive = false;
+ scope.$apply();
+ $timeout.flush();
+ // test the active state, should be false
+ expect(element.hasClass(CONST.SWITCH_DISABLED_CLASS)).toBeTruthy();
+ expect(element.find(CONST.INPUT_SELECTOR).attr('disabled')).toBeTruthy();
+ // test the model, should be false
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeFalsy();
+
+ scope.model = true;
+ scope.$apply();
+
+ // test the active state, should be false
+ expect(element.hasClass(CONST.SWITCH_DISABLED_CLASS)).toBeTruthy();
+ expect(element.find(CONST.INPUT_SELECTOR).attr('disabled')).toBeTruthy();
+ // test the model, should be true
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ };
+ }
+ it('should deactivate the switch, then change the model', inject(makeTestChangeModelWhenSwitchIsDeactivated()));
+
// Test the activation
function makeTestActivate(input) {
return function () {
@@ -723,4 +751,140 @@ describe('Directive: bsSwitch', function () {
}
it('should evaluate change expression when model changes', inject(makeTestModelSwitchChange()));
it('should evaluate change expression when model changes', inject(makeTestModelSwitchChange(true)));
+
+ // Test the null model from true state
+ function makeTestToIndeterminateNullFromTrue(input) {
+ return function () {
+ var element = compileDirective(undefined, input);
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ scope.model = true;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ scope.model = null;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ };
+ }
+ it('should change from true to the indeterminate state when the model is null', inject(makeTestToIndeterminateNullFromTrue()));
+ it('should change from true to the indeterminate state when the model is null (input)', inject(makeTestToIndeterminateNullFromTrue(true)));
+
+ // Test the null model from false state
+ function makeTestToIndeterminateNullFromFalse(input) {
+ return function () {
+ var element = compileDirective(undefined, input);
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ scope.model = false;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeTruthy();
+ scope.model = null;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeFalsy();
+ };
+ }
+ it('should change from false to the indeterminate state when the model is null', inject(makeTestToIndeterminateNullFromFalse()));
+ it('should change from false to the indeterminate state when the model is null (input)', inject(makeTestToIndeterminateNullFromFalse(true)));
+
+ // Test the undefined model from true state
+ function makeTestToIndeterminateUndefinedFromTrue(input) {
+ return function () {
+ var element = compileDirective(undefined, input);
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ scope.model = true;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ scope.model = undefined;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ };
+ }
+ it('should change from true to the indeterminate state when the model is null', inject(makeTestToIndeterminateUndefinedFromTrue()));
+ it('should change from true to the indeterminate state when the model is null (input)', inject(makeTestToIndeterminateUndefinedFromTrue(true)));
+
+ // Test the undefined model from false state
+ function makeTestToIndeterminateUndefinedFromFalse(input) {
+ return function () {
+ var element = compileDirective(undefined, input);
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ scope.model = false;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeTruthy();
+ scope.model = undefined;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeFalsy();
+ };
+ }
+ it('should change from false to the indeterminate state when the model is null', inject(makeTestToIndeterminateUndefinedFromFalse()));
+ it('should change from false to the indeterminate state when the model is null (input)', inject(makeTestToIndeterminateUndefinedFromFalse(true)));
+
+ // Test the changing multiple state
+ function makeTestMultipleChangeOfStateIndeterminate(input) {
+ return function () {
+ var element = compileDirective(undefined, input);
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ scope.model = false;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeTruthy();
+ scope.model = undefined;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeFalsy();
+ scope.model = true;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ };
+ }
+ it('should change from false to the indeterminate state and to true', inject(makeTestMultipleChangeOfStateIndeterminate()));
+ it('should change from false to the indeterminate state and to true (input)', inject(makeTestMultipleChangeOfStateIndeterminate(true)));
+
+ // Test the changing multiple state other way round
+ function makeTestMultipleChangeOfStateIndeterminateReverse(input) {
+ return function () {
+ var element = compileDirective(undefined, input);
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ scope.model = true;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ scope.model = undefined;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeTruthy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeTruthy();
+ scope.model = false;
+ scope.$apply();
+ expect(element.hasClass(CONST.SWITCH_INDETERMINATE_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_ON_CLASS)).toBeFalsy();
+ expect(element.hasClass(CONST.SWITCH_OFF_CLASS)).toBeTruthy();
+ };
+ }
+ it('should change from false to the indeterminate state and to false', inject(makeTestMultipleChangeOfStateIndeterminateReverse()));
+ it('should change from false to the indeterminate state and to false (input)', inject(makeTestMultipleChangeOfStateIndeterminateReverse(true)));
});