Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f664f9f45 | |||
| 955848c3b1 | |||
| 7a1d54c8c3 | |||
| 0ed1a59aef | |||
| f2722b59a5 | |||
| 57ed7e4f7f | |||
| 90848144e8 | |||
| a4d7076c8e | |||
| c824731ae8 | |||
| 1653afa210 | |||
| 7e2f2c1bad | |||
| 61f365abfd | |||
| ec2d9ad605 | |||
| 08b50ccb1c | |||
| 44ab0a8106 | |||
| 1962485504 | |||
| 8a4f625ef6 | |||
| 7be665399f | |||
| 2edb5d38cb | |||
| 4e06553f7c | |||
| 25ff206767 | |||
| 997813f0eb | |||
| 25db68e903 | |||
| 78559761dc | |||
| 14384fc40f | |||
| 58f1813aca | |||
| 9666c64f4a | |||
| f9f7e02d15 | |||
| a4bea6f229 | |||
| c00851a18b | |||
| c687acd489 | |||
| 3f70d76327 | |||
| 08ee30a91e | |||
| 7671bd6ed4 | |||
| 1a132dd757 | |||
| 9881a27397 | |||
| 294b151342 | |||
| 969eb9c74d | |||
| 048d85a2ad | |||
| 876e72a0df | |||
| 6734908108 | |||
| 515bcf2933 | |||
| 148371fb6d | |||
| 8047c06258 | |||
| 3e8ecfffe0 | |||
| ddcacb7a83 | |||
| 915eda0540 | |||
| f9eede7555 | |||
| fb5fabf580 | |||
| aef24cde4b | |||
| b893a93f82 | |||
| 6352f13e85 |
+1
-1
@@ -13,7 +13,7 @@ addons:
|
||||
before_install:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- npm install --quiet -g grunt-cli karma
|
||||
- npm install --quiet -g karma
|
||||
|
||||
script: grunt
|
||||
sudo: false
|
||||
|
||||
+148
-42
@@ -1,5 +1,98 @@
|
||||
<a name="2.3.2"></a>
|
||||
## [2.3.2](https://github.com/angular-ui/bootstrap/compare/2.3.1...v2.3.2) (2016-12-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dropdown:** re-add close([955848c](https://github.com/angular-ui/bootstrap/commit/955848c)), closes [#6382](https://github.com/angular-ui/bootstrap/issues/6382) [#6321](https://github.com/angular-ui/bootstrap/issues/6321) [#6357](https://github.com/angular-ui/bootstrap/issues/6357) [#6364](https://github.com/angular-ui/bootstrap/issues/6364)
|
||||
|
||||
|
||||
|
||||
<a name="2.3.1"></a>
|
||||
## [2.3.1](https://github.com/angular-ui/bootstrap/compare/2.3.0...v2.3.1) (2016-12-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dateparser:** add new date format for angular 1.5+ only([f2722b5](https://github.com/angular-ui/bootstrap/commit/f2722b5)), closes [#6349](https://github.com/angular-ui/bootstrap/issues/6349)
|
||||
|
||||
* **datepickerPopup:** change to toTimezone only([1962485](https://github.com/angular-ui/bootstrap/commit/1962485)), fixes [#6235](https://github.com/angular-ui/bootstrap/issues/6235)
|
||||
|
||||
* **modal:** revert focus behavior on open([8a4f625](https://github.com/angular-ui/bootstrap/commit/8a4f625)), closes [#6295](https://github.com/angular-ui/bootstrap/issues/6295)
|
||||
|
||||
<a name="2.3.0"></a>
|
||||
# [2.3.0](https://github.com/angular-ui/bootstrap/compare/2.2.0...2.3.0) (2016-11-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **dateparser:** add LLLL support([25ff206](https://github.com/angular-ui/bootstrap/commit/25ff206)), closes [#6281](https://github.com/angular-ui/bootstrap/issues/6281)
|
||||
|
||||
|
||||
|
||||
<a name="2.2.0"></a>
|
||||
# [2.2.0](https://github.com/angular-ui/bootstrap/compare/2.1.4...2.2.0) (2016-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dropdown:** exit keybind is not open ([14384fc](https://github.com/angular-ui/bootstrap/commit/14384fc)), closes [#6278](https://github.com/angular-ui/bootstrap/issues/6278) [#6208](https://github.com/angular-ui/bootstrap/issues/6208)
|
||||
* **modal:** improve ARIA support. ([f9f7e02](https://github.com/angular-ui/bootstrap/commit/f9f7e02)), closes [#6203](https://github.com/angular-ui/bootstrap/issues/6203)
|
||||
* **position:** correct scrollbar width calculation ([58f1813](https://github.com/angular-ui/bootstrap/commit/58f1813)), closes [#6273](https://github.com/angular-ui/bootstrap/issues/6273)
|
||||
* **tooltip:** cancel timeout when hidden ([7855976](https://github.com/angular-ui/bootstrap/commit/7855976)), closes [#6226](https://github.com/angular-ui/bootstrap/issues/6226) [#6221](https://github.com/angular-ui/bootstrap/issues/6221)
|
||||
|
||||
### Features
|
||||
|
||||
* **timepicker:** add validation information ([9666c64](https://github.com/angular-ui/bootstrap/commit/9666c64)), closes [#6230](https://github.com/angular-ui/bootstrap/issues/6230) [#6259](https://github.com/angular-ui/bootstrap/issues/6259)
|
||||
|
||||
|
||||
|
||||
<a name="2.1.4"></a>
|
||||
## [2.1.4](https://github.com/angular-ui/bootstrap/compare/2.1.3...2.1.4) (2016-09-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datepicker:** improve accessibility ([3f70d76](https://github.com/angular-ui/bootstrap/commit/3f70d76)), closes [#6247](https://github.com/angular-ui/bootstrap/issues/6247)
|
||||
* **dropdown:** prevent premature scope removal ([08ee30a](https://github.com/angular-ui/bootstrap/commit/08ee30a)), closes [#6238](https://github.com/angular-ui/bootstrap/issues/6238) [#6225](https://github.com/angular-ui/bootstrap/issues/6225)
|
||||
|
||||
|
||||
|
||||
<a name="2.1.3"></a>
|
||||
## [2.1.3](https://github.com/angular-ui/bootstrap/compare/2.1.2...2.1.3) (2016-08-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modal:** compile only once with component ([969eb9c](https://github.com/angular-ui/bootstrap/commit/969eb9c)), closes [#6202](https://github.com/angular-ui/bootstrap/issues/6202) [#6201](https://github.com/angular-ui/bootstrap/issues/6201)
|
||||
|
||||
|
||||
|
||||
<a name="2.1.2"></a>
|
||||
## [2.1.2](https://github.com/angular-ui/bootstrap/compare/2.1.1...2.1.2) (2016-08-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **collapse:** revert change to transition css ([515bcf2](https://github.com/angular-ui/bootstrap/commit/515bcf2)), closes [#6196](https://github.com/angular-ui/bootstrap/issues/6196) [#6194](https://github.com/angular-ui/bootstrap/issues/6194)
|
||||
* **datepicker:** fix accidental global ([ddcacb7](https://github.com/angular-ui/bootstrap/commit/ddcacb7)), closes [#6188](https://github.com/angular-ui/bootstrap/issues/6188)
|
||||
* **modal:** close and dismiss bindings on component ([3e8ecff](https://github.com/angular-ui/bootstrap/commit/3e8ecff)), closes [#6192](https://github.com/angular-ui/bootstrap/issues/6192) [#6191](https://github.com/angular-ui/bootstrap/issues/6191)
|
||||
|
||||
|
||||
|
||||
<a name="2.1.1"></a>
|
||||
## [2.1.1](https://github.com/angular-ui/bootstrap/compare/2.1.0...2.1.1) (2016-08-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **collapse:** default to css([aef24cd](https://github.com/angular-ui/bootstrap/commit/aef24cd)), closes [#6182](https://github.com/angular-ui/bootstrap/issues/6182) [#6045](https://github.com/angular-ui/bootstrap/issues/6045)
|
||||
* **modal:** switch to .append([fb5fabf](https://github.com/angular-ui/bootstrap/commit/fb5fabf)), closes [#6187](https://github.com/angular-ui/bootstrap/issues/6187) [#6186](https://github.com/angular-ui/bootstrap/issues/6186)
|
||||
|
||||
|
||||
|
||||
<a name="2.1.0"></a>
|
||||
# [2.1.0](https://github.com/angular-ui/bootstrap/compare/2.0.2...v2.1.0) (2016-08-19)
|
||||
# [2.1.0](https://github.com/angular-ui/bootstrap/compare/2.0.2...2.1.0) (2016-08-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -17,7 +110,7 @@
|
||||
|
||||
|
||||
<a name="2.0.2"></a>
|
||||
## [2.0.2](https://github.com/angular-ui/bootstrap/compare/2.0.1...v2.0.2) (2016-08-15)
|
||||
## [2.0.2](https://github.com/angular-ui/bootstrap/compare/2.0.1...2.0.2) (2016-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -28,7 +121,7 @@
|
||||
|
||||
|
||||
<a name="2.0.1"></a>
|
||||
## [2.0.1](https://github.com/angular-ui/bootstrap/compare/2.0.0...v2.0.1) (2016-08-02)
|
||||
## [2.0.1](https://github.com/angular-ui/bootstrap/compare/2.0.0...2.0.1) (2016-08-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -38,7 +131,7 @@
|
||||
|
||||
|
||||
<a name="2.0.0"></a>
|
||||
# [2.0.0](https://github.com/angular-ui/bootstrap/compare/1.3.3...v2.0.0) (2016-07-20)
|
||||
# [2.0.0](https://github.com/angular-ui/bootstrap/compare/1.3.3...2.0.0) (2016-07-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -118,7 +211,7 @@ This could affect selectors if they are being used.
|
||||
|
||||
|
||||
<a name="1.3.3"></a>
|
||||
## [1.3.3](https://github.com/angular-ui/bootstrap/compare/1.3.2...v1.3.3) (2016-05-23)
|
||||
## [1.3.3](https://github.com/angular-ui/bootstrap/compare/1.3.2...1.3.3) (2016-05-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -144,7 +237,7 @@ This could affect selectors if they are being used.
|
||||
|
||||
|
||||
<a name="1.3.2"></a>
|
||||
## [1.3.2](https://github.com/angular-ui/bootstrap/compare/1.3.1...v1.3.2) (2016-04-14)
|
||||
## [1.3.2](https://github.com/angular-ui/bootstrap/compare/1.3.1...1.3.2) (2016-04-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -170,7 +263,7 @@ This could affect selectors if they are being used.
|
||||
|
||||
|
||||
<a name="1.3.1"></a>
|
||||
## [1.3.1](https://github.com/angular-ui/bootstrap/compare/1.3.0...v1.3.1) (2016-04-05)
|
||||
## [1.3.1](https://github.com/angular-ui/bootstrap/compare/1.3.0...1.3.1) (2016-04-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -181,7 +274,7 @@ This could affect selectors if they are being used.
|
||||
|
||||
|
||||
<a name="1.3.0"></a>
|
||||
# [1.3.0](https://github.com/angular-ui/bootstrap/compare/1.2.5...v1.3.0) (2016-04-05)
|
||||
# [1.3.0](https://github.com/angular-ui/bootstrap/compare/1.2.5...1.3.0) (2016-04-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -224,7 +317,7 @@ attribute pass-throughs in the popup
|
||||
|
||||
|
||||
<a name="1.2.5"></a>
|
||||
## [1.2.5](https://github.com/angular-ui/bootstrap/compare/1.2.4...v1.2.5) (2016-03-20)
|
||||
## [1.2.5](https://github.com/angular-ui/bootstrap/compare/1.2.4...1.2.5) (2016-03-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -247,13 +340,13 @@ attribute pass-throughs in the popup
|
||||
|
||||
|
||||
<a name="1.2.4"></a>
|
||||
## [1.2.4](https://github.com/angular-ui/bootstrap/compare/1.2.3...v1.2.4) (2016-03-06)
|
||||
## [1.2.4](https://github.com/angular-ui/bootstrap/compare/1.2.3...1.2.4) (2016-03-06)
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.2.3"></a>
|
||||
## [1.2.3](https://github.com/angular-ui/bootstrap/compare/1.2.2...v1.2.3) (2016-03-06)
|
||||
## [1.2.3](https://github.com/angular-ui/bootstrap/compare/1.2.2...1.2.3) (2016-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -272,7 +365,7 @@ attribute pass-throughs in the popup
|
||||
|
||||
|
||||
<a name="1.2.2"></a>
|
||||
## [1.2.2](https://github.com/angular-ui/bootstrap/compare/1.2.1...v1.2.2) (2016-03-03)
|
||||
## [1.2.2](https://github.com/angular-ui/bootstrap/compare/1.2.1...1.2.2) (2016-03-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -289,7 +382,7 @@ attribute pass-throughs in the popup
|
||||
|
||||
|
||||
<a name="1.2.1"></a>
|
||||
## [1.2.1](https://github.com/angular-ui/bootstrap/compare/1.2.0...v1.2.1) (2016-02-27)
|
||||
## [1.2.1](https://github.com/angular-ui/bootstrap/compare/1.2.0...1.2.1) (2016-02-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -299,7 +392,7 @@ attribute pass-throughs in the popup
|
||||
|
||||
|
||||
<a name="1.2.0"></a>
|
||||
# [1.2.0](https://github.com/angular-ui/bootstrap/compare/1.1.2...v1.2.0) (2016-02-26)
|
||||
# [1.2.0](https://github.com/angular-ui/bootstrap/compare/1.1.2...1.2.0) (2016-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -359,7 +452,7 @@ template
|
||||
|
||||
|
||||
<a name="1.1.2"></a>
|
||||
## [1.1.2](https://github.com/angular-ui/bootstrap/compare/1.1.1...v1.1.2) (2016-02-01)
|
||||
## [1.1.2](https://github.com/angular-ui/bootstrap/compare/1.1.1...1.1.2) (2016-02-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -377,7 +470,7 @@ template
|
||||
|
||||
|
||||
<a name="1.1.1"></a>
|
||||
## [1.1.1](https://github.com/angular-ui/bootstrap/compare/v1.1.0...v1.1.1) (2016-01-25)
|
||||
## [1.1.1](https://github.com/angular-ui/bootstrap/compare/1.1.0...1.1.1) (2016-01-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -427,7 +520,7 @@ template in one's app and provide the necessary CSS
|
||||
|
||||
|
||||
<a name="1.0.3"></a>
|
||||
# [1.0.3](https://github.com/angular-ui/bootstrap/compare/v1.0.2...v1.0.3) (2016-01-12)
|
||||
# [1.0.3](https://github.com/angular-ui/bootstrap/compare/1.0.2...1.0.3) (2016-01-12)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -437,7 +530,7 @@ template in one's app and provide the necessary CSS
|
||||
|
||||
|
||||
<a name="1.0.2"></a>
|
||||
# [1.0.2](https://github.com/angular-ui/bootstrap/compare/v1.0.1...v1.0.2) (2016-01-12)
|
||||
# [1.0.2](https://github.com/angular-ui/bootstrap/compare/1.0.1...1.0.2) (2016-01-12)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -447,7 +540,7 @@ template in one's app and provide the necessary CSS
|
||||
|
||||
|
||||
<a name="1.0.1"></a>
|
||||
# [1.0.1](https://github.com/angular-ui/bootstrap/compare/1.0.0...v1.0.1) (2016-01-12)
|
||||
# [1.0.1](https://github.com/angular-ui/bootstrap/compare/1.0.0...1.0.1) (2016-01-12)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -468,7 +561,7 @@ template in one's app and provide the necessary CSS
|
||||
|
||||
|
||||
<a name="1.0.0"></a>
|
||||
# [1.0.0](https://github.com/angular-ui/bootstrap/compare/0.14.3...v1.0.0) (2016-01-08)
|
||||
# [1.0.0](https://github.com/angular-ui/bootstrap/compare/0.14.3...1.0.0) (2016-01-08)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -613,7 +706,7 @@ $scope.typeaheadContainer = angular.element(document.querySelector('#typeaheadCo
|
||||
|
||||
|
||||
<a name="0.14.3"></a>
|
||||
# [0.14.3](https://github.com/angular-ui/bootstrap/compare/0.14.2...v0.14.3) (2015-10-23)
|
||||
# [0.14.3](https://github.com/angular-ui/bootstrap/compare/0.14.2...0.14.3) (2015-10-23)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -638,7 +731,7 @@ $scope.typeaheadContainer = angular.element(document.querySelector('#typeaheadCo
|
||||
|
||||
|
||||
<a name="0.14.2"></a>
|
||||
# [0.14.2](https://github.com/angular-ui/bootstrap/compare/0.14.1...v0.14.2) (2015-10-14)
|
||||
# [0.14.2](https://github.com/angular-ui/bootstrap/compare/0.14.1...0.14.2) (2015-10-14)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -650,7 +743,7 @@ $scope.typeaheadContainer = angular.element(document.querySelector('#typeaheadCo
|
||||
|
||||
|
||||
<a name="0.14.1"></a>
|
||||
# [0.14.1](https://github.com/angular-ui/bootstrap/compare/0.14.0...v0.14.1) (2015-10-11)
|
||||
# [0.14.1](https://github.com/angular-ui/bootstrap/compare/0.14.0...0.14.1) (2015-10-11)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -833,7 +926,7 @@ $scope.typeaheadContainer = angular.element(document.querySelector('#typeaheadCo
|
||||
|
||||
|
||||
<a name"0.13.3"></a>
|
||||
# 0.13.3 (2015-08-09)
|
||||
# [0.13.3](https://github.com/angular-ui/bootstrap/compare/0.13.2...0.13.3) (2015-08-09)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -920,7 +1013,7 @@ Closes #4080
|
||||
|
||||
|
||||
<a name"0.13.2"></a>
|
||||
# 0.13.2 (2015-08-02)
|
||||
# [0.13.2](https://github.com/angular-ui/bootstrap/compare/0.13.1...0.13.2) (2015-08-02)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -966,7 +1059,7 @@ Closes #4080
|
||||
|
||||
|
||||
<a name"0.13.1"></a>
|
||||
# 0.13.1 (2015-07-23)
|
||||
# [0.13.1](https://github.com/angular-ui/bootstrap/compare/0.13.0...0.13.1) (2015-07-23)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -1027,7 +1120,7 @@ Closes #4080
|
||||
|
||||
|
||||
<a name="0.13.0"></a>
|
||||
# 0.13.0 (2015-05-02)
|
||||
# [0.13.0](https://github.com/angular-ui/bootstrap/compare/0.12.1...0.13.0) (2015-05-02)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -1126,7 +1219,8 @@ Closes #4080
|
||||
* **transition:** deprecate transition module ([8a552443](https://github.com/angular-ui/bootstrap/commit/8a552443741d1e5b4b29d9da9c7e9990fa37886c), closes [#3497](https://github.com/angular-ui/bootstrap/issues/3497))
|
||||
|
||||
|
||||
# 0.12.1 (2015-02-20)
|
||||
<a name="0.12.1"></a>
|
||||
# [0.12.1](https://github.com/angular-ui/bootstrap/compare/0.12.0...0.12.1) (2015-02-20)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
@@ -1134,7 +1228,7 @@ Closes #4080
|
||||
- incorrect position when text wraps ([5726e3ef](http://github.com/angular-ui/bootstrap/commit/5726e3ef))
|
||||
|
||||
<a name="0.12.0"></a>
|
||||
# 0.12.0 (2014-11-16)
|
||||
# [0.12.0](https://github.com/angular-ui/bootstrap/compare/0.11.2...0.12.0) (2014-11-16)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
@@ -1187,11 +1281,13 @@ once* and can no longer be changed after initialization.
|
||||
```
|
||||
|
||||
|
||||
# 0.11.2 (2014-09-26)
|
||||
<a name="0.11.2"></a>
|
||||
# [0.11.2](https://github.com/angular-ui/bootstrap/compare/0.11.1...0.11.2) (2014-09-26)
|
||||
|
||||
Revert breaking change in **dropdown** ([1a998c4](http://github.com/angular-ui/bootstrap/commit/1a998c4))
|
||||
|
||||
# 0.11.1 (2014-09-26)
|
||||
<a name="0.11.1"></a>
|
||||
# [0.11.1](https://github.com/angular-ui/bootstrap/compare/0.11.0...0.11.1) (2014-09-26)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1225,7 +1321,8 @@ Revert breaking change in **dropdown** ([1a998c4](http://github.com/angular-ui/b
|
||||
- allow multiple line expression ([c7db0df4](http://github.com/angular-ui/bootstrap/commit/c7db0df4))
|
||||
- replace ng-if with ng-show in matches popup ([a0be450d](http://github.com/angular-ui/bootstrap/commit/a0be450d))
|
||||
|
||||
# 0.11.0 (2014-05-01)
|
||||
<a name="0.11.0"></a>
|
||||
# [0.11.0](https://github.com/angular-ui/bootstrap/compare/0.10.0...0.11.0) (2014-05-01)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1403,7 +1500,8 @@ Revert breaking change in **dropdown** ([1a998c4](http://github.com/angular-ui/b
|
||||
<tabset type="{{navtype}}" ...></tabset>
|
||||
```
|
||||
|
||||
# 0.10.0 (2014-01-13)
|
||||
<a name="0.10.0"></a>
|
||||
# [0.10.0](https://github.com/angular-ui/bootstrap/compare/0.9.0...0.10.0) (2014-01-13)
|
||||
|
||||
_This release adds AngularJS 1.2 support_
|
||||
|
||||
@@ -1424,7 +1522,8 @@ _This release adds AngularJS 1.2 support_
|
||||
- **tooltip:**
|
||||
- performance and scope fixes ([c0df3201](http://github.com/angular-ui/bootstrap/commit/c0df3201))
|
||||
|
||||
# 0.9.0 (2013-12-28)
|
||||
<a name="0.9.0"></a>
|
||||
# [0.9.0](https://github.com/angular-ui/bootstrap/compare/0.8.0...0.9.0) (2013-12-28)
|
||||
|
||||
_This release adds Bootstrap3 support_
|
||||
|
||||
@@ -1467,7 +1566,8 @@ _This release adds Bootstrap3 support_
|
||||
- **tooltip:**
|
||||
- re-position tooltip after draw ([a99b3608](http://github.com/angular-ui/bootstrap/commit/a99b3608))
|
||||
|
||||
# 0.8.0 (2013-12-28)
|
||||
<a name="0.8.0"></a>
|
||||
# [0.8.0](https://github.com/angular-ui/bootstrap/compare/0.7.0...0.8.0) (2013-12-28)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1534,7 +1634,8 @@ _This release adds Bootstrap3 support_
|
||||
<progress><bar ng-repeat="obj in objs" value="obj.var" type="{{obj.type}}"></bar></progress>
|
||||
```
|
||||
|
||||
# 0.7.0 (2013-11-22)
|
||||
<a name="0.7.0"></a>
|
||||
# [0.7.0](https://github.com/angular-ui/bootstrap/compare/0.6.0...0.7.0) (2013-11-22)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1582,7 +1683,8 @@ _This release adds Bootstrap3 support_
|
||||
- evaluate matches source against a correct scope ([fd21214d](http://github.com/angular-ui/bootstrap/commit/fd21214d))
|
||||
- support IE8 ([0e9f9980](http://github.com/angular-ui/bootstrap/commit/0e9f9980))
|
||||
|
||||
# 0.6.0 (2013-09-08)
|
||||
<a name="0.6.0"></a>
|
||||
# [0.6.0](https://github.com/angular-ui/bootstrap/compare/0.6.0...0.7.0) (2013-09-08)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1661,7 +1763,8 @@ Check the documentation for the `$modal` service to migrate from `$dialog`
|
||||
|
||||
The placment='mouse' is gone with no equivalent
|
||||
|
||||
# 0.5.0 (2013-08-04)
|
||||
<a name="0.5.0"></a>
|
||||
# [0.5.0](https://github.com/angular-ui/bootstrap/compare/0.4.0...0.5.0) (2013-08-04)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1744,7 +1847,8 @@ The placment='mouse' is gone with no equivalent
|
||||
<pagination first-text="{{var1}}" ...></pagination>
|
||||
```
|
||||
|
||||
# 0.4.0 (2013-06-24)
|
||||
<a name="0.4.0"></a>
|
||||
# [0.4.0](https://github.com/angular-ui/bootstrap/compare/0.3.0...0.4.0) (2013-06-24)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1862,8 +1966,8 @@ The placment='mouse' is gone with no equivalent
|
||||
</tabset>
|
||||
```
|
||||
|
||||
|
||||
# 0.3.0 (2013-04-30)
|
||||
<a name="0.3.0"></a>
|
||||
# [0.3.0](https://github.com/angular-ui/bootstrap/compare/0.2.0...0.3.0) (2013-04-30)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1904,7 +2008,8 @@ The placment='mouse' is gone with no equivalent
|
||||
- correctly higlight matches if query contains regexp-special chars ([467afcd6](https://github.com/angular-ui/bootstrap/commit/467afcd6))
|
||||
- fix matches pop-up positioning issues ([74beecdb](https://github.com/angular-ui/bootstrap/commit/74beecdb))
|
||||
|
||||
# 0.2.0 (2013-03-03)
|
||||
<a name="0.2.0"></a>
|
||||
# [0.2.0](https://github.com/angular-ui/bootstrap/compare/0.1.0...0.2.0) (2013-03-03)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1938,6 +2043,7 @@ The placment='mouse' is gone with no equivalent
|
||||
- **typeahead:**
|
||||
- update inputs value on mapping where label is not derived from the model ([a5f64de](https://github.com/angular-ui/bootstrap/commit/a5f64de))
|
||||
|
||||
<a name="0.1.0"></a>
|
||||
# 0.1.0 (2013-02-02)
|
||||
|
||||
_Very first, initial release_.
|
||||
|
||||
@@ -131,7 +131,7 @@ The other modules, such as `accordion` in the example below, do not have CSS res
|
||||
import accordion from 'angular-ui-bootstrap/src/accordion';
|
||||
import typeahead from 'angular-ui-bootstrap/src/typeahead/index-nocss.js';
|
||||
|
||||
angular.module('myModule', [accordion, datepicker]);
|
||||
angular.module('myModule', [accordion, typeahead]);
|
||||
```
|
||||
|
||||
# Versioning
|
||||
|
||||
@@ -73,7 +73,7 @@ section {
|
||||
|
||||
}
|
||||
|
||||
.navbar .collapse {
|
||||
.navbar-fixed-top .collapse {
|
||||
border-top: 1px solid #e7e7e7;
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 8.2 KiB |
+4
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"author": "https://github.com/angular-ui/bootstrap/graphs/contributors",
|
||||
"name": "angular-ui-bootstrap",
|
||||
"version": "2.1.0",
|
||||
"version": "2.3.2",
|
||||
"homepage": "http://angular-ui.github.io/bootstrap/",
|
||||
"dependencies": {},
|
||||
"directories": {
|
||||
@@ -15,6 +15,7 @@
|
||||
],
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"demo": "grunt after-test && static dist -a 0.0.0.0 -H '{\"Cache-Control\": \"no-cache, must-revalidate\"}'",
|
||||
"test": "grunt"
|
||||
},
|
||||
"repository": {
|
||||
@@ -26,6 +27,7 @@
|
||||
"angular-mocks": "1.5.8",
|
||||
"angular-sanitize": "1.5.8",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-cli": "^1.2.0",
|
||||
"grunt-contrib-concat": "^1.0.0",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-uglify": "^1.0.1",
|
||||
@@ -44,6 +46,7 @@
|
||||
"load-grunt-tasks": "^3.3.0",
|
||||
"lodash": "^4.1.0",
|
||||
"marked": "^0.3.5",
|
||||
"node-static": "^0.7.8",
|
||||
"semver": "^5.0.1",
|
||||
"shelljs": "^0.6.0"
|
||||
},
|
||||
|
||||
@@ -18,12 +18,12 @@ angular.module('ui.bootstrap.collapse', [])
|
||||
horizontal = !!('horizontal' in attrs);
|
||||
if (horizontal) {
|
||||
css = {
|
||||
width: 'auto'
|
||||
width: ''
|
||||
};
|
||||
cssTo = {width: '0'};
|
||||
} else {
|
||||
css = {
|
||||
height: 'auto'
|
||||
height: ''
|
||||
};
|
||||
cssTo = {height: '0'};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,31 @@
|
||||
<style>
|
||||
.horizontal-collapse {
|
||||
height: 70px;
|
||||
}
|
||||
.navbar-collapse.in {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
</style>
|
||||
<div ng-controller="CollapseDemoCtrl">
|
||||
<p>Resize window to less than 768 pixels to display mobile menu toggle button.</p>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" ng-click="isNavCollapsed = !isNavCollapsed">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">A menu</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" uib-collapse="isNavCollapsed">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="#">Link 1</a></li>
|
||||
<li><a href="#">Link 2</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<hr>
|
||||
<button type="button" class="btn btn-default" ng-click="isCollapsed = !isCollapsed">Toggle collapse Vertically</button>
|
||||
<hr>
|
||||
<div uib-collapse="isCollapsed">
|
||||
@@ -7,7 +34,7 @@
|
||||
|
||||
<button type="button" class="btn btn-default" ng-click="isCollapsedHorizontal = !isCollapsedHorizontal">Toggle collapse Horizontally</button>
|
||||
<hr>
|
||||
<div uib-collapse="isCollapsedHorizontal" horizontal>
|
||||
<div class="horizontal-collapse" uib-collapse="isCollapsedHorizontal" horizontal>
|
||||
<div class="well well-lg">Some content</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
angular.module('ui.bootstrap.demo').controller('CollapseDemoCtrl', function ($scope) {
|
||||
$scope.isNavCollapsed = true;
|
||||
$scope.isCollapsed = false;
|
||||
$scope.isCollapsedHorizontal = false;
|
||||
});
|
||||
|
||||
@@ -27,8 +27,11 @@
|
||||
<i class="glyphicon glyphicon-eye-open"></i>
|
||||
_(Default: `false`)_ -
|
||||
Whether the element should be collapsed or not.
|
||||
|
||||
|
||||
* `horizontal`
|
||||
<small class="badge">$</small> -
|
||||
An optional attribute that permit to collapse horizontally.
|
||||
|
||||
### Known Issues
|
||||
|
||||
When using the `horizontal` attribute with this directive, keep in mind that due to how CSS can reflow as the collapse element goes from 0px to its desired end width, this cause result in issues with a changing height. This can cause animations to not appear to run. The best way around this is to set a fixed height via CSS on the horizontal collapse element so that this situation does not occur, and so the animation can run as expected.
|
||||
|
||||
@@ -230,6 +230,15 @@ angular.module('ui.bootstrap.dateparser', [])
|
||||
formatter: function(date) { return dateFilter(date, 'G'); }
|
||||
}
|
||||
];
|
||||
|
||||
if (angular.version.major >= 1 && angular.version.minor > 4) {
|
||||
formatCodeToRegex.push({
|
||||
key: 'LLLL',
|
||||
regex: $locale.DATETIME_FORMATS.STANDALONEMONTH.join('|'),
|
||||
apply: function(value) { this.month = $locale.DATETIME_FORMATS.STANDALONEMONTH.indexOf(value); },
|
||||
formatter: function(date) { return dateFilter(date, 'LLLL'); }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.init();
|
||||
|
||||
@@ -58,6 +58,9 @@ Certain format codes support i18n. Check this [guide](https://docs.angularjs.org
|
||||
_(Example: `3` or `03`)_ -
|
||||
Parses a numeric month, but allowing an optional leading zero
|
||||
|
||||
* `LLLL`
|
||||
_(Example: `February`, i18n support)_ - Stand-alone month in year (January-December). Requires Angular version 1.5.1 or higher.
|
||||
|
||||
* `dd`
|
||||
_(Example: `05`, Leading 0)_ -
|
||||
Parses a numeric day.
|
||||
|
||||
@@ -84,6 +84,16 @@ describe('date parser', function() {
|
||||
expectFilter(new Date(2011, 4, 2, 0), 'dd-M!-yy', '02-05-11');
|
||||
expectFilter(oldDate, 'yyyy/M!/dd', '0001/03/06');
|
||||
});
|
||||
|
||||
it('should work correctly for `LLLL`', function() {
|
||||
expectFilter(new Date(2013, 7, 24, 0), 'LLLL/dd/yyyy', 'August/24/2013');
|
||||
expectFilter(new Date(2004, 10, 7, 0), 'dd.LLLL.yy', '07.November.04');
|
||||
expectFilter(new Date(2011, 4, 18, 0), 'dd-LLLL-yy', '18-May-11');
|
||||
expectFilter(new Date(1980, 1, 5, 0), 'LLLL/dd/yyyy', 'February/05/1980');
|
||||
expectFilter(new Date(1955, 2, 5, 0), 'yyyy/LLLL/dd', '1955/March/05');
|
||||
expectFilter(new Date(2011, 5, 2, 0), 'dd-LLLL-yy', '02-June-11');
|
||||
expectFilter(oldDate, 'yyyy/LLLL/dd', '0001/March/06');
|
||||
});
|
||||
|
||||
it('should work correctly for `d`', function() {
|
||||
expectFilter(new Date(2013, 10, 17, 0), 'd.MMMM.yy', '17.November.13');
|
||||
|
||||
@@ -126,7 +126,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
case 'minMode':
|
||||
if ($scope.datepickerOptions[key]) {
|
||||
$scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) {
|
||||
self[key] = $scope[key] = angular.isDefined(value) ? value : datepickerOptions[key];
|
||||
self[key] = $scope[key] = angular.isDefined(value) ? value : $scope.datepickerOptions[key];
|
||||
if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) ||
|
||||
key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) {
|
||||
$scope.datepickerMode = self[key];
|
||||
|
||||
@@ -333,7 +333,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
if (angular.isString(viewValue)) {
|
||||
var date = parseDateString(viewValue);
|
||||
if (!isNaN(date)) {
|
||||
return dateParser.fromTimezone(date, ngModelOptions.timezone);
|
||||
return dateParser.toTimezone(date, ngModelOptions.timezone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -397,7 +397,7 @@ describe('datepicker popup', function() {
|
||||
it('stops the ESC key from propagating if the dropdown is open, but not when closed', function() {
|
||||
var documentKey = -1;
|
||||
var getKey = function(evt) { documentKey = evt.which; };
|
||||
$document.bind('keydown', getKey);
|
||||
$document.on('keydown', getKey);
|
||||
|
||||
triggerKeyDown(inputEl, 'esc');
|
||||
expect(documentKey).toBe(-1);
|
||||
@@ -405,7 +405,7 @@ describe('datepicker popup', function() {
|
||||
triggerKeyDown(inputEl, 'esc');
|
||||
expect(documentKey).toBe(27);
|
||||
|
||||
$document.unbind('keydown', getKey);
|
||||
$document.off('keydown', getKey);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+82
-12
@@ -1,14 +1,33 @@
|
||||
angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.multiMap', 'ui.bootstrap.position'])
|
||||
|
||||
.constant('uibDropdownConfig', {
|
||||
appendToOpenClass: 'uib-dropdown-open',
|
||||
openClass: 'open'
|
||||
})
|
||||
|
||||
.service('uibDropdownService', ['$document', '$rootScope', function($document, $rootScope) {
|
||||
.service('uibDropdownService', ['$document', '$rootScope', '$$multiMap', function($document, $rootScope, $$multiMap) {
|
||||
var openScope = null;
|
||||
var openedContainers = $$multiMap.createNew();
|
||||
|
||||
this.open = function(dropdownScope, element) {
|
||||
this.isOnlyOpen = function(dropdownScope, appendTo) {
|
||||
var openedDropdowns = openedContainers.get(appendTo);
|
||||
if (openedDropdowns) {
|
||||
var openDropdown = openedDropdowns.reduce(function(toClose, dropdown) {
|
||||
if (dropdown.scope === dropdownScope) {
|
||||
return dropdown;
|
||||
}
|
||||
|
||||
return toClose;
|
||||
}, {});
|
||||
if (openDropdown) {
|
||||
return openedDropdowns.length === 1;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
this.open = function(dropdownScope, element, appendTo) {
|
||||
if (!openScope) {
|
||||
$document.on('click', closeDropdown);
|
||||
}
|
||||
@@ -18,13 +37,51 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
}
|
||||
|
||||
openScope = dropdownScope;
|
||||
|
||||
if (!appendTo) {
|
||||
return;
|
||||
}
|
||||
|
||||
var openedDropdowns = openedContainers.get(appendTo);
|
||||
if (openedDropdowns) {
|
||||
var openedScopes = openedDropdowns.map(function(dropdown) {
|
||||
return dropdown.scope;
|
||||
});
|
||||
if (openedScopes.indexOf(dropdownScope) === -1) {
|
||||
openedContainers.put(appendTo, {
|
||||
scope: dropdownScope
|
||||
});
|
||||
}
|
||||
} else {
|
||||
openedContainers.put(appendTo, {
|
||||
scope: dropdownScope
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.close = function(dropdownScope, element) {
|
||||
this.close = function(dropdownScope, element, appendTo) {
|
||||
if (openScope === dropdownScope) {
|
||||
openScope = null;
|
||||
$document.off('click', closeDropdown);
|
||||
$document.off('keydown', this.keybindFilter);
|
||||
openScope = null;
|
||||
}
|
||||
|
||||
if (!appendTo) {
|
||||
return;
|
||||
}
|
||||
|
||||
var openedDropdowns = openedContainers.get(appendTo);
|
||||
if (openedDropdowns) {
|
||||
var dropdownToClose = openedDropdowns.reduce(function(toClose, dropdown) {
|
||||
if (dropdown.scope === dropdownScope) {
|
||||
return dropdown;
|
||||
}
|
||||
|
||||
return toClose;
|
||||
}, {});
|
||||
if (dropdownToClose) {
|
||||
openedContainers.remove(appendTo, dropdownToClose);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,8 +105,8 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
return;
|
||||
}
|
||||
|
||||
openScope.isOpen = false;
|
||||
openScope.focusToggleElement();
|
||||
openScope.isOpen = false;
|
||||
|
||||
if (!$rootScope.$$phase) {
|
||||
openScope.$apply();
|
||||
@@ -57,6 +114,11 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
};
|
||||
|
||||
this.keybindFilter = function(evt) {
|
||||
if (!openScope) {
|
||||
// see this.close as ESC could have been pressed which kills the scope so we can not proceed
|
||||
return;
|
||||
}
|
||||
|
||||
var dropdownElement = openScope.getDropdownElement();
|
||||
var toggleElement = openScope.getToggleElement();
|
||||
var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target);
|
||||
@@ -239,10 +301,18 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
}
|
||||
|
||||
var openContainer = appendTo ? appendTo : $element;
|
||||
var hasOpenClass = openContainer.hasClass(appendTo ? appendToOpenClass : openClass);
|
||||
var dropdownOpenClass = appendTo ? appendToOpenClass : openClass;
|
||||
var hasOpenClass = openContainer.hasClass(dropdownOpenClass);
|
||||
var isOnlyOpen = uibDropdownService.isOnlyOpen($scope, appendTo);
|
||||
|
||||
if (hasOpenClass === !isOpen) {
|
||||
$animate[isOpen ? 'addClass' : 'removeClass'](openContainer, appendTo ? appendToOpenClass : openClass).then(function() {
|
||||
var toggleClass;
|
||||
if (appendTo) {
|
||||
toggleClass = !isOnlyOpen ? 'addClass' : 'removeClass';
|
||||
} else {
|
||||
toggleClass = isOpen ? 'addClass' : 'removeClass';
|
||||
}
|
||||
$animate[toggleClass](openContainer, dropdownOpenClass).then(function() {
|
||||
if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
|
||||
toggleInvoker($scope, { open: !!isOpen });
|
||||
}
|
||||
@@ -265,9 +335,9 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
}
|
||||
|
||||
scope.focusToggleElement();
|
||||
uibDropdownService.open(scope, $element);
|
||||
uibDropdownService.open(scope, $element, appendTo);
|
||||
} else {
|
||||
uibDropdownService.close(scope, $element);
|
||||
uibDropdownService.close(scope, $element, appendTo);
|
||||
if (self.dropdownMenuTemplateUrl) {
|
||||
if (templateScope) {
|
||||
templateScope.$destroy();
|
||||
@@ -340,7 +410,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
}
|
||||
};
|
||||
|
||||
element.bind('click', toggleDropdown);
|
||||
element.on('click', toggleDropdown);
|
||||
|
||||
// WAI-ARIA
|
||||
element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
|
||||
@@ -349,7 +419,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
});
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
element.unbind('click', toggleDropdown);
|
||||
element.off('click', toggleDropdown);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
require('../multiMap');
|
||||
require('../position/index-nocss.js');
|
||||
require('./dropdown');
|
||||
|
||||
|
||||
@@ -99,11 +99,11 @@ describe('uib-dropdown', function() {
|
||||
expect(elm1).not.toHaveClass(dropdownConfig.openClass);
|
||||
expect(elm2).not.toHaveClass(dropdownConfig.openClass);
|
||||
|
||||
clickDropdownToggle( elm1 );
|
||||
clickDropdownToggle(elm1);
|
||||
expect(elm1).toHaveClass(dropdownConfig.openClass);
|
||||
expect(elm2).not.toHaveClass(dropdownConfig.openClass);
|
||||
|
||||
clickDropdownToggle( elm2 );
|
||||
clickDropdownToggle(elm2);
|
||||
expect(elm1).not.toHaveClass(dropdownConfig.openClass);
|
||||
expect(elm2).toHaveClass(dropdownConfig.openClass);
|
||||
});
|
||||
@@ -303,6 +303,37 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('using dropdown-append-to with two dropdowns', function() {
|
||||
function dropdown() {
|
||||
return $compile('<div><div class="dropdown1" uib-dropdown dropdown-append-to="appendTo" on-toggle="log(1, open)"><a href uib-dropdown-toggle></a><ul class="dropdown-menu" uib-dropdown-menu id="dropdown-menu"><li><a href>Hello On Container</a></li></ul></div><div class="dropdown2" uib-dropdown dropdown-append-to="appendTo" on-toggle="log(2, open)"><a href uib-dropdown-toggle></a><ul class="dropdown-menu" uib-dropdown-menu id="dropdown-menu"><li><a href>Hello On Container</a></li></ul></div></div>')($rootScope);
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
$document.find('body').append(angular.element('<div id="dropdown-container"></div>'));
|
||||
|
||||
$rootScope.appendTo = $document.find('#dropdown-container');
|
||||
$rootScope.log = jasmine.createSpy('log');
|
||||
|
||||
element = dropdown();
|
||||
$document.find('body').append(element);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// Cleanup the extra elements we appended
|
||||
$document.find('#dropdown-container').remove();
|
||||
});
|
||||
|
||||
it('should keep the class when toggling from one dropdown to another with the same container', function() {
|
||||
var container = $document.find('#dropdown-container');
|
||||
|
||||
expect(container).not.toHaveClass('uib-dropdown-open');
|
||||
element.find('.dropdown1 [uib-dropdown-toggle]').click();
|
||||
expect(container).toHaveClass('uib-dropdown-open');
|
||||
element.find('.dropdown2 [uib-dropdown-toggle]').click();
|
||||
expect(container).toHaveClass('uib-dropdown-open');
|
||||
});
|
||||
});
|
||||
|
||||
describe('using is-open', function() {
|
||||
describe('with uib-dropdown-toggle', function() {
|
||||
beforeEach(function() {
|
||||
|
||||
+30
-11
@@ -1,25 +1,44 @@
|
||||
<div ng-controller="ModalDemoCtrl">
|
||||
<div ng-controller="ModalDemoCtrl as $ctrl" class="modal-demo">
|
||||
<script type="text/ng-template" id="myModalContent.html">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" id="modal-title">I'm a modal!</h3>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-body">
|
||||
<ul>
|
||||
<li ng-repeat="item in items">
|
||||
<a href="#" ng-click="$event.preventDefault(); selected.item = item">{{ item }}</a>
|
||||
<li ng-repeat="item in $ctrl.items">
|
||||
<a href="#" ng-click="$event.preventDefault(); $ctrl.selected.item = item">{{ item }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
Selected: <b>{{ selected.item }}</b>
|
||||
Selected: <b>{{ $ctrl.selected.item }}</b>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
|
||||
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
|
||||
<button class="btn btn-primary" type="button" ng-click="$ctrl.ok()">OK</button>
|
||||
<button class="btn btn-warning" type="button" ng-click="$ctrl.cancel()">Cancel</button>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/ng-template" id="stackedModal.html">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" id="modal-title-{{name}}">The {{name}} modal!</h3>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-body-{{name}}">
|
||||
Having multiple modals open at once is probably bad UX but it's technically possible.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<button type="button" class="btn btn-default" ng-click="open()">Open me!</button>
|
||||
<button type="button" class="btn btn-default" ng-click="open('lg')">Large modal</button>
|
||||
<button type="button" class="btn btn-default" ng-click="open('sm')">Small modal</button>
|
||||
<button type="button" class="btn btn-default" ng-click="toggleAnimation()">Toggle Animation ({{ animationsEnabled }})</button>
|
||||
<div ng-show="selected">Selection from a modal: {{ selected }}</div>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.open()">Open me!</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.open('lg')">Large modal</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.open('sm')">Small modal</button>
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
ng-click="$ctrl.open('sm', '.modal-parent')">
|
||||
Modal appended to a custom parent
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.toggleAnimation()">Toggle Animation ({{ $ctrl.animationsEnabled }})</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.openComponentModal()">Open a component modal!</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.openMultipleModals()">
|
||||
Open multiple modals at once
|
||||
</button>
|
||||
<div ng-show="$ctrl.selected">Selection from a modal: {{ $ctrl.selected }}</div>
|
||||
<div class="modal-parent">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+92
-19
@@ -1,53 +1,126 @@
|
||||
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $uibModal, $log) {
|
||||
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($uibModal, $log, $document) {
|
||||
var $ctrl = this;
|
||||
$ctrl.items = ['item1', 'item2', 'item3'];
|
||||
|
||||
$scope.items = ['item1', 'item2', 'item3'];
|
||||
|
||||
$scope.animationsEnabled = true;
|
||||
|
||||
$scope.open = function (size) {
|
||||
$ctrl.animationsEnabled = true;
|
||||
|
||||
$ctrl.open = function (size, parentSelector) {
|
||||
var parentElem = parentSelector ?
|
||||
angular.element($document[0].querySelector('.modal-demo ' + parentSelector)) : undefined;
|
||||
var modalInstance = $uibModal.open({
|
||||
animation: $scope.animationsEnabled,
|
||||
animation: $ctrl.animationsEnabled,
|
||||
ariaLabelledBy: 'modal-title',
|
||||
ariaDescribedBy: 'modal-body',
|
||||
templateUrl: 'myModalContent.html',
|
||||
controller: 'ModalInstanceCtrl',
|
||||
controllerAs: '$ctrl',
|
||||
size: size,
|
||||
appendTo: parentElem,
|
||||
resolve: {
|
||||
items: function () {
|
||||
return $scope.items;
|
||||
return $ctrl.items;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
modalInstance.result.then(function (selectedItem) {
|
||||
$scope.selected = selectedItem;
|
||||
$ctrl.selected = selectedItem;
|
||||
}, function () {
|
||||
$log.info('Modal dismissed at: ' + new Date());
|
||||
});
|
||||
};
|
||||
|
||||
$scope.toggleAnimation = function () {
|
||||
$scope.animationsEnabled = !$scope.animationsEnabled;
|
||||
$ctrl.openComponentModal = function () {
|
||||
var modalInstance = $uibModal.open({
|
||||
animation: $ctrl.animationsEnabled,
|
||||
component: 'modalComponent',
|
||||
resolve: {
|
||||
items: function () {
|
||||
return $ctrl.items;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
modalInstance.result.then(function (selectedItem) {
|
||||
$ctrl.selected = selectedItem;
|
||||
}, function () {
|
||||
$log.info('modal-component dismissed at: ' + new Date());
|
||||
});
|
||||
};
|
||||
|
||||
$ctrl.openMultipleModals = function () {
|
||||
$uibModal.open({
|
||||
animation: $ctrl.animationsEnabled,
|
||||
ariaLabelledBy: 'modal-title-bottom',
|
||||
ariaDescribedBy: 'modal-body-bottom',
|
||||
templateUrl: 'stackedModal.html',
|
||||
size: 'sm',
|
||||
controller: function($scope) {
|
||||
$scope.name = 'bottom';
|
||||
}
|
||||
});
|
||||
|
||||
$uibModal.open({
|
||||
animation: $ctrl.animationsEnabled,
|
||||
ariaLabelledBy: 'modal-title-top',
|
||||
ariaDescribedBy: 'modal-body-top',
|
||||
templateUrl: 'stackedModal.html',
|
||||
size: 'sm',
|
||||
controller: function($scope) {
|
||||
$scope.name = 'top';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$ctrl.toggleAnimation = function () {
|
||||
$ctrl.animationsEnabled = !$ctrl.animationsEnabled;
|
||||
};
|
||||
});
|
||||
|
||||
// Please note that $uibModalInstance represents a modal window (instance) dependency.
|
||||
// It is not the same as the $uibModal service used above.
|
||||
|
||||
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, items) {
|
||||
|
||||
$scope.items = items;
|
||||
$scope.selected = {
|
||||
item: $scope.items[0]
|
||||
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($uibModalInstance, items) {
|
||||
var $ctrl = this;
|
||||
$ctrl.items = items;
|
||||
$ctrl.selected = {
|
||||
item: $ctrl.items[0]
|
||||
};
|
||||
|
||||
$scope.ok = function () {
|
||||
$uibModalInstance.close($scope.selected.item);
|
||||
$ctrl.ok = function () {
|
||||
$uibModalInstance.close($ctrl.selected.item);
|
||||
};
|
||||
|
||||
$scope.cancel = function () {
|
||||
$ctrl.cancel = function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
};
|
||||
});
|
||||
|
||||
// Please note that the close and dismiss bindings are from $uibModalInstance.
|
||||
|
||||
angular.module('ui.bootstrap.demo').component('modalComponent', {
|
||||
templateUrl: 'myModalContent.html',
|
||||
bindings: {
|
||||
resolve: '<',
|
||||
close: '&',
|
||||
dismiss: '&'
|
||||
},
|
||||
controller: function () {
|
||||
var $ctrl = this;
|
||||
|
||||
$ctrl.$onInit = function () {
|
||||
$ctrl.items = $ctrl.resolve.items;
|
||||
$ctrl.selected = {
|
||||
item: $ctrl.items[0]
|
||||
};
|
||||
};
|
||||
|
||||
$ctrl.ok = function () {
|
||||
$ctrl.close({$value: $ctrl.selected.item});
|
||||
};
|
||||
|
||||
$ctrl.cancel = function () {
|
||||
$ctrl.dismiss({$value: 'cancel'});
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
`$uibModal` is a service to create modal windows.
|
||||
Creating modals is straightforward: create a template, a controller and reference them when using `$uibModal`.
|
||||
Creating modals is straightforward: create a template and controller, and reference them when using `$uibModal`.
|
||||
|
||||
The `$uibModal` service has only one method: `open(options)`.
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
require('../multiMap');
|
||||
require('../position/index-nocss.js');
|
||||
require('../stackedMap');
|
||||
require('../../template/modal/window.html.js');
|
||||
|
||||
+56
-62
@@ -1,59 +1,4 @@
|
||||
angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.position'])
|
||||
/**
|
||||
* A helper, internal data structure that stores all references attached to key
|
||||
*/
|
||||
.factory('$$multiMap', function() {
|
||||
return {
|
||||
createNew: function() {
|
||||
var map = {};
|
||||
|
||||
return {
|
||||
entries: function() {
|
||||
return Object.keys(map).map(function(key) {
|
||||
return {
|
||||
key: key,
|
||||
value: map[key]
|
||||
};
|
||||
});
|
||||
},
|
||||
get: function(key) {
|
||||
return map[key];
|
||||
},
|
||||
hasKey: function(key) {
|
||||
return !!map[key];
|
||||
},
|
||||
keys: function() {
|
||||
return Object.keys(map);
|
||||
},
|
||||
put: function(key, value) {
|
||||
if (!map[key]) {
|
||||
map[key] = [];
|
||||
}
|
||||
|
||||
map[key].push(value);
|
||||
},
|
||||
remove: function(key, value) {
|
||||
var values = map[key];
|
||||
|
||||
if (!values) {
|
||||
return;
|
||||
}
|
||||
|
||||
var idx = values.indexOf(value);
|
||||
|
||||
if (idx !== -1) {
|
||||
values.splice(idx, 1);
|
||||
}
|
||||
|
||||
if (!values.length) {
|
||||
delete map[key];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
angular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.stackedMap', 'ui.bootstrap.position'])
|
||||
/**
|
||||
* Pluggable resolve mechanism for the modal resolve resolution
|
||||
* Supports UI Router's $resolve service
|
||||
@@ -163,7 +108,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
// {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
|
||||
scope.$isRendered = true;
|
||||
|
||||
// Deferred object that will be resolved when this modal is render.
|
||||
// Deferred object that will be resolved when this modal is rendered.
|
||||
var modalRenderDeferObj = $q.defer();
|
||||
// Resolve render promise post-digest
|
||||
scope.$$postDigest(function() {
|
||||
@@ -196,7 +141,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
|
||||
/**
|
||||
* If something within the freshly-opened modal already has focus (perhaps via a
|
||||
* directive that causes focus). then no need to try and focus anything.
|
||||
* directive that causes focus) then there's no need to try to focus anything.
|
||||
*/
|
||||
if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
|
||||
var inputWithAutofocus = element[0].querySelector('[autofocus]');
|
||||
@@ -254,6 +199,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
};
|
||||
var topModalIndex = 0;
|
||||
var previousTopOpenedModal = null;
|
||||
var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count';
|
||||
|
||||
//Modal focus behavior
|
||||
var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' +
|
||||
@@ -512,10 +458,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
content.attr({
|
||||
resolve: '$resolve',
|
||||
'modal-instance': '$uibModalInstance',
|
||||
close: 'close($value)',
|
||||
dismiss: 'dismiss($value)'
|
||||
close: '$close($value)',
|
||||
dismiss: '$dismiss($value)'
|
||||
});
|
||||
content = $compile(content)(modal.scope);
|
||||
} else {
|
||||
content = modal.content;
|
||||
}
|
||||
@@ -537,7 +482,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
'tabindex': -1,
|
||||
'uib-modal-animation-class': 'fade',
|
||||
'modal-in-class': 'in'
|
||||
}).html(content);
|
||||
}).append(content);
|
||||
if (modal.windowClass) {
|
||||
angularDomEl.addClass(modal.windowClass);
|
||||
}
|
||||
@@ -556,25 +501,74 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
|
||||
openedWindows.top().value.modalDomEl = angularDomEl;
|
||||
openedWindows.top().value.modalOpener = modalOpener;
|
||||
|
||||
applyAriaHidden(angularDomEl);
|
||||
|
||||
function applyAriaHidden(el) {
|
||||
if (!el || el[0].tagName === 'BODY') {
|
||||
return;
|
||||
}
|
||||
|
||||
getSiblings(el).forEach(function(sibling) {
|
||||
var elemIsAlreadyHidden = sibling.getAttribute('aria-hidden') === 'true',
|
||||
ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10);
|
||||
|
||||
if (!ariaHiddenCount) {
|
||||
ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0;
|
||||
}
|
||||
|
||||
sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1);
|
||||
sibling.setAttribute('aria-hidden', 'true');
|
||||
});
|
||||
|
||||
return applyAriaHidden(el.parent());
|
||||
|
||||
function getSiblings(el) {
|
||||
var children = el.parent() ? el.parent().children() : [];
|
||||
|
||||
return Array.prototype.filter.call(children, function(child) {
|
||||
return child !== el[0];
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function broadcastClosing(modalWindow, resultOrReason, closing) {
|
||||
return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
|
||||
}
|
||||
|
||||
function unhideBackgroundElements() {
|
||||
Array.prototype.forEach.call(
|
||||
document.querySelectorAll('[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']'),
|
||||
function(hiddenEl) {
|
||||
var ariaHiddenCount = parseInt(hiddenEl.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10),
|
||||
newHiddenCount = ariaHiddenCount - 1;
|
||||
hiddenEl.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, newHiddenCount);
|
||||
|
||||
if (!newHiddenCount) {
|
||||
hiddenEl.removeAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME);
|
||||
hiddenEl.removeAttribute('aria-hidden');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$modalStack.close = function(modalInstance, result) {
|
||||
var modalWindow = openedWindows.get(modalInstance);
|
||||
unhideBackgroundElements();
|
||||
if (modalWindow && broadcastClosing(modalWindow, result, true)) {
|
||||
modalWindow.value.modalScope.$$uibDestructionScheduled = true;
|
||||
modalWindow.value.deferred.resolve(result);
|
||||
removeModalWindow(modalInstance, modalWindow.value.modalOpener);
|
||||
return true;
|
||||
}
|
||||
|
||||
return !modalWindow;
|
||||
};
|
||||
|
||||
$modalStack.dismiss = function(modalInstance, reason) {
|
||||
var modalWindow = openedWindows.get(modalInstance);
|
||||
unhideBackgroundElements();
|
||||
if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
|
||||
modalWindow.value.modalScope.$$uibDestructionScheduled = true;
|
||||
modalWindow.value.deferred.reject(reason);
|
||||
|
||||
@@ -161,6 +161,7 @@ describe('$uibModal', function() {
|
||||
toBeResolvedWith: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(promise, expected) {
|
||||
var called = false;
|
||||
promise.then(function(result) {
|
||||
expect(result).toEqual(expected);
|
||||
|
||||
@@ -169,10 +170,18 @@ describe('$uibModal', function() {
|
||||
} else {
|
||||
result.message = 'Expected "' + angular.mock.dump(result) + '" to be resolved with "' + expected + '".';
|
||||
}
|
||||
}, function(result) {
|
||||
fail('Expected "' + angular.mock.dump(result) + '" to be resolved with "' + expected + '".');
|
||||
})['finally'](function() {
|
||||
called = true;
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
if (!called) {
|
||||
fail('Expected "' + angular.mock.dump(result) + '" to be resolved with "' + expected + '".');
|
||||
}
|
||||
|
||||
return {pass: true};
|
||||
}
|
||||
};
|
||||
@@ -181,9 +190,10 @@ describe('$uibModal', function() {
|
||||
return {
|
||||
compare: function(promise, expected) {
|
||||
var result = {};
|
||||
var called = false;
|
||||
|
||||
promise.then(function() {
|
||||
|
||||
promise.then(function(result) {
|
||||
fail('Expected "' + angular.mock.dump(result) + '" to be rejected with "' + expected + '".');
|
||||
}, function(result) {
|
||||
expect(result).toEqual(expected);
|
||||
|
||||
@@ -192,10 +202,16 @@ describe('$uibModal', function() {
|
||||
} else {
|
||||
result.message = 'Expected "' + angular.mock.dump(result) + '" to be rejected with "' + expected + '".';
|
||||
}
|
||||
})['finally'](function() {
|
||||
called = true;
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
if (!called) {
|
||||
fail('Expected "' + angular.mock.dump(result) + '" to be rejected with "' + expected + '".');
|
||||
}
|
||||
|
||||
return {pass: true};
|
||||
}
|
||||
};
|
||||
@@ -510,7 +526,7 @@ describe('$uibModal', function() {
|
||||
|
||||
var modal = open({template: '<div>Content<button>inside modal</button></div>'});
|
||||
$rootScope.$digest();
|
||||
expect(document.activeElement.tagName).toBe('DIV');
|
||||
expect(document.activeElement.className.split(' ')).toContain('modal');
|
||||
expect($document).toHaveModalsOpen(1);
|
||||
|
||||
triggerKeyDown($document, 27);
|
||||
@@ -640,7 +656,7 @@ describe('$uibModal', function() {
|
||||
it('should not focus on the element that has autofocus attribute when the modal is opened and something in the modal already has focus and the animations have finished', function() {
|
||||
function openAndCloseModalWithAutofocusElement() {
|
||||
|
||||
var modal = open({template: '<div><input type="text" id="auto-focus-element" autofocus><input type="text" id="pre-focus-element" focus-me></div>'});
|
||||
var modal = open({template: '<div><input type="text" id="pre-focus-element" focus-me><input type="text" id="auto-focus-element" autofocus></div>'});
|
||||
$rootScope.$digest();
|
||||
expect(angular.element('#auto-focus-element')).not.toHaveFocus();
|
||||
expect(angular.element('#pre-focus-element')).toHaveFocus();
|
||||
@@ -682,7 +698,7 @@ describe('$uibModal', function() {
|
||||
$rootScope.$digest();
|
||||
$animate.flush();
|
||||
|
||||
expect(document.activeElement.tagName).toBe('DIV');
|
||||
expect(document.activeElement.className.split(' ')).toContain('modal');
|
||||
|
||||
close(modal, 'closed ok');
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
require('./multiMap.js');
|
||||
@@ -0,0 +1,55 @@
|
||||
angular.module('ui.bootstrap.multiMap', [])
|
||||
/**
|
||||
* A helper, internal data structure that stores all references attached to key
|
||||
*/
|
||||
.factory('$$multiMap', function() {
|
||||
return {
|
||||
createNew: function() {
|
||||
var map = {};
|
||||
|
||||
return {
|
||||
entries: function() {
|
||||
return Object.keys(map).map(function(key) {
|
||||
return {
|
||||
key: key,
|
||||
value: map[key]
|
||||
};
|
||||
});
|
||||
},
|
||||
get: function(key) {
|
||||
return map[key];
|
||||
},
|
||||
hasKey: function(key) {
|
||||
return !!map[key];
|
||||
},
|
||||
keys: function() {
|
||||
return Object.keys(map);
|
||||
},
|
||||
put: function(key, value) {
|
||||
if (!map[key]) {
|
||||
map[key] = [];
|
||||
}
|
||||
|
||||
map[key].push(value);
|
||||
},
|
||||
remove: function(key, value) {
|
||||
var values = map[key];
|
||||
|
||||
if (!values) {
|
||||
return;
|
||||
}
|
||||
|
||||
var idx = values.indexOf(value);
|
||||
|
||||
if (idx !== -1) {
|
||||
values.splice(idx, 1);
|
||||
}
|
||||
|
||||
if (!values.length) {
|
||||
delete map[key];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
describe('multi map', function() {
|
||||
var multiMap;
|
||||
|
||||
beforeEach(module('ui.bootstrap.modal'));
|
||||
beforeEach(module('ui.bootstrap.multiMap'));
|
||||
beforeEach(inject(function($$multiMap) {
|
||||
multiMap = $$multiMap.createNew();
|
||||
}));
|
||||
@@ -34,6 +34,9 @@ All these settings are available for the three types of popovers.
|
||||
_(Default: `false`, Config: `appendToBody`)_ -
|
||||
Should the popover be appended to '$body' instead of the parent element?
|
||||
|
||||
* `popover-class` -
|
||||
Custom class to be applied to the popover.
|
||||
|
||||
* `popover-enable`
|
||||
<small class="badge">$</small>
|
||||
_(Default: `true`)_ -
|
||||
|
||||
@@ -130,7 +130,7 @@ angular.module('ui.bootstrap.position', [])
|
||||
var paddingRight = this.parseStyle(elemStyle.paddingRight);
|
||||
var paddingBottom = this.parseStyle(elemStyle.paddingBottom);
|
||||
var scrollParent = this.scrollParent(elem, false, true);
|
||||
var scrollbarWidth = this.scrollbarWidth(scrollParent, BODY_REGEX.test(scrollParent.tagName));
|
||||
var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName));
|
||||
|
||||
return {
|
||||
scrollbarWidth: scrollbarWidth,
|
||||
|
||||
@@ -1230,6 +1230,7 @@ describe('timepicker directive', function() {
|
||||
changeInputValueTo(el, 'pizza');
|
||||
expect($rootScope.time).toBe(null);
|
||||
expect(el.parent().hasClass('has-error')).toBe(true);
|
||||
expect(el.hasClass('ng-invalid-hours'));
|
||||
expect(element.hasClass('ng-invalid-time')).toBe(true);
|
||||
|
||||
changeInputValueTo(el, 8);
|
||||
@@ -1247,6 +1248,7 @@ describe('timepicker directive', function() {
|
||||
changeInputValueTo(el, '8a');
|
||||
expect($rootScope.time).toBe(null);
|
||||
expect(el.parent().hasClass('has-error')).toBe(true);
|
||||
expect(el.hasClass('ng-invalid-minutes'));
|
||||
expect(element.hasClass('ng-invalid-time')).toBe(true);
|
||||
|
||||
changeInputValueTo(el, 22);
|
||||
@@ -1262,6 +1264,7 @@ describe('timepicker directive', function() {
|
||||
changeInputValueTo(el, 'pizza');
|
||||
expect($rootScope.time).toBe(null);
|
||||
expect(el.parent().hasClass('has-error')).toBe(true);
|
||||
expect(el.hasClass('ng-invalid-seconds'));
|
||||
expect(element.hasClass('ng-invalid-time')).toBe(true);
|
||||
|
||||
changeInputValueTo(el, 13);
|
||||
@@ -1291,6 +1294,9 @@ describe('timepicker directive', function() {
|
||||
elS.blur();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(elH.hasClass('ng-valid'));
|
||||
expect(elM.hasClass('ng-valid'));
|
||||
expect(elS.hasClass('ng-valid'));
|
||||
expect(element.hasClass('ng-invalid-time')).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
})
|
||||
|
||||
.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {
|
||||
var hoursModelCtrl, minutesModelCtrl, secondsModelCtrl;
|
||||
var selected = new Date(),
|
||||
watchers = [],
|
||||
ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
|
||||
@@ -36,6 +37,10 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
minutesInputEl = inputs.eq(1),
|
||||
secondsInputEl = inputs.eq(2);
|
||||
|
||||
hoursModelCtrl = hoursInputEl.controller('ngModel');
|
||||
minutesModelCtrl = minutesInputEl.controller('ngModel');
|
||||
secondsModelCtrl = secondsInputEl.controller('ngModel');
|
||||
|
||||
var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;
|
||||
|
||||
if (mousewheel) {
|
||||
@@ -215,21 +220,21 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
return e.detail || delta > 0;
|
||||
};
|
||||
|
||||
hoursInputEl.bind('mousewheel wheel', function(e) {
|
||||
hoursInputEl.on('mousewheel wheel', function(e) {
|
||||
if (!disabled) {
|
||||
$scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
minutesInputEl.bind('mousewheel wheel', function(e) {
|
||||
minutesInputEl.on('mousewheel wheel', function(e) {
|
||||
if (!disabled) {
|
||||
$scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
secondsInputEl.bind('mousewheel wheel', function(e) {
|
||||
secondsInputEl.on('mousewheel wheel', function(e) {
|
||||
if (!disabled) {
|
||||
$scope.$apply(isScrollingUp(e) ? $scope.incrementSeconds() : $scope.decrementSeconds());
|
||||
}
|
||||
@@ -239,7 +244,7 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
|
||||
// Respond on up/down arrowkeys
|
||||
this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
|
||||
hoursInputEl.bind('keydown', function(e) {
|
||||
hoursInputEl.on('keydown', function(e) {
|
||||
if (!disabled) {
|
||||
if (e.which === 38) { // up
|
||||
e.preventDefault();
|
||||
@@ -253,7 +258,7 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
}
|
||||
});
|
||||
|
||||
minutesInputEl.bind('keydown', function(e) {
|
||||
minutesInputEl.on('keydown', function(e) {
|
||||
if (!disabled) {
|
||||
if (e.which === 38) { // up
|
||||
e.preventDefault();
|
||||
@@ -267,7 +272,7 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
}
|
||||
});
|
||||
|
||||
secondsInputEl.bind('keydown', function(e) {
|
||||
secondsInputEl.on('keydown', function(e) {
|
||||
if (!disabled) {
|
||||
if (e.which === 38) { // up
|
||||
e.preventDefault();
|
||||
@@ -295,14 +300,23 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
ngModelCtrl.$setValidity('time', false);
|
||||
if (angular.isDefined(invalidHours)) {
|
||||
$scope.invalidHours = invalidHours;
|
||||
if (hoursModelCtrl) {
|
||||
hoursModelCtrl.$setValidity('hours', false);
|
||||
}
|
||||
}
|
||||
|
||||
if (angular.isDefined(invalidMinutes)) {
|
||||
$scope.invalidMinutes = invalidMinutes;
|
||||
if (minutesModelCtrl) {
|
||||
minutesModelCtrl.$setValidity('minutes', false);
|
||||
}
|
||||
}
|
||||
|
||||
if (angular.isDefined(invalidSeconds)) {
|
||||
$scope.invalidSeconds = invalidSeconds;
|
||||
if (secondsModelCtrl) {
|
||||
secondsModelCtrl.$setValidity('seconds', false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -325,7 +339,7 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
}
|
||||
};
|
||||
|
||||
hoursInputEl.bind('blur', function(e) {
|
||||
hoursInputEl.on('blur', function(e) {
|
||||
ngModelCtrl.$setTouched();
|
||||
if (modelIsEmpty()) {
|
||||
makeValid();
|
||||
@@ -357,7 +371,7 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
}
|
||||
};
|
||||
|
||||
minutesInputEl.bind('blur', function(e) {
|
||||
minutesInputEl.on('blur', function(e) {
|
||||
ngModelCtrl.$setTouched();
|
||||
if (modelIsEmpty()) {
|
||||
makeValid();
|
||||
@@ -383,7 +397,7 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
}
|
||||
};
|
||||
|
||||
secondsInputEl.bind('blur', function(e) {
|
||||
secondsInputEl.on('blur', function(e) {
|
||||
if (modelIsEmpty()) {
|
||||
makeValid();
|
||||
} else if (!$scope.invalidSeconds && $scope.seconds < 10) {
|
||||
@@ -425,6 +439,18 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
}
|
||||
|
||||
function makeValid() {
|
||||
if (hoursModelCtrl) {
|
||||
hoursModelCtrl.$setValidity('hours', true);
|
||||
}
|
||||
|
||||
if (minutesModelCtrl) {
|
||||
minutesModelCtrl.$setValidity('minutes', true);
|
||||
}
|
||||
|
||||
if (secondsModelCtrl) {
|
||||
secondsModelCtrl.$setValidity('seconds', true);
|
||||
}
|
||||
|
||||
ngModelCtrl.$setValidity('time', true);
|
||||
$scope.invalidHours = false;
|
||||
$scope.invalidMinutes = false;
|
||||
|
||||
@@ -118,3 +118,5 @@ For Safari 7+ support, if you want to use the **focus** `tooltip-trigger`, you n
|
||||
Click Me
|
||||
</a>
|
||||
```
|
||||
|
||||
For Safari (potentially all versions up to 9), there is an issue with the hover CSS selector when using multiple elements grouped close to each other that are using the tooltip - it is possible for multiple elements to gain the hover state when mousing between the elements quickly and exiting the container at the right time. See [issue #5445](https://github.com/angular-ui/bootstrap/issues/5445) for more details.
|
||||
|
||||
@@ -144,6 +144,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
var showTimeout;
|
||||
var hideTimeout;
|
||||
var positionTimeout;
|
||||
var adjustmentTimeout;
|
||||
var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
|
||||
var triggers = getTriggers(undefined);
|
||||
var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
|
||||
@@ -176,12 +177,13 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
|
||||
}
|
||||
|
||||
$timeout(function() {
|
||||
adjustmentTimeout = $timeout(function() {
|
||||
var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
|
||||
var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight);
|
||||
if (adjustment) {
|
||||
tooltip.css(adjustment);
|
||||
}
|
||||
adjustmentTimeout = null;
|
||||
}, 0, false);
|
||||
|
||||
// first time through tt element will have the
|
||||
@@ -346,7 +348,11 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
|
||||
if (tooltip) {
|
||||
tooltip.remove();
|
||||
|
||||
tooltip = null;
|
||||
if (adjustmentTimeout) {
|
||||
$timeout.cancel(adjustmentTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
openedTooltips.remove(ttScope);
|
||||
|
||||
@@ -430,7 +430,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap
|
||||
}
|
||||
});
|
||||
|
||||
element.bind('focus', function (evt) {
|
||||
element.on('focus', function (evt) {
|
||||
hasFocus = true;
|
||||
if (minLength === 0 && !modelCtrl.$viewValue) {
|
||||
$timeout(function() {
|
||||
@@ -439,7 +439,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap
|
||||
}
|
||||
});
|
||||
|
||||
element.bind('blur', function(evt) {
|
||||
element.on('blur', function(evt) {
|
||||
if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {
|
||||
selected = true;
|
||||
scope.$apply(function() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>
|
||||
<th colspan="{{::5 + showWeeks}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></button></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th ng-if="showWeeks" class="text-center"></th>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>
|
||||
<th colspan="{{::yearHeaderColspan}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></i></button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>
|
||||
<th colspan="{{::columns - 2}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ul class="uib-datepicker-popup dropdown-menu uib-position-measure" dropdown-nested ng-if="isOpen" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">
|
||||
<ul role="presentation" class="uib-datepicker-popup dropdown-menu uib-position-measure" dropdown-nested ng-if="isOpen" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">
|
||||
<li ng-transclude></li>
|
||||
<li ng-if="showButtonBar" class="uib-button-bar">
|
||||
<span class="btn-group pull-left">
|
||||
|
||||
Reference in New Issue
Block a user