diff --git a/.eslintrc b/.eslintrc
index e754434..8540796 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,4 +1,8 @@
{
+ "env": {
+ "browser": true,
+ "es6": true
+ },
"rules": {
"comma-dangle": 2,
"no-cond-assign": 2,
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..9e92540
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,15 @@
+The issues forum is __NOT__ for support requests. It is for bugs and feature requests only.
+Please read https://github.com/angular-ui/bootstrap/blob/master/CONTRIBUTING.md and search
+existing issues (both open and closed) prior to opening any new issue and ensure you follow the instructions therein.
+
+### Bug description:
+
+### Link to minimally-working plunker that reproduces the issue:
+
+### Version of Angular, UIBS, and Bootstrap
+
+Angular:
+
+UIBS:
+
+Bootstrap:
diff --git a/.npmignore b/.npmignore
index 5895bce..925a2cd 100644
--- a/.npmignore
+++ b/.npmignore
@@ -14,13 +14,11 @@ pids
logs
results
# test coverage files
-coverage/
+.coverage/
node_modules
npm-debug.log
-template/**/*.js
-
.git
docs
misc
diff --git a/.travis.yml b/.travis.yml
index 1c8ee40..fba6738 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,14 @@
language: node_js
node_js:
- - "5.1"
+ - "5.9"
+env:
+ - CXX=g++-4.8
+addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - g++-4.8
before_install:
- export DISPLAY=:99.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 944768f..4376216 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,504 @@
-
-## [0.14.3](https://github.com/angular-ui/bootstrap/compare/0.14.2...v0.14.3) (2015-10-23)
+
+## [1.3.3](https://github.com/angular-ui/bootstrap/compare/1.3.2...v1.3.3) (2016-05-23)
+
+
+### Bug Fixes
+
+* **datepicker:** add intermediary valid date check([a417ec2](https://github.com/angular-ui/bootstrap/commit/a417ec2)), closes [#5872](https://github.com/angular-ui/bootstrap/issues/5872) [#5865](https://github.com/angular-ui/bootstrap/issues/5865)
+* **datepickerPopup:** convert numbers to date before parsing([5188463](https://github.com/angular-ui/bootstrap/commit/5188463)), closes [#5873](https://github.com/angular-ui/bootstrap/issues/5873) [#5871](https://github.com/angular-ui/bootstrap/issues/5871)
+* **dropdown:** align position with vertical scrollbar([2b48259](https://github.com/angular-ui/bootstrap/commit/2b48259)), closes [#5830](https://github.com/angular-ui/bootstrap/issues/5830) [#4317](https://github.com/angular-ui/bootstrap/issues/4317)
+
+
+### Features
+
+* **accordion:** add alternative attribute support([4c40d9d](https://github.com/angular-ui/bootstrap/commit/4c40d9d)), closes [#5834](https://github.com/angular-ui/bootstrap/issues/5834) [#5839](https://github.com/angular-ui/bootstrap/issues/5839)
+* **modal:** add resolve values to template([dd09148](https://github.com/angular-ui/bootstrap/commit/dd09148)), closes [#5808](https://github.com/angular-ui/bootstrap/issues/5808) [#5857](https://github.com/angular-ui/bootstrap/issues/5857)
+* **tab:** allow strings for index([26d3995](https://github.com/angular-ui/bootstrap/commit/26d3995)), closes [#5713](https://github.com/angular-ui/bootstrap/issues/5713) [#5827](https://github.com/angular-ui/bootstrap/issues/5827)
+* **tabs:** pass the selected index to onDeselect([241fea8](https://github.com/angular-ui/bootstrap/commit/241fea8)), closes [#5820](https://github.com/angular-ui/bootstrap/issues/5820) [#5821](https://github.com/angular-ui/bootstrap/issues/5821)
+* **typeahead:** Add support for `should-select`([2ffb86f](https://github.com/angular-ui/bootstrap/commit/2ffb86f)), closes [#5671](https://github.com/angular-ui/bootstrap/issues/5671) [#5794](https://github.com/angular-ui/bootstrap/issues/5794)
+
+
+### BREAKING CHANGES
+
+* modal: Since this adds support for $resolve being exposed on $scope, it could potentially overwrite any pre-existing usage of it - this is an unlikely scenario, but marked as a breaking change in case this key is being used
+
+
+
+
+## [1.3.2](https://github.com/angular-ui/bootstrap/compare/1.3.1...v1.3.2) (2016-04-14)
+
+
+### Bug Fixes
+
+* **datepicker:** ensure datepicker is focused ([33cbd0f](https://github.com/angular-ui/bootstrap/commit/33cbd0f)), closes [#5761](https://github.com/angular-ui/bootstrap/issues/5761) [#5754](https://github.com/angular-ui/bootstrap/issues/5754)
+* **datepickerPopup:** do not show incorrect warning ([98eb8f1](https://github.com/angular-ui/bootstrap/commit/98eb8f1)), closes [#5743](https://github.com/angular-ui/bootstrap/issues/5743) [#5747](https://github.com/angular-ui/bootstrap/issues/5747)
+* **dropdown:** stop esc keydown event ([68200bb](https://github.com/angular-ui/bootstrap/commit/68200bb)), closes [#5778](https://github.com/angular-ui/bootstrap/issues/5778) [#5787](https://github.com/angular-ui/bootstrap/issues/5787)
+* **modal:** missing require in modal ([a887d2b](https://github.com/angular-ui/bootstrap/commit/a887d2b)), closes [#5786](https://github.com/angular-ui/bootstrap/issues/5786)
+* **modal:** scroll padding only added once ([aef08d5](https://github.com/angular-ui/bootstrap/commit/aef08d5)), closes [#5790](https://github.com/angular-ui/bootstrap/issues/5790) [#5789](https://github.com/angular-ui/bootstrap/issues/5789)
+* **site:** allow FastClick to be blocked ([37f9cd2](https://github.com/angular-ui/bootstrap/commit/37f9cd2)), closes [#5756](https://github.com/angular-ui/bootstrap/issues/5756)
+* **tooltip:** arrow position ([d96d53e](https://github.com/angular-ui/bootstrap/commit/d96d53e)), closes [#5785](https://github.com/angular-ui/bootstrap/issues/5785) [#5779](https://github.com/angular-ui/bootstrap/issues/5779)
+* **typeahead:** use $setViewValue on blur ([bba3f27](https://github.com/angular-ui/bootstrap/commit/bba3f27)), closes [#5769](https://github.com/angular-ui/bootstrap/issues/5769) [#5694](https://github.com/angular-ui/bootstrap/issues/5694)
+
+### Features
+
+* **modal:** add no css import script ([a27a4e2](https://github.com/angular-ui/bootstrap/commit/a27a4e2)), closes [#5788](https://github.com/angular-ui/bootstrap/issues/5788)
+
+
+### BREAKING CHANGES
+
+* dropdown: Stops propagation of keydown event when escape key is pressed. Removes keydown event from the document and moves it to the dropdown element.
+
+
+
+
+## [1.3.1](https://github.com/angular-ui/bootstrap/compare/1.3.0...v1.3.1) (2016-04-05)
+
+
+### Bug Fixes
+
+* **datepickerPopup:** register popup module ([86ee9c3](https://github.com/angular-ui/bootstrap/commit/86ee9c3)), closes [#5745](https://github.com/angular-ui/bootstrap/issues/5745)
+* **modal:** ensure correct index is set ([a08ad70](https://github.com/angular-ui/bootstrap/commit/a08ad70)), closes [#5733](https://github.com/angular-ui/bootstrap/issues/5733) [#5670](https://github.com/angular-ui/bootstrap/issues/5670)
+
+
+
+
+# [1.3.0](https://github.com/angular-ui/bootstrap/compare/1.2.5...v1.3.0) (2016-04-05)
+
+
+### Bug Fixes
+
+* **carousel:** fix animation from programmatic trigger ([44fb19b](https://github.com/angular-ui/bootstrap/commit/44fb19b)), closes [#5674](https://github.com/angular-ui/bootstrap/issues/5674) [#5601](https://github.com/angular-ui/bootstrap/issues/5601)
+* modify CSS loaded for modules with dependencies ([8074899](https://github.com/angular-ui/bootstrap/commit/8074899)), closes [#5698](https://github.com/angular-ui/bootstrap/issues/5698)
+* **carousel:** use proper sort comparison ([434c1c5](https://github.com/angular-ui/bootstrap/commit/434c1c5)), closes [#5638](https://github.com/angular-ui/bootstrap/issues/5638) [#5702](https://github.com/angular-ui/bootstrap/issues/5702)
+* **modal:** body content shift ([c83d0a8](https://github.com/angular-ui/bootstrap/commit/c83d0a8)), closes [#2631](https://github.com/angular-ui/bootstrap/issues/2631) [#5711](https://github.com/angular-ui/bootstrap/issues/5711)
+* **popover:** rename title attribute ([cca1460](https://github.com/angular-ui/bootstrap/commit/cca1460)), closes [#5719](https://github.com/angular-ui/bootstrap/issues/5719) [#5721](https://github.com/angular-ui/bootstrap/issues/5721)
+* **tab:** add support for tab deselect prevention ([e0fcc00](https://github.com/angular-ui/bootstrap/commit/e0fcc00)), closes [#5720](https://github.com/angular-ui/bootstrap/issues/5720) [#5723](https://github.com/angular-ui/bootstrap/issues/5723)
+* **tab:** correctly identify index on removal ([03e6047](https://github.com/angular-ui/bootstrap/commit/03e6047)), closes [#5689](https://github.com/angular-ui/bootstrap/issues/5689)
+* **tab:** fix event handler call ([d767afb](https://github.com/angular-ui/bootstrap/commit/d767afb)), closes [#5720](https://github.com/angular-ui/bootstrap/issues/5720) [#5738](https://github.com/angular-ui/bootstrap/issues/5738)
+
+### Features
+
+* add support for loading without CSS ([de504fb](https://github.com/angular-ui/bootstrap/commit/de504fb)), closes [#5696](https://github.com/angular-ui/bootstrap/issues/5696)
+* **carousel:** disable prev/next arrows if at bounds ([a3964d4](https://github.com/angular-ui/bootstrap/commit/a3964d4)), closes [#5704](https://github.com/angular-ui/bootstrap/issues/5704) [#5708](https://github.com/angular-ui/bootstrap/issues/5708)
+* **dateparser:** use 68 as the yy format pivot year ([701e0cb](https://github.com/angular-ui/bootstrap/commit/701e0cb)), closes [#5735](https://github.com/angular-ui/bootstrap/issues/5735)
+* **datepicker:** deprecate literal usage ([fc02fd1](https://github.com/angular-ui/bootstrap/commit/fc02fd1)), closes [#5658](https://github.com/angular-ui/bootstrap/issues/5658) [#5732](https://github.com/angular-ui/bootstrap/issues/5732)
+* **datepicker:** remove deprecated code ([ad91c82](https://github.com/angular-ui/bootstrap/commit/ad91c82)), closes [#5660](https://github.com/angular-ui/bootstrap/issues/5660)
+* **datepicker:** watch for changes when falsy ([45165ba](https://github.com/angular-ui/bootstrap/commit/45165ba)), closes [#5672](https://github.com/angular-ui/bootstrap/issues/5672) [#5677](https://github.com/angular-ui/bootstrap/issues/5677)
+* **datepickerPopup:** split off popup from datepicker ([fbc873c](https://github.com/angular-ui/bootstrap/commit/fbc873c)), closes [#5676](https://github.com/angular-ui/bootstrap/issues/5676)
+* **dropdown:** remove $locationChangeSuccess listener ([c534cb4](https://github.com/angular-ui/bootstrap/commit/c534cb4)), closes [#5648](https://github.com/angular-ui/bootstrap/issues/5648) [#5680](https://github.com/angular-ui/bootstrap/issues/5680)
+* **timepicker:** remove automatic padding when empty ([449c0d1](https://github.com/angular-ui/bootstrap/commit/449c0d1)), closes [#5293](https://github.com/angular-ui/bootstrap/issues/5293) [#5299](https://github.com/angular-ui/bootstrap/issues/5299)
+
+
+### BREAKING CHANGES
+
+* carousel: This adds disabled CSS - there is a possibility this may break existing UI slightly for those adding custom CSS/making use of custom templates. Modify the template appropriately if necessary
+* timepicker: This removes automatic padding done by the timepicker
+when the input is empty - if that behavior is desired, write a custom
+directive implementing it
+* dropdown: The dropdown no longer will remain open on $locationChangeSuccess with autoclose set to disabled. Implement this logic inside app along with usage of isOpen two-way binding if this functionality is desired.
+* datepickerPopup: The datepicker popup is no longer a part of the
+datepicker module, but now a part of the datepickerPopup module. Please
+change code accordingly if including specific modules
+* datepicker: This removes inline datepicker attribute support and
+attribute pass-throughs in the popup
+
+
+
+
+## [1.2.5](https://github.com/angular-ui/bootstrap/compare/1.2.4...v1.2.5) (2016-03-20)
+
+
+### Bug Fixes
+
+* **datepicker:** dereference date initialization ([1b888d4](https://github.com/angular-ui/bootstrap/commit/1b888d4)), closes [#5643](https://github.com/angular-ui/bootstrap/issues/5643) [#5441](https://github.com/angular-ui/bootstrap/issues/5441)
+* **datepicker:** fix today button disabled condition ([316e96c](https://github.com/angular-ui/bootstrap/commit/316e96c)), closes [#5637](https://github.com/angular-ui/bootstrap/issues/5637) [#5622](https://github.com/angular-ui/bootstrap/issues/5622)
+* **modal:** dynamically fetch elements ([e15a22a](https://github.com/angular-ui/bootstrap/commit/e15a22a)), closes [#5630](https://github.com/angular-ui/bootstrap/issues/5630) [#5050](https://github.com/angular-ui/bootstrap/issues/5050) [#5421](https://github.com/angular-ui/bootstrap/issues/5421)
+* **popover:** add popover-html css ([54ac06a](https://github.com/angular-ui/bootstrap/commit/54ac06a)), closes [#5603](https://github.com/angular-ui/bootstrap/issues/5603) [#5602](https://github.com/angular-ui/bootstrap/issues/5602)
+* **tooltip:** css to support arrow positioning ([66c416c](https://github.com/angular-ui/bootstrap/commit/66c416c)), closes [#5610](https://github.com/angular-ui/bootstrap/issues/5610) [#5611](https://github.com/angular-ui/bootstrap/issues/5611)
+* **typeahead:** reset errors when clearing ([bc7c55a](https://github.com/angular-ui/bootstrap/commit/bc7c55a)), closes [#5641](https://github.com/angular-ui/bootstrap/issues/5641)
+
+### Features
+
+* **accordion:** add bound panel-class support ([ffb5529](https://github.com/angular-ui/bootstrap/commit/ffb5529)), closes [#5368](https://github.com/angular-ui/bootstrap/issues/5368) [#5596](https://github.com/angular-ui/bootstrap/issues/5596)
+* **modal:** exclude hidden elements from query ([5ef56e2](https://github.com/angular-ui/bootstrap/commit/5ef56e2)), closes [#5512](https://github.com/angular-ui/bootstrap/issues/5512) [#5644](https://github.com/angular-ui/bootstrap/issues/5644)
+* **rating:** ability to disable rating reset ([8747b58](https://github.com/angular-ui/bootstrap/commit/8747b58)), closes [#5532](https://github.com/angular-ui/bootstrap/issues/5532) [#5631](https://github.com/angular-ui/bootstrap/issues/5631)
+* **tab:** add select expressions ([bb36e40](https://github.com/angular-ui/bootstrap/commit/bb36e40)), closes [#5438](https://github.com/angular-ui/bootstrap/issues/5438)
+* **timepicker:** add pad-hours support ([c7be087](https://github.com/angular-ui/bootstrap/commit/c7be087)), closes [#4288](https://github.com/angular-ui/bootstrap/issues/4288) [#5633](https://github.com/angular-ui/bootstrap/issues/5633)
+
+
+
+
+## [1.2.4](https://github.com/angular-ui/bootstrap/compare/1.2.3...v1.2.4) (2016-03-06)
+
+
+
+
+
+## [1.2.3](https://github.com/angular-ui/bootstrap/compare/1.2.2...v1.2.3) (2016-03-06)
+
+
+### Bug Fixes
+
+* **dropdown:** correctly update isOpen ([aac0d2b](https://github.com/angular-ui/bootstrap/commit/aac0d2b)), closes [#5589](https://github.com/angular-ui/bootstrap/issues/5589) [#3261](https://github.com/angular-ui/bootstrap/issues/3261)
+* **modal:** switch to $animate ([dd62c73](https://github.com/angular-ui/bootstrap/commit/dd62c73)), closes [#5585](https://github.com/angular-ui/bootstrap/issues/5585) [#5298](https://github.com/angular-ui/bootstrap/issues/5298)
+* **position:** auto position append to body ([a516178](https://github.com/angular-ui/bootstrap/commit/a516178)), closes [#5582](https://github.com/angular-ui/bootstrap/issues/5582) [#5576](https://github.com/angular-ui/bootstrap/issues/5576)
+* **tabs:** support heading with : ([a945dd2](https://github.com/angular-ui/bootstrap/commit/a945dd2)), closes [#5590](https://github.com/angular-ui/bootstrap/issues/5590) [#5568](https://github.com/angular-ui/bootstrap/issues/5568)
+* **typeahead:** change to original scope ([7949494](https://github.com/angular-ui/bootstrap/commit/7949494)), closes [#5588](https://github.com/angular-ui/bootstrap/issues/5588) [#5467](https://github.com/angular-ui/bootstrap/issues/5467)
+* **typeahead:** update isOpen on escape ([313ba83](https://github.com/angular-ui/bootstrap/commit/313ba83)), closes [#5579](https://github.com/angular-ui/bootstrap/issues/5579) [#5587](https://github.com/angular-ui/bootstrap/issues/5587)
+
+### Features
+
+* **datepicker:** add helpers for styling ([c15dcbd](https://github.com/angular-ui/bootstrap/commit/c15dcbd)), closes [#5580](https://github.com/angular-ui/bootstrap/issues/5580)
+
+
+
+
+## [1.2.2](https://github.com/angular-ui/bootstrap/compare/1.2.1...v1.2.2) (2016-03-03)
+
+
+### Bug Fixes
+
+* **Gruntfile:** add per module flag ([a816251](https://github.com/angular-ui/bootstrap/commit/a816251)), closes [#5567](https://github.com/angular-ui/bootstrap/issues/5567)
+* **modal:** fire ng-leave on close ([299f751](https://github.com/angular-ui/bootstrap/commit/299f751)), closes [#5556](https://github.com/angular-ui/bootstrap/issues/5556) [#5399](https://github.com/angular-ui/bootstrap/issues/5399)
+* **modal:** fix bindToController props ([5e43870](https://github.com/angular-ui/bootstrap/commit/5e43870)), closes [#5569](https://github.com/angular-ui/bootstrap/issues/5569)
+* **position:** add CSS for webpack support ([d68086f](https://github.com/angular-ui/bootstrap/commit/d68086f)), closes [#5561](https://github.com/angular-ui/bootstrap/issues/5561)
+* **rating:** fix usage of aria-valuetext ([4369800](https://github.com/angular-ui/bootstrap/commit/4369800)), closes [#5573](https://github.com/angular-ui/bootstrap/issues/5573) [#5571](https://github.com/angular-ui/bootstrap/issues/5571)
+* **tabs:** update doc and fix tab demo ([9d74d6c](https://github.com/angular-ui/bootstrap/commit/9d74d6c)), closes [#5575](https://github.com/angular-ui/bootstrap/issues/5575) [#5551](https://github.com/angular-ui/bootstrap/issues/5551)
+* **tests:** add style tag once ([cc2d1b9](https://github.com/angular-ui/bootstrap/commit/cc2d1b9)), closes [#5557](https://github.com/angular-ui/bootstrap/issues/5557) [#5548](https://github.com/angular-ui/bootstrap/issues/5548)
+* **tooltip:** import CSS ([c8922a2](https://github.com/angular-ui/bootstrap/commit/c8922a2)), closes [#5552](https://github.com/angular-ui/bootstrap/issues/5552)
+
+
+
+
+## [1.2.1](https://github.com/angular-ui/bootstrap/compare/1.2.0...v1.2.1) (2016-02-27)
### Bug Fixes
+* **popover:** add missing selector ([70c1c90](https://github.com/angular-ui/bootstrap/commit/70c1c90)), closes [#5549](https://github.com/angular-ui/bootstrap/issues/5549)
+
+
+
+
+# [1.2.0](https://github.com/angular-ui/bootstrap/compare/1.1.2...v1.2.0) (2016-02-26)
+
+
+### Bug Fixes
+
+* **buttons:** fix uncheckable attribute ([b245242](https://github.com/angular-ui/bootstrap/commit/b245242)), closes [#5451](https://github.com/angular-ui/bootstrap/issues/5451) [#5412](https://github.com/angular-ui/bootstrap/issues/5412)
+* **dateparser:** append end of format ([5c565df](https://github.com/angular-ui/bootstrap/commit/5c565df)), closes [#5385](https://github.com/angular-ui/bootstrap/issues/5385) [#5387](https://github.com/angular-ui/bootstrap/issues/5387)
+* **datepicker:** adjust datepicker header buttons ([f125537](https://github.com/angular-ui/bootstrap/commit/f125537)), closes [#5393](https://github.com/angular-ui/bootstrap/issues/5393) [#5392](https://github.com/angular-ui/bootstrap/issues/5392)
+* **datepicker:** assign initDate correctly to the controller ([8769749](https://github.com/angular-ui/bootstrap/commit/8769749)), closes [#5541](https://github.com/angular-ui/bootstrap/issues/5541)
+* **datepicker:** check if initDate is valid ([ab59413](https://github.com/angular-ui/bootstrap/commit/ab59413)), closes [#5190](https://github.com/angular-ui/bootstrap/issues/5190) [#5266](https://github.com/angular-ui/bootstrap/issues/5266)
+* **datepicker:** default to current date ([4b2ee0f](https://github.com/angular-ui/bootstrap/commit/4b2ee0f)), closes [#5395](https://github.com/angular-ui/bootstrap/issues/5395) [#5190](https://github.com/angular-ui/bootstrap/issues/5190)
+* **datepicker:** fallback to current date ([e4fc201](https://github.com/angular-ui/bootstrap/commit/e4fc201)), closes [#5418](https://github.com/angular-ui/bootstrap/issues/5418) [#5417](https://github.com/angular-ui/bootstrap/issues/5417)
+* **datepicker:** fix popup updateOn: default support ([47e412e](https://github.com/angular-ui/bootstrap/commit/47e412e)), closes [#5529](https://github.com/angular-ui/bootstrap/issues/5529)
+* **datepicker:** stop event bubbling from buttons ([e283cea](https://github.com/angular-ui/bootstrap/commit/e283cea)), closes [#5400](https://github.com/angular-ui/bootstrap/issues/5400) [#5347](https://github.com/angular-ui/bootstrap/issues/5347)
+* **modal:** fix modal rendered promise ([42fb486](https://github.com/angular-ui/bootstrap/commit/42fb486)), closes [#5401](https://github.com/angular-ui/bootstrap/issues/5401) [#5331](https://github.com/angular-ui/bootstrap/issues/5331)
+* **modal:** fix race condition with openedClass ([979fe0b](https://github.com/angular-ui/bootstrap/commit/979fe0b)), closes [#5483](https://github.com/angular-ui/bootstrap/issues/5483)
+* **position:** getRawNode to handle select/ul elem ([8b3e86f](https://github.com/angular-ui/bootstrap/commit/8b3e86f)), closes [#5491](https://github.com/angular-ui/bootstrap/issues/5491) [#5354](https://github.com/angular-ui/bootstrap/issues/5354)
+* **position:** move inline styles to a class ([4bb178a](https://github.com/angular-ui/bootstrap/commit/4bb178a)), closes [#5535](https://github.com/angular-ui/bootstrap/issues/5535) [#5470](https://github.com/angular-ui/bootstrap/issues/5470)
+* **progressbar:** fix default max value ([258b341](https://github.com/angular-ui/bootstrap/commit/258b341)), closes [#5374](https://github.com/angular-ui/bootstrap/issues/5374) [#5373](https://github.com/angular-ui/bootstrap/issues/5373)
+* **rating:** change to read-only ([d5a757d](https://github.com/angular-ui/bootstrap/commit/d5a757d)), closes [#5371](https://github.com/angular-ui/bootstrap/issues/5371) [#5435](https://github.com/angular-ui/bootstrap/issues/5435)
+* **tab:** make active optional ([d1553a4](https://github.com/angular-ui/bootstrap/commit/d1553a4)), closes [#5489](https://github.com/angular-ui/bootstrap/issues/5489)
+* **tabs:** adding bootstrap 4 specific class ([3814fe3](https://github.com/angular-ui/bootstrap/commit/3814fe3)), closes [#5488](https://github.com/angular-ui/bootstrap/issues/5488)
+* **typeahead:** fix shift tab ([64e3127](https://github.com/angular-ui/bootstrap/commit/64e3127)), closes [#5494](https://github.com/angular-ui/bootstrap/issues/5494) [#5493](https://github.com/angular-ui/bootstrap/issues/5493)
+* **typeahead:** Fix tab index for hint input ([4178500](https://github.com/angular-ui/bootstrap/commit/4178500)), closes [#5478](https://github.com/angular-ui/bootstrap/issues/5478) [#5492](https://github.com/angular-ui/bootstrap/issues/5492)
+
+### Features
+
+* **accordion:** use attribute for heading insertion ([ca6b177](https://github.com/angular-ui/bootstrap/commit/ca6b177)), closes [#5324](https://github.com/angular-ui/bootstrap/issues/5324) [#5396](https://github.com/angular-ui/bootstrap/issues/5396)
+* **datepicker:** add deprecation notices ([10eac7c](https://github.com/angular-ui/bootstrap/commit/10eac7c)), closes [#5415](https://github.com/angular-ui/bootstrap/issues/5415)
+* **datepicker:** implement auto position ([f9903ba](https://github.com/angular-ui/bootstrap/commit/f9903ba)), closes [#5444](https://github.com/angular-ui/bootstrap/issues/5444)
+* **datepicker:** move attribute support to options ([d880aea](https://github.com/angular-ui/bootstrap/commit/d880aea)), closes [#5528](https://github.com/angular-ui/bootstrap/issues/5528)
+* **datepicker:** move datepicker mode to options ([74a1d04](https://github.com/angular-ui/bootstrap/commit/74a1d04)), closes [#5526](https://github.com/angular-ui/bootstrap/issues/5526)
+* **datepicker:** pass options from popup to inline ([3e10184](https://github.com/angular-ui/bootstrap/commit/3e10184)), closes [#5355](https://github.com/angular-ui/bootstrap/issues/5355)
+* **datepicker:** preserve popup attributes ([bbc4912](https://github.com/angular-ui/bootstrap/commit/bbc4912)), closes [#5537](https://github.com/angular-ui/bootstrap/issues/5537)
+* **modal:** Call $onInit on controller if defined ([8349758](https://github.com/angular-ui/bootstrap/commit/8349758)), closes [#5472](https://github.com/angular-ui/bootstrap/issues/5472) [#5509](https://github.com/angular-ui/bootstrap/issues/5509)
+* **pagination:** add custom label support ([785c373](https://github.com/angular-ui/bootstrap/commit/785c373)), closes [#2532](https://github.com/angular-ui/bootstrap/issues/2532) [#5547](https://github.com/angular-ui/bootstrap/issues/5547)
+* **position:** add isScrollable ([3c0a7cd](https://github.com/angular-ui/bootstrap/commit/3c0a7cd)), closes [#5508](https://github.com/angular-ui/bootstrap/issues/5508)
+* **tab:** add template-url support ([54c51c4](https://github.com/angular-ui/bootstrap/commit/54c51c4)), closes [#5405](https://github.com/angular-ui/bootstrap/issues/5405) [#5443](https://github.com/angular-ui/bootstrap/issues/5443)
+* **tabs:** support optional classes on tab ([8364e76](https://github.com/angular-ui/bootstrap/commit/8364e76)), closes [#5430](https://github.com/angular-ui/bootstrap/issues/5430)
+* **tooltip:** arrow position ([fa17c48](https://github.com/angular-ui/bootstrap/commit/fa17c48)), closes [#5464](https://github.com/angular-ui/bootstrap/issues/5464) [#5502](https://github.com/angular-ui/bootstrap/issues/5502)
+* **typeahead:** add dynamic min length support ([f81d440](https://github.com/angular-ui/bootstrap/commit/f81d440)), closes [#5363](https://github.com/angular-ui/bootstrap/issues/5363)
+
+
+### BREAKING CHANGES
+
+* rating: Attribute supported has been changed to `read-only`
+from `readonly`
+* accordion: This changes to use the `uibAccordionHeader` attribute instead of a `` element for inserting the custom header HTML. If you use a custom template for the accordion group, please add this attribute to the appropriate location.
+* datepicker: This requires $event to be passed in the second
+argument of the select function and in the close argument for the popup
+template
+* datepicker: This adds extra CSS for the datepicker for the left and right header buttons - one can override this appropriately with any selector of class priority higher than 1
+* datepicker: This breaks any snake-cased key usage, i.e.
+`show-weeks`. Convert all keys used to camelCase.
+* tab: Make the `active` attribute optional and move to `tabset` element.
+* carousel: the `active` attribute is now required on the `uib-carousel` element and a unique `index` attribute is required on each `uib-slide` element.
+
+
+
+
+## [1.1.2](https://github.com/angular-ui/bootstrap/compare/1.1.1...v1.1.2) (2016-02-01)
+
+
+### Bug Fixes
+
+* **datepicker:** fix validation for M! & d! ([c3b1431](https://github.com/angular-ui/bootstrap/commit/c3b1431)), closes [#5376](https://github.com/angular-ui/bootstrap/issues/5376) [#5225](https://github.com/angular-ui/bootstrap/issues/5225)
+* **modal:** ensure shift+tab is trapped in modal ([d2621e3](https://github.com/angular-ui/bootstrap/commit/d2621e3)), closes [#5294](https://github.com/angular-ui/bootstrap/issues/5294) [#5229](https://github.com/angular-ui/bootstrap/issues/5229)
+* **tooltip:** prevent closing on $locationChangeSuccess ([48c9cd8](https://github.com/angular-ui/bootstrap/commit/48c9cd8)), closes [#5360](https://github.com/angular-ui/bootstrap/issues/5360) [#5337](https://github.com/angular-ui/bootstrap/issues/5337)
+* **typeahead:** add guard for no $viewValue ([dbe9e81](https://github.com/angular-ui/bootstrap/commit/dbe9e81)), closes [#5358](https://github.com/angular-ui/bootstrap/issues/5358) [#5357](https://github.com/angular-ui/bootstrap/issues/5357)
+
+### Features
+
+* **accordion:** add aria tags ([61cdef1](https://github.com/angular-ui/bootstrap/commit/61cdef1)), closes [#5338](https://github.com/angular-ui/bootstrap/issues/5338)
+* **datepicker:** add datepickerOptions support ([e58c42c](https://github.com/angular-ui/bootstrap/commit/e58c42c)), closes [#5340](https://github.com/angular-ui/bootstrap/issues/5340)
+
+
+
+
+## [1.1.1](https://github.com/angular-ui/bootstrap/compare/v1.1.0...v1.1.1) (2016-01-25)
+
+
+### Bug Fixes
+
+* **datepicker:** allow using min/max mode/date with datepickerOptions ([97af6a9](https://github.com/angular-ui/bootstrap/commit/97af6a9)), closes [#5334](https://github.com/angular-ui/bootstrap/issues/5334) [#5315](https://github.com/angular-ui/bootstrap/issues/5315)
+* **modal:** fix modal closed resolution ([d5a48ea](https://github.com/angular-ui/bootstrap/commit/d5a48ea)), closes [#5322](https://github.com/angular-ui/bootstrap/issues/5322) [#5326](https://github.com/angular-ui/bootstrap/issues/5326)
+
+
+
+
+# [1.1.0](https://github.com/angular-ui/bootstrap/compare/v1.0.3...v1.1.0) (2016-01-18)
+
+
+## Bug Fixes
+
+* **collapse:** avoid initial animation when expanded ([57219aa](https://github.com/angular-ui/bootstrap/commit/57219aa)), closes [#5199](https://github.com/angular-ui/bootstrap/issues/5199) [#4414](https://github.com/angular-ui/bootstrap/issues/4414) [#5192](https://github.com/angular-ui/bootstrap/issues/5192)
+* **datepicker:** allow expressions for minMode/maxMode ([7e93ec9](https://github.com/angular-ui/bootstrap/commit/7e93ec9)), closes [#5264](https://github.com/angular-ui/bootstrap/issues/5264) [#5268](https://github.com/angular-ui/bootstrap/issues/5268) [#5240](https://github.com/angular-ui/bootstrap/issues/5240)
+* **datepicker:** fix popup CSS ([b3e6d17](https://github.com/angular-ui/bootstrap/commit/b3e6d17)), closes [#5258](https://github.com/angular-ui/bootstrap/issues/5258)
+* **datepicker:** fix popup element garbage collection ([2cb3bc2](https://github.com/angular-ui/bootstrap/commit/2cb3bc2)), closes [#5274](https://github.com/angular-ui/bootstrap/issues/5274) [#5058](https://github.com/angular-ui/bootstrap/issues/5058)
+* **datepicker:** pass through null ([78ba137](https://github.com/angular-ui/bootstrap/commit/78ba137)), closes [#5275](https://github.com/angular-ui/bootstrap/issues/5275) [#5238](https://github.com/angular-ui/bootstrap/issues/5238)
+* **modal:** change to compile before appending ([1dbad8a](https://github.com/angular-ui/bootstrap/commit/1dbad8a)), closes [#5224](https://github.com/angular-ui/bootstrap/issues/5224) [#5183](https://github.com/angular-ui/bootstrap/issues/5183)
+* **paging:** garbage collect parent $watchers ([32b88f1](https://github.com/angular-ui/bootstrap/commit/32b88f1)), closes [#5276](https://github.com/angular-ui/bootstrap/issues/5276)
+* **position:** positionArrow descendant selector ([9f4c3a5](https://github.com/angular-ui/bootstrap/commit/9f4c3a5), [e8b6a83](https://github.com/angular-ui/bootstrap/commit/e8b6a83)), closes [#5246](https://github.com/angular-ui/bootstrap/issues/5246) [#5230](https://github.com/angular-ui/bootstrap/issues/5230)
+* **tab:** revert template change ([907c851](https://github.com/angular-ui/bootstrap/commit/907c851)), closes [#5262](https://github.com/angular-ui/bootstrap/issues/5262) [#5254](https://github.com/angular-ui/bootstrap/issues/5254)
+* **timepicker:** garbage collect parent watchers ([3f809af](https://github.com/angular-ui/bootstrap/commit/3f809af)), closes [#5277](https://github.com/angular-ui/bootstrap/issues/5277)
+* **tooltip:** fix addClass signature ([6a2d91b](https://github.com/angular-ui/bootstrap/commit/6a2d91b)), closes [#5235](https://github.com/angular-ui/bootstrap/issues/5235)
+* **typeahead:** add guard for destroyed $scope ([e105e85](https://github.com/angular-ui/bootstrap/commit/e105e85)), closes [#5267](https://github.com/angular-ui/bootstrap/issues/5267)
+* **typeahead:** fix css selector ([00ac93e](https://github.com/angular-ui/bootstrap/commit/00ac93e)), closes [#5251](https://github.com/angular-ui/bootstrap/issues/5251)
+
+## Features
+
+* **collapse:** add callback hooks ([446364a](https://github.com/angular-ui/bootstrap/commit/446364a)), closes [#5194](https://github.com/angular-ui/bootstrap/issues/5194) [#5226](https://github.com/angular-ui/bootstrap/issues/5226)
+* **datepicker:** extract inline styles to stylesheet ([6843ab6](https://github.com/angular-ui/bootstrap/commit/6843ab6)), closes [#5215](https://github.com/angular-ui/bootstrap/issues/5215)
+* **datepicker:** use $locale for starting day ([332eefb](https://github.com/angular-ui/bootstrap/commit/332eefb)), closes [#4954](https://github.com/angular-ui/bootstrap/issues/4954) [#5281](https://github.com/angular-ui/bootstrap/issues/5281)
+* **timepicker:** add placeholder for seconds input ([717ea69](https://github.com/angular-ui/bootstrap/commit/717ea69)), closes [#5257](https://github.com/angular-ui/bootstrap/issues/5257)
+* **timepicker:** move inline styles to stylesheet ([b658b03](https://github.com/angular-ui/bootstrap/commit/b658b03)), closes [#5218](https://github.com/angular-ui/bootstrap/issues/5218)
+* **typeahead:** add title to matches ([f523361](https://github.com/angular-ui/bootstrap/commit/f523361)), closes [#5252](https://github.com/angular-ui/bootstrap/issues/5252)
+* **typeahead:** move inline style to stylesheet ([e8201d1](https://github.com/angular-ui/bootstrap/commit/e8201d1)), closes [#5219](https://github.com/angular-ui/bootstrap/issues/5219)
+
+
+## BREAKING CHANGES
+
+* tab: This undoes the prior change to the template using div
+elements. If one wishes to use div elements, one must override the
+template in one's app and provide the necessary CSS
+
+
+
+
+# [1.0.3](https://github.com/angular-ui/bootstrap/compare/v1.0.2...v1.0.3) (2016-01-12)
+
+
+## Bug Fixes
+
+* **timepicker:** fix injection ([627a451](https://github.com/angular-ui/bootstrap/commit/627a451))
+
+
+
+
+# [1.0.2](https://github.com/angular-ui/bootstrap/compare/v1.0.1...v1.0.2) (2016-01-12)
+
+
+## Bug Fixes
+
+* **tabs:** fix csp check ([74be568](https://github.com/angular-ui/bootstrap/commit/74be568)), closes [#5214](https://github.com/angular-ui/bootstrap/issues/5214)
+
+
+
+
+# [1.0.1](https://github.com/angular-ui/bootstrap/compare/1.0.0...v1.0.1) (2016-01-12)
+
+
+## Bug Fixes
+
+* **build:** add ; after script ([9d0269e](https://github.com/angular-ui/bootstrap/commit/9d0269e)), closes [#5197](https://github.com/angular-ui/bootstrap/issues/5197) [#5196](https://github.com/angular-ui/bootstrap/issues/5196)
+* **carousel:** reset active for buffered transitions ([36fca74](https://github.com/angular-ui/bootstrap/commit/36fca74)), closes [#5195](https://github.com/angular-ui/bootstrap/issues/5195) [#5178](https://github.com/angular-ui/bootstrap/issues/5178)
+* **datepicker:** fix error message ([aa010b0](https://github.com/angular-ui/bootstrap/commit/aa010b0)), closes [#5198](https://github.com/angular-ui/bootstrap/issues/5198) [#5191](https://github.com/angular-ui/bootstrap/issues/5191)
+* **datepicker:** fix usage of non-standard format ([428beaf](https://github.com/angular-ui/bootstrap/commit/428beaf)), closes [#5188](https://github.com/angular-ui/bootstrap/issues/5188) [#5187](https://github.com/angular-ui/bootstrap/issues/5187)
+* **timepicker:** prevent mixture of numbers and letters ([9e9c6cf](https://github.com/angular-ui/bootstrap/commit/9e9c6cf)), closes [#5201](https://github.com/angular-ui/bootstrap/issues/5201) [#5085](https://github.com/angular-ui/bootstrap/issues/5085)
+* **timepicker:** use correct disabled expression ([71afeeb](https://github.com/angular-ui/bootstrap/commit/71afeeb)), closes [#5185](https://github.com/angular-ui/bootstrap/issues/5185) [#5182](https://github.com/angular-ui/bootstrap/issues/5182)
+* **typeahead:** scroll only parent element ([3dac5e3](https://github.com/angular-ui/bootstrap/commit/3dac5e3)), closes [#5212](https://github.com/angular-ui/bootstrap/issues/5212) [#5180](https://github.com/angular-ui/bootstrap/issues/5180)
+
+## Features
+
+* **tabs:** add CSS to css file ([db7adf7](https://github.com/angular-ui/bootstrap/commit/db7adf7)), closes [#5211](https://github.com/angular-ui/bootstrap/issues/5211)
+* **timepicker:** add templateUrl in timepickerConfig ([4b0e381](https://github.com/angular-ui/bootstrap/commit/4b0e381)), closes [#5087](https://github.com/angular-ui/bootstrap/issues/5087) [#5200](https://github.com/angular-ui/bootstrap/issues/5200)
+
+
+
+
+# [1.0.0](https://github.com/angular-ui/bootstrap/compare/0.14.3...v1.0.0) (2016-01-08)
+
+
+## Bug Fixes
+
+* **accordion:** ensure panelOpen class is present ([0917623](https://github.com/angular-ui/bootstrap/commit/0917623)), closes [#4849](https://github.com/angular-ui/bootstrap/issues/4849) [#4870](https://github.com/angular-ui/bootstrap/issues/4870)
+* **accordion:** fix unexpected routing ([df211bd](https://github.com/angular-ui/bootstrap/commit/df211bd)), closes [#4792](https://github.com/angular-ui/bootstrap/issues/4792)
+* **carousel:** decouple animation information from DOM ([38c1b14](https://github.com/angular-ui/bootstrap/commit/38c1b14)), closes [#4737](https://github.com/angular-ui/bootstrap/issues/4737) [#4516](https://github.com/angular-ui/bootstrap/issues/4516)
+* **carousel:** fix conditions for animation ([12a37e0](https://github.com/angular-ui/bootstrap/commit/12a37e0)), closes [#4974](https://github.com/angular-ui/bootstrap/issues/4974) [#4972](https://github.com/angular-ui/bootstrap/issues/4972)
+* **carousel:** remove version checks ([9d93af1](https://github.com/angular-ui/bootstrap/commit/9d93af1)), closes [#4122](https://github.com/angular-ui/bootstrap/issues/4122) [#4774](https://github.com/angular-ui/bootstrap/issues/4774)
+* **carousel:** resolve rendering issues ([763cfd9](https://github.com/angular-ui/bootstrap/commit/763cfd9)), closes [#4984](https://github.com/angular-ui/bootstrap/issues/4984) [#4361](https://github.com/angular-ui/bootstrap/issues/4361) [#4823](https://github.com/angular-ui/bootstrap/issues/4823) [#4969](https://github.com/angular-ui/bootstrap/issues/4969)
+* **collapse:** set initial state to avoid animation ([5ad08ff](https://github.com/angular-ui/bootstrap/commit/5ad08ff)), closes [#5075](https://github.com/angular-ui/bootstrap/issues/5075) [#4848](https://github.com/angular-ui/bootstrap/issues/4848) [#4885](https://github.com/angular-ui/bootstrap/issues/4885)
+* **dateparser:** baseDate only care about dates ([21b2297](https://github.com/angular-ui/bootstrap/commit/21b2297)), closes [#4767](https://github.com/angular-ui/bootstrap/issues/4767)
+* **dateparser:** enforce order of regex construction ([83d1435](https://github.com/angular-ui/bootstrap/commit/83d1435)), closes [#4810](https://github.com/angular-ui/bootstrap/issues/4810) [#4808](https://github.com/angular-ui/bootstrap/issues/4808)
+* **datepicker:** active date should be model if present ([9019298](https://github.com/angular-ui/bootstrap/commit/9019298)), closes [#5082](https://github.com/angular-ui/bootstrap/issues/5082) [#5081](https://github.com/angular-ui/bootstrap/issues/5081)
+* **datepicker:** correctly display pre-100 years ([beabb4a](https://github.com/angular-ui/bootstrap/commit/beabb4a)), closes [#4812](https://github.com/angular-ui/bootstrap/issues/4812) [#4032](https://github.com/angular-ui/bootstrap/issues/4032)
+* **datepicker:** correctly set minMode/maxMode ([1524080](https://github.com/angular-ui/bootstrap/commit/1524080)), closes [#5093](https://github.com/angular-ui/bootstrap/issues/5093) [#5090](https://github.com/angular-ui/bootstrap/issues/5090)
+* **datepicker:** fix minDate/maxDate with literals ([e7f709f](https://github.com/angular-ui/bootstrap/commit/e7f709f)), closes [#4841](https://github.com/angular-ui/bootstrap/issues/4841) [#3437](https://github.com/angular-ui/bootstrap/issues/3437)
+* **datepicker:** stop propagation of esc in popup ([000d6c3](https://github.com/angular-ui/bootstrap/commit/000d6c3)), closes [#5074](https://github.com/angular-ui/bootstrap/issues/5074) [#5013](https://github.com/angular-ui/bootstrap/issues/5013)
+* **datepicker:** update with alternative format ([fd88dcb](https://github.com/angular-ui/bootstrap/commit/fd88dcb)), closes [#5014](https://github.com/angular-ui/bootstrap/issues/5014)
+* **debounce:** fix argument slicing ([e196be8](https://github.com/angular-ui/bootstrap/commit/e196be8)), closes [#4859](https://github.com/angular-ui/bootstrap/issues/4859) [#4860](https://github.com/angular-ui/bootstrap/issues/4860)
+* **dropdown:** do not close on right click ([bf1768e](https://github.com/angular-ui/bootstrap/commit/bf1768e)), closes [#5052](https://github.com/angular-ui/bootstrap/issues/5052) [#5051](https://github.com/angular-ui/bootstrap/issues/5051)
+* **dropdown:** remove class support for uib-dropdown-menu directive ([43535cf](https://github.com/angular-ui/bootstrap/commit/43535cf)), closes [#4753](https://github.com/angular-ui/bootstrap/issues/4753)
+* **dropdown:** remove extra uib-keyboard-nav ([57f72b2](https://github.com/angular-ui/bootstrap/commit/57f72b2)), closes [#4891](https://github.com/angular-ui/bootstrap/issues/4891)
+* **modal:** add focus check for IE ([a5c2a5b](https://github.com/angular-ui/bootstrap/commit/a5c2a5b)), closes [#5097](https://github.com/angular-ui/bootstrap/issues/5097) [#5096](https://github.com/angular-ui/bootstrap/issues/5096)
+* **modal:** clean up animation when disabled ([972dee6](https://github.com/angular-ui/bootstrap/commit/972dee6)), closes [#4740](https://github.com/angular-ui/bootstrap/issues/4740) [#4672](https://github.com/angular-ui/bootstrap/issues/4672)
+* **modal:** fix bindToController ([b8969d1](https://github.com/angular-ui/bootstrap/commit/b8969d1)), closes [#5048](https://github.com/angular-ui/bootstrap/issues/5048) [#5039](https://github.com/angular-ui/bootstrap/issues/5039)
+* **modal:** retain focus if child has focus ([726ccc3](https://github.com/angular-ui/bootstrap/commit/726ccc3)), closes [#4904](https://github.com/angular-ui/bootstrap/issues/4904) [#4903](https://github.com/angular-ui/bootstrap/issues/4903)
+* **modal:** trap tabbing regardless of config ([c0f1027](https://github.com/angular-ui/bootstrap/commit/c0f1027)), closes [#5010](https://github.com/angular-ui/bootstrap/issues/5010) [#4990](https://github.com/angular-ui/bootstrap/issues/4990)
+* **pagination:** retain model on initialization ([30099a0](https://github.com/angular-ui/bootstrap/commit/30099a0)), closes [#3786](https://github.com/angular-ui/bootstrap/issues/3786) [#4783](https://github.com/angular-ui/bootstrap/issues/4783) [#2956](https://github.com/angular-ui/bootstrap/issues/2956)
+* **tab:** fix unexpected routing ([d59083b](https://github.com/angular-ui/bootstrap/commit/d59083b)), closes [#4793](https://github.com/angular-ui/bootstrap/issues/4793) [#3266](https://github.com/angular-ui/bootstrap/issues/3266)
+* **timepicker:** correct meridian toggle condition ([09ad740](https://github.com/angular-ui/bootstrap/commit/09ad740)), closes [#4435](https://github.com/angular-ui/bootstrap/issues/4435)
+* **tooltip:** race condition when setting position ([429ddc1](https://github.com/angular-ui/bootstrap/commit/429ddc1)), closes [#4765](https://github.com/angular-ui/bootstrap/issues/4765) [#4757](https://github.com/angular-ui/bootstrap/issues/4757)
+* **typeahead:** allow parent to be required ([3aa41f0](https://github.com/angular-ui/bootstrap/commit/3aa41f0)), closes [#4800](https://github.com/angular-ui/bootstrap/issues/4800) [#2679](https://github.com/angular-ui/bootstrap/issues/2679)
+* **typeahead:** clear typeahead input when editable is false ([1d9294c](https://github.com/angular-ui/bootstrap/commit/1d9294c)), closes [#1620](https://github.com/angular-ui/bootstrap/issues/1620) [#4265](https://github.com/angular-ui/bootstrap/issues/4265) [#4752](https://github.com/angular-ui/bootstrap/issues/4752)
+* **typeahead:** fix programmatic focus issue ([cab0945](https://github.com/angular-ui/bootstrap/commit/cab0945)), closes [#5150](https://github.com/angular-ui/bootstrap/issues/5150) [#764](https://github.com/angular-ui/bootstrap/issues/764)
+* **typeahead:** use correct selector ([e1e6e1b](https://github.com/angular-ui/bootstrap/commit/e1e6e1b)), closes [#5168](https://github.com/angular-ui/bootstrap/issues/5168) [#5167](https://github.com/angular-ui/bootstrap/issues/5167)
+* allow library to be loaded async ([a851636](https://github.com/angular-ui/bootstrap/commit/a851636)), closes [#4775](https://github.com/angular-ui/bootstrap/issues/4775) [#3665](https://github.com/angular-ui/bootstrap/issues/3665)
+
+## Features
+
+* **accordion:** remove deprecated code ([0010aff](https://github.com/angular-ui/bootstrap/commit/0010aff)), closes [#4706](https://github.com/angular-ui/bootstrap/issues/4706)
+* **alert:** remove deprecated code ([21e852b](https://github.com/angular-ui/bootstrap/commit/21e852b)), closes [#4714](https://github.com/angular-ui/bootstrap/issues/4714)
+* **buttons:** add uib-uncheckable support ([b77618e](https://github.com/angular-ui/bootstrap/commit/b77618e)), closes [#3604](https://github.com/angular-ui/bootstrap/issues/3604) [#4791](https://github.com/angular-ui/bootstrap/issues/4791)
+* **buttons:** remove deprecated code ([b549263](https://github.com/angular-ui/bootstrap/commit/b549263)), closes [#4716](https://github.com/angular-ui/bootstrap/issues/4716)
+* **carousel:** expose next and prev on controller ([9b80ee1](https://github.com/angular-ui/bootstrap/commit/9b80ee1)), closes [#4851](https://github.com/angular-ui/bootstrap/issues/4851) [#4853](https://github.com/angular-ui/bootstrap/issues/4853)
+* **carousel:** remove deprecated code ([b159b21](https://github.com/angular-ui/bootstrap/commit/b159b21)), closes [#4717](https://github.com/angular-ui/bootstrap/issues/4717)
+* **collapse:** remove deprecated code ([bc004df](https://github.com/angular-ui/bootstrap/commit/bc004df)), closes [#4715](https://github.com/angular-ui/bootstrap/issues/4715)
+* **dateparser:** add M! and d! support ([b1cfc57](https://github.com/angular-ui/bootstrap/commit/b1cfc57)), closes [#4805](https://github.com/angular-ui/bootstrap/issues/4805) [#4809](https://github.com/angular-ui/bootstrap/issues/4809)
+* **dateparser:** add new format support ([ea388b3](https://github.com/angular-ui/bootstrap/commit/ea388b3)), closes [#3418](https://github.com/angular-ui/bootstrap/issues/3418) [#4833](https://github.com/angular-ui/bootstrap/issues/4833)
+* **dateparser:** add support for literals ([1c79888](https://github.com/angular-ui/bootstrap/commit/1c79888)), closes [#3914](https://github.com/angular-ui/bootstrap/issues/3914) [#4426](https://github.com/angular-ui/bootstrap/issues/4426)
+* **dateparser:** add Z support ([2fb812b](https://github.com/angular-ui/bootstrap/commit/2fb812b)), closes [#4831](https://github.com/angular-ui/bootstrap/issues/4831)
+* **dateparser:** change template literal from ' to ` ([9513f10](https://github.com/angular-ui/bootstrap/commit/9513f10)), closes [#4880](https://github.com/angular-ui/bootstrap/issues/4880) [#4936](https://github.com/angular-ui/bootstrap/issues/4936) [#4938](https://github.com/angular-ui/bootstrap/issues/4938)
+* **dateparser:** remove deprecated code ([2d68f41](https://github.com/angular-ui/bootstrap/commit/2d68f41)), closes [#4718](https://github.com/angular-ui/bootstrap/issues/4718)
+* **datepicker:** add allowInvalid support ([2460e42](https://github.com/angular-ui/bootstrap/commit/2460e42)), closes [#4694](https://github.com/angular-ui/bootstrap/issues/4694) [#4837](https://github.com/angular-ui/bootstrap/issues/4837)
+* **datepicker:** add disabled and ngDisabled support ([434c602](https://github.com/angular-ui/bootstrap/commit/434c602)), closes [#4059](https://github.com/angular-ui/bootstrap/issues/4059) [#4814](https://github.com/angular-ui/bootstrap/issues/4814)
+* **datepicker:** add semantic classes ([97c4333](https://github.com/angular-ui/bootstrap/commit/97c4333)), closes [#4761](https://github.com/angular-ui/bootstrap/issues/4761)
+* **datepicker:** add timezone support ([09098f8](https://github.com/angular-ui/bootstrap/commit/09098f8)), closes [#5062](https://github.com/angular-ui/bootstrap/issues/5062)
+* **datepicker:** implements alternative format support ([8bfeda0](https://github.com/angular-ui/bootstrap/commit/8bfeda0)), closes [#4951](https://github.com/angular-ui/bootstrap/issues/4951) [#4952](https://github.com/angular-ui/bootstrap/issues/4952)
+* **datepicker:** pass through attrs in popup ([26d3103](https://github.com/angular-ui/bootstrap/commit/26d3103)), closes [#4863](https://github.com/angular-ui/bootstrap/issues/4863) [#3338](https://github.com/angular-ui/bootstrap/issues/3338)
+* **datepicker:** remove deprecated code ([2fc3f21](https://github.com/angular-ui/bootstrap/commit/2fc3f21)), closes [#4708](https://github.com/angular-ui/bootstrap/issues/4708)
+* **datepicker:** yearRange -> yearRows and yearColumns ([b784422](https://github.com/angular-ui/bootstrap/commit/b784422)), closes [#3348](https://github.com/angular-ui/bootstrap/issues/3348) [#4970](https://github.com/angular-ui/bootstrap/issues/4970)
+* **dropdown:** add `append-to` support ([809ecdb](https://github.com/angular-ui/bootstrap/commit/809ecdb)), closes [#4467](https://github.com/angular-ui/bootstrap/issues/4467) [#4488](https://github.com/angular-ui/bootstrap/issues/4488)
+* **dropdown:** add open class support ([0495ff0](https://github.com/angular-ui/bootstrap/commit/0495ff0)), closes [#4466](https://github.com/angular-ui/bootstrap/issues/4466) [#4794](https://github.com/angular-ui/bootstrap/issues/4794)
+* **dropdown:** remove deprecated code ([ca3a343](https://github.com/angular-ui/bootstrap/commit/ca3a343)), closes [#4719](https://github.com/angular-ui/bootstrap/issues/4719)
+* **modal:** add appendTo support ([16d854c](https://github.com/angular-ui/bootstrap/commit/16d854c)), closes [#4599](https://github.com/angular-ui/bootstrap/issues/4599)
+* **modal:** add closed promise ([e9c4977](https://github.com/angular-ui/bootstrap/commit/e9c4977)), closes [#4979](https://github.com/angular-ui/bootstrap/issues/4979)
+* **modal:** add pluggable resolve support ([2635f0d](https://github.com/angular-ui/bootstrap/commit/2635f0d)), closes [#3405](https://github.com/angular-ui/bootstrap/issues/3405) [#5078](https://github.com/angular-ui/bootstrap/issues/5078)
+* **modal:** allow appending outside iframe ([80df015](https://github.com/angular-ui/bootstrap/commit/80df015)), closes [#4818](https://github.com/angular-ui/bootstrap/issues/4818)
+* **modal:** change to use $animate ([742132a](https://github.com/angular-ui/bootstrap/commit/742132a)), closes [#3418](https://github.com/angular-ui/bootstrap/issues/3418) [#4834](https://github.com/angular-ui/bootstrap/issues/4834)
+* **modal:** remove deprecated code ([a85d499](https://github.com/angular-ui/bootstrap/commit/a85d499)), closes [#4709](https://github.com/angular-ui/bootstrap/issues/4709)
+* **modal:** support requiring from parent directive ([e28cced](https://github.com/angular-ui/bootstrap/commit/e28cced)), closes [#3765](https://github.com/angular-ui/bootstrap/issues/3765) [#4844](https://github.com/angular-ui/bootstrap/issues/4844)
+* **pager:** change controllerAs to pager ([5890248](https://github.com/angular-ui/bootstrap/commit/5890248)), closes [#4961](https://github.com/angular-ui/bootstrap/issues/4961)
+* **pager:** move to separate component ([2a3314d](https://github.com/angular-ui/bootstrap/commit/2a3314d)), closes [#4935](https://github.com/angular-ui/bootstrap/issues/4935)
+* **pagination:** add force-ellipses option and boundaryLinkNumbers ([56642ea](https://github.com/angular-ui/bootstrap/commit/56642ea)), closes [#2924](https://github.com/angular-ui/bootstrap/issues/2924) [#3064](https://github.com/angular-ui/bootstrap/issues/3064) [#3565](https://github.com/angular-ui/bootstrap/issues/3565)
+* **pagination:** remove deprecated code ([75e493a](https://github.com/angular-ui/bootstrap/commit/75e493a)), closes [#4720](https://github.com/angular-ui/bootstrap/issues/4720)
+* **pagination:** Show ellipsis when rotating ([3f307e4](https://github.com/angular-ui/bootstrap/commit/3f307e4))
+* **paging:** factor out common controller code ([f2f8c4e](https://github.com/angular-ui/bootstrap/commit/f2f8c4e)), closes [#4803](https://github.com/angular-ui/bootstrap/issues/4803) [#4968](https://github.com/angular-ui/bootstrap/issues/4968)
+* **position:** implement auto positioning ([d265113](https://github.com/angular-ui/bootstrap/commit/d265113))
+* **position:** remove deprecated code ([42fa28f](https://github.com/angular-ui/bootstrap/commit/42fa28f)), closes [#4721](https://github.com/angular-ui/bootstrap/issues/4721)
+* **progressbar:** remove deprecated code ([0669b06](https://github.com/angular-ui/bootstrap/commit/0669b06)), closes [#4722](https://github.com/angular-ui/bootstrap/issues/4722)
+* **rating:** remove deprecated code ([d844623](https://github.com/angular-ui/bootstrap/commit/d844623)), closes [#4723](https://github.com/angular-ui/bootstrap/issues/4723)
+* **tabs:** add controllerAs support ([a5cac90](https://github.com/angular-ui/bootstrap/commit/a5cac90)), closes [#5019](https://github.com/angular-ui/bootstrap/issues/5019) [#5020](https://github.com/angular-ui/bootstrap/issues/5020)
+* **tabs:** remove deprecated code ([1b75164](https://github.com/angular-ui/bootstrap/commit/1b75164)), closes [#4710](https://github.com/angular-ui/bootstrap/issues/4710)
+* **timepicker:** add model state support ([fe69386](https://github.com/angular-ui/bootstrap/commit/fe69386)), closes [#3527](https://github.com/angular-ui/bootstrap/issues/3527) [#4835](https://github.com/angular-ui/bootstrap/issues/4835)
+* **timepicker:** add ngDisabled support ([4651191](https://github.com/angular-ui/bootstrap/commit/4651191)), closes [#2219](https://github.com/angular-ui/bootstrap/issues/2219) [#4811](https://github.com/angular-ui/bootstrap/issues/4811)
+* **timepicker:** add semantic classes ([1a822a1](https://github.com/angular-ui/bootstrap/commit/1a822a1)), closes [#4764](https://github.com/angular-ui/bootstrap/issues/4764) [#4971](https://github.com/angular-ui/bootstrap/issues/4971)
+* **timepicker:** add support for seconds ([c7fa845](https://github.com/angular-ui/bootstrap/commit/c7fa845)), closes [#4768](https://github.com/angular-ui/bootstrap/issues/4768)
+* **timepicker:** added ability to handle empty model ([8ffdaeb](https://github.com/angular-ui/bootstrap/commit/8ffdaeb)), closes [#1114](https://github.com/angular-ui/bootstrap/issues/1114) [#4203](https://github.com/angular-ui/bootstrap/issues/4203) [#4617](https://github.com/angular-ui/bootstrap/issues/4617)
+* **timepicker:** remove deprecated code ([feb2b73](https://github.com/angular-ui/bootstrap/commit/feb2b73)), closes [#4712](https://github.com/angular-ui/bootstrap/issues/4712)
+* **tooltip:** add appendToBody only attribute support ([2a1aaf2](https://github.com/angular-ui/bootstrap/commit/2a1aaf2)), closes [#4945](https://github.com/angular-ui/bootstrap/issues/4945) [#5071](https://github.com/angular-ui/bootstrap/issues/5071)
+* **tooltip:** add outsideClick trigger ([8737303](https://github.com/angular-ui/bootstrap/commit/8737303)), closes [#4419](https://github.com/angular-ui/bootstrap/issues/4419) [#4871](https://github.com/angular-ui/bootstrap/issues/4871)
+* **tooltip:** change back to jqLite listeners ([a5ca78a](https://github.com/angular-ui/bootstrap/commit/a5ca78a)), closes [#4886](https://github.com/angular-ui/bootstrap/issues/4886) [#5157](https://github.com/angular-ui/bootstrap/issues/5157)
+* **tooltip:** remove deprecated code ([187f64c](https://github.com/angular-ui/bootstrap/commit/187f64c)), closes [#4713](https://github.com/angular-ui/bootstrap/issues/4713)
+* **typeahead:** change to `appendTo` ([8637afc](https://github.com/angular-ui/bootstrap/commit/8637afc)), closes [#4797](https://github.com/angular-ui/bootstrap/issues/4797)
+* add npm support in main repository ([a9e476f](https://github.com/angular-ui/bootstrap/commit/a9e476f)), closes [#4739](https://github.com/angular-ui/bootstrap/issues/4739) [#5129](https://github.com/angular-ui/bootstrap/issues/5129)
+* prefix virtual templates with `uib/` ([342c576](https://github.com/angular-ui/bootstrap/commit/342c576)), closes [#1205](https://github.com/angular-ui/bootstrap/issues/1205) [#4839](https://github.com/angular-ui/bootstrap/issues/4839)
+* **typeahead:** add 'is-open' support ([167cfad](https://github.com/angular-ui/bootstrap/commit/167cfad)), closes [#4760](https://github.com/angular-ui/bootstrap/issues/4760) [#4779](https://github.com/angular-ui/bootstrap/issues/4779)
+* **typeahead:** add ability to scroll with matches ([a1355e7](https://github.com/angular-ui/bootstrap/commit/a1355e7)), closes [#4463](https://github.com/angular-ui/bootstrap/issues/4463)
+* **typeahead:** add dynamic toggling of Editable ([a5bafe6](https://github.com/angular-ui/bootstrap/commit/a5bafe6)), closes [#2638](https://github.com/angular-ui/bootstrap/issues/2638) [#4820](https://github.com/angular-ui/bootstrap/issues/4820)
+* **typeahead:** add event object to onSelect ([3e876b8](https://github.com/angular-ui/bootstrap/commit/3e876b8)), closes [#5165](https://github.com/angular-ui/bootstrap/issues/5165)
+* **typeahead:** add min-length === 0 support ([d859f42](https://github.com/angular-ui/bootstrap/commit/d859f42)), closes [#764](https://github.com/angular-ui/bootstrap/issues/764) [#2324](https://github.com/angular-ui/bootstrap/issues/2324) [#4789](https://github.com/angular-ui/bootstrap/issues/4789)
+* **typeahead:** add ng-model-options debounce support ([bd47f6c](https://github.com/angular-ui/bootstrap/commit/bd47f6c)), closes [#4982](https://github.com/angular-ui/bootstrap/issues/4982)
+* **typeahead:** add show-hint option ([ef82ad1](https://github.com/angular-ui/bootstrap/commit/ef82ad1)), closes [#2570](https://github.com/angular-ui/bootstrap/issues/2570) [#4784](https://github.com/angular-ui/bootstrap/issues/4784)
+* **typeahead:** remove deprecated code ([606d419](https://github.com/angular-ui/bootstrap/commit/606d419)), closes [#4711](https://github.com/angular-ui/bootstrap/issues/4711)
+
+## Reverts
+
+* **dateparser:** change template literal to ' ([f40066a](https://github.com/angular-ui/bootstrap/commit/f40066a)), closes [#5091](https://github.com/angular-ui/bootstrap/issues/5091)
+* **progressbar:** remove min-width ([ed7e460](https://github.com/angular-ui/bootstrap/commit/ed7e460)), closes [#5141](https://github.com/angular-ui/bootstrap/issues/5141)
+
+
+## BREAKING CHANGES
+
+* all: All of the deprecated services/directives/etc. are removed - one must use all prefixed versions instead
+* pager: As part of the split of the pager component from the
+pagination component, this changes the controllerAs use to `pager` from
+`pagination`
+* dropdown: `keyboard-nav` for the dropdown is no longer a directive and to use it you have to use `keyboard-nav` instead of `uib-keyboard-nav`.
+* dropdown: remove class support for `uib-dropdown-menu` directive.
+* All virtual templates in UI Bootstrap now are prefixed
+with `uib/` - if one is overriding the templates via `$templateCache` path
+or manually building the templates from the UI Bootstrap repository, one
+needs to change the string used in the `$templateCache` representation
+to have the new prefix
+* typeahead: Usage before
+```html
+
+
+```
+After
+```html
+
+
+```
+```js
+$scope.typeaheadContainer = angular.element(document.querySelector('#typeaheadContainer'));
+```
+* tab: This causes the cursor style to be removed from the tab - implement CSS on the `.uib-tab > div` selector, or similar, accordingly
+* accordion: This causes the cursor style to be removed from the heading - implement CSS on the `accordion-toggle` class accordingly
+* datepicker: yearRange is replaced by yearRows and yearColumns for manually specifying the dimensions of the yearpicker. If one wants the prior behavior with yearRange with a different number of rows, just set yearRows
+
+
+
+
+# [0.14.3](https://github.com/angular-ui/bootstrap/compare/0.14.2...v0.14.3) (2015-10-23)
+
+
+## Bug Fixes
+
* **alert:** allow interpolations with dismiss-on-timeout ([de24f46](https://github.com/angular-ui/bootstrap/commit/de24f46)), closes [#4665](https://github.com/angular-ui/bootstrap/issues/4665) [#4666](https://github.com/angular-ui/bootstrap/issues/4666)
* **buttons:** double toggle on spacebar ([e8808d3](https://github.com/angular-ui/bootstrap/commit/e8808d3)), closes [#4474](https://github.com/angular-ui/bootstrap/issues/4474) [#4630](https://github.com/angular-ui/bootstrap/issues/4630)
* **collapse:** fix collapse animation timing ([6d1cd0f](https://github.com/angular-ui/bootstrap/commit/6d1cd0f)), closes [#4493](https://github.com/angular-ui/bootstrap/issues/4493)
@@ -15,7 +510,7 @@
* **tooltip:** scrollbar flashing ([6c82b2b](https://github.com/angular-ui/bootstrap/commit/6c82b2b)), closes [#4550](https://github.com/angular-ui/bootstrap/issues/4550) [#4623](https://github.com/angular-ui/bootstrap/issues/4623) [#4458](https://github.com/angular-ui/bootstrap/issues/4458)
* **typeahead:** dangling event listeners ([94fb282](https://github.com/angular-ui/bootstrap/commit/94fb282)), closes [#4632](https://github.com/angular-ui/bootstrap/issues/4632) [#4636](https://github.com/angular-ui/bootstrap/issues/4636)
-### Features
+## Features
* **datepicker:** add templateUrl support for pickers ([1f65d87](https://github.com/angular-ui/bootstrap/commit/1f65d87)), closes [#4432](https://github.com/angular-ui/bootstrap/issues/4432)
* **datepicker:** preserve timezone with model ([0d64aad](https://github.com/angular-ui/bootstrap/commit/0d64aad)), closes [#4676](https://github.com/angular-ui/bootstrap/issues/4676)
@@ -24,10 +519,10 @@
-## [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...v0.14.2) (2015-10-14)
-### Bug Fixes
+## Bug Fixes
* **progressbar:** fix percentage calculation ([feb689c](https://github.com/angular-ui/bootstrap/commit/feb689c)), closes [#4471](https://github.com/angular-ui/bootstrap/issues/4471) [#4588](https://github.com/angular-ui/bootstrap/issues/4588) [#4452](https://github.com/angular-ui/bootstrap/issues/4452)
* **tooltip:** clean up stackedMap on scope destroy ([ebb5e18](https://github.com/angular-ui/bootstrap/commit/ebb5e18)), closes [#4610](https://github.com/angular-ui/bootstrap/issues/4610) [#4604](https://github.com/angular-ui/bootstrap/issues/4604)
@@ -36,10 +531,10 @@
-## [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...v0.14.1) (2015-10-11)
-### Bug Fixes
+## Bug Fixes
* **accordion:** make deprecated controller work with 1.3.x ([c5e6042](https://github.com/angular-ui/bootstrap/commit/c5e6042)), closes [#4574](https://github.com/angular-ui/bootstrap/issues/4574)
* **alert:** make deprecated controller work with 1.3.x ([e8c8ee6](https://github.com/angular-ui/bootstrap/commit/e8c8ee6)), closes [#4576](https://github.com/angular-ui/bootstrap/issues/4576)
@@ -53,7 +548,7 @@
* **tabs:** make deprecated controller work with 1.3.x ([685bd6a](https://github.com/angular-ui/bootstrap/commit/685bd6a)), closes [#4583](https://github.com/angular-ui/bootstrap/issues/4583)
* **timepicker:** make deprecated controller work with 1.3.x ([00f60ee](https://github.com/angular-ui/bootstrap/commit/00f60ee)), closes [#4584](https://github.com/angular-ui/bootstrap/issues/4584)
-### Features
+## Features
* **timepicker:** add accessibility improvements ([4ebecbc](https://github.com/angular-ui/bootstrap/commit/4ebecbc)), closes [#4569](https://github.com/angular-ui/bootstrap/issues/4569) [#4573](https://github.com/angular-ui/bootstrap/issues/4573)
@@ -63,7 +558,7 @@
# [0.14.0](https://github.com/angular-ui/bootstrap/compare/0.13.4...0.14.0) (2015-10-09)
-### Bug Fixes
+## Bug Fixes
* **accordion:** coerce to boolean ([b864aa9](https://github.com/angular-ui/bootstrap/commit/b864aa9)), closes [#4385](https://github.com/angular-ui/bootstrap/issues/4385)
* **accordion:** re-expose AccordionController ([5382226](https://github.com/angular-ui/bootstrap/commit/5382226)), closes [#4524](https://github.com/angular-ui/bootstrap/issues/4524)
@@ -95,7 +590,7 @@
* **tooltip:** properly gc popupTimeout ([ff52f52](https://github.com/angular-ui/bootstrap/commit/ff52f52)), closes [#2786](https://github.com/angular-ui/bootstrap/issues/2786)
* **tooltip:** set `visibility: hidden` to avoid flicker ([f7cb8bc](https://github.com/angular-ui/bootstrap/commit/f7cb8bc)), closes [#4342](https://github.com/angular-ui/bootstrap/issues/4342)
-### Features
+## Features
* **accordion:** use uib- prefix ([0328a76](https://github.com/angular-ui/bootstrap/commit/0328a76)), closes [#4389](https://github.com/angular-ui/bootstrap/issues/4389)
* **accordion:** use uib- prefix ([298ec8c](https://github.com/angular-ui/bootstrap/commit/298ec8c)), closes [#4503](https://github.com/angular-ui/bootstrap/issues/4503)
@@ -124,21 +619,21 @@
* **typeahead:** add customClass support for dropdown ([fa1cdfc](https://github.com/angular-ui/bootstrap/commit/fa1cdfc)), closes [#4332](https://github.com/angular-ui/bootstrap/issues/4332) [#4410](https://github.com/angular-ui/bootstrap/issues/4410)
* **typeahead:** add uib- prefix ([9e5e1a2](https://github.com/angular-ui/bootstrap/commit/9e5e1a2)), closes [#4542](https://github.com/angular-ui/bootstrap/issues/4542)
-### Reverts
+## Reverts
* **dropdown:** undo adding of `open` class on body ([6f9f1fc](https://github.com/angular-ui/bootstrap/commit/6f9f1fc))
-### BREAKING CHANGES
+## BREAKING CHANGES
* Removes focus on datepicker on selection of a date via keyboard for accessibility reasons
-## [0.13.4](https://github.com/angular-ui/bootstrap/compare/0.13.3...0.13.4) (2015-09-03)
+# [0.13.4](https://github.com/angular-ui/bootstrap/compare/0.13.3...0.13.4) (2015-09-03)
-### Bug Fixes
+## Bug Fixes
* **accordion:** add custom open class support ([575eb85](https://github.com/angular-ui/bootstrap/commit/575eb85)), closes [#4198](https://github.com/angular-ui/bootstrap/issues/4198)
* **datepicker:** ensure the original target is not in popup ([9b2f7ac](https://github.com/angular-ui/bootstrap/commit/9b2f7ac)), closes [#4316](https://github.com/angular-ui/bootstrap/issues/4316) [#4314](https://github.com/angular-ui/bootstrap/issues/4314)
@@ -158,7 +653,7 @@
* **typeahead:** release references on destruction ([695db9d](https://github.com/angular-ui/bootstrap/commit/695db9d)), closes [#4299](https://github.com/angular-ui/bootstrap/issues/4299) [#4298](https://github.com/angular-ui/bootstrap/issues/4298)
* **typeahead:** use ng-bind-html ([bb9fa1a](https://github.com/angular-ui/bootstrap/commit/bb9fa1a)), closes [#3463](https://github.com/angular-ui/bootstrap/issues/3463) [#4073](https://github.com/angular-ui/bootstrap/issues/4073)
-### Features
+## Features
* **accordion:** allow custom panel class ([5ee23a4](https://github.com/angular-ui/bootstrap/commit/5ee23a4)), closes [#4242](https://github.com/angular-ui/bootstrap/issues/4242) [#3968](https://github.com/angular-ui/bootstrap/issues/3968)
* **accordion:** support spacebar to toggle group ([aa5a991](https://github.com/angular-ui/bootstrap/commit/aa5a991)), closes [#4319](https://github.com/angular-ui/bootstrap/issues/4319) [#4249](https://github.com/angular-ui/bootstrap/issues/4249)
@@ -178,7 +673,7 @@
* **typeahead:** add custom popup template support ([4b02648](https://github.com/angular-ui/bootstrap/commit/4b02648)), closes [#4320](https://github.com/angular-ui/bootstrap/issues/4320) [#3774](https://github.com/angular-ui/bootstrap/issues/3774)
-### Breaking Changes
+## Breaking Changes
* **buttons**
* hide nested `` elements on `btn-radio` and `btn-checkbox` directives.
@@ -219,10 +714,10 @@
-### 0.13.3 (2015-08-09)
+# 0.13.3 (2015-08-09)
-#### Bug Fixes
+## Bug Fixes
* **accordion:**
* add `open` class when expanded ([ead15e37](https://github.com/angular-ui/bootstrap/commit/ead15e37), closes [#4152](https://github.com/angular-ui/bootstrap/issues/4152), [#3419](https://github.com/angular-ui/bootstrap/issues/3419))
@@ -251,7 +746,7 @@
* **typeahead:** return `null` if empty ([c7d3a660](https://github.com/angular-ui/bootstrap/commit/c7d3a660), closes [#4078](https://github.com/angular-ui/bootstrap/issues/4078), [#3176](https://github.com/angular-ui/bootstrap/issues/3176))
-#### Features
+## Features
* **accordion:**
* add `controllerAs` support ([9865ee8e](https://github.com/angular-ui/bootstrap/commit/9865ee8e), closes [#4138](https://github.com/angular-ui/bootstrap/issues/4138))
@@ -283,7 +778,7 @@
* add multiple trigger support ([ca9196fa](https://github.com/angular-ui/bootstrap/commit/ca9196fa), closes [#3987](https://github.com/angular-ui/bootstrap/issues/3987), [#4077](https://github.com/angular-ui/bootstrap/issues/4077))
-#### Breaking Changes
+## Breaking Changes
* add `open` class to accordion group when expanded
@@ -306,10 +801,10 @@ Closes #4080
-### 0.13.2 (2015-08-02)
+# 0.13.2 (2015-08-02)
-#### Bug Fixes
+## Bug Fixes
* **accordion:** apply disabled style to accordion-header ([0643fd3e](https://github.com/angular-ui/bootstrap/commit/0643fd3e), closes [#3599](https://github.com/angular-ui/bootstrap/issues/3599), [#3233](https://github.com/angular-ui/bootstrap/issues/3233))
* **buttons:** respect disabled attribute ([42e1af5c](https://github.com/angular-ui/bootstrap/commit/42e1af5c), closes [#4026](https://github.com/angular-ui/bootstrap/issues/4026), [#4013](https://github.com/angular-ui/bootstrap/issues/4013))
@@ -340,7 +835,7 @@ Closes #4080
* only reset matches if matches are present ([97e077e1](https://github.com/angular-ui/bootstrap/commit/97e077e1), closes [#3119](https://github.com/angular-ui/bootstrap/issues/3119))
-#### Features
+## Features
* **build:** add support for npm publishing ([27f7ca26](https://github.com/angular-ui/bootstrap/commit/27f7ca26), closes [#3108](https://github.com/angular-ui/bootstrap/issues/3108))
* **modal:** trap focus in modal for tabbing ([a028d2aa](https://github.com/angular-ui/bootstrap/commit/a028d2aa), closes [#3689](https://github.com/angular-ui/bootstrap/issues/3689), [#4004](https://github.com/angular-ui/bootstrap/issues/4004), [#738](https://github.com/angular-ui/bootstrap/issues/738))
@@ -352,10 +847,10 @@ Closes #4080
-### 0.13.1 (2015-07-23)
+# 0.13.1 (2015-07-23)
-#### Bug Fixes
+## Bug Fixes
* **accordion:** add CSP compliance for accordion & typeahead ([fb302c60](https://github.com/angular-ui/bootstrap/commit/fb302c60), closes [#3909](https://github.com/angular-ui/bootstrap/issues/3909), [#3904](https://github.com/angular-ui/bootstrap/issues/3904))
* **alert:**
@@ -393,7 +888,7 @@ Closes #4080
* add href to show cursor as pointer ([195e520e](https://github.com/angular-ui/bootstrap/commit/195e520e), closes [#3649](https://github.com/angular-ui/bootstrap/issues/3649))
-#### Features
+## Features
* **alert:** pass $event to close() ([44e06425](https://github.com/angular-ui/bootstrap/commit/44e06425), closes [#3828](https://github.com/angular-ui/bootstrap/issues/3828), [#3827](https://github.com/angular-ui/bootstrap/issues/3827))
* **carousel:** add `noWrap` option to prevent re-cycling of slides ([7fb3840f](https://github.com/angular-ui/bootstrap/commit/7fb3840f), closes [#3462](https://github.com/angular-ui/bootstrap/issues/3462), [#3397](https://github.com/angular-ui/bootstrap/issues/3397))
@@ -413,10 +908,10 @@ Closes #4080
-## 0.13.0 (2015-05-02)
+# 0.13.0 (2015-05-02)
-#### Bug Fixes
+## Bug Fixes
* **accordion:**
* Made accordion heading tab-able for IE9-10 ([6abad509](https://github.com/angular-ui/bootstrap/commit/6abad509cd4d44c3ca432f2f21c9ecea0a206b53))
@@ -477,7 +972,7 @@ Closes #4080
* $compile match template after adding to DOM ([03446c56](https://github.com/angular-ui/bootstrap/commit/03446c56335d5ee0970f9730af215fea1dd53f48))
-#### Features
+## Features
* **dateparser:**
* Add support for HH, H, mm, m, ss, s formats ([971a1b57](https://github.com/angular-ui/bootstrap/commit/971a1b57394c1e1088564e0809c1341620586aa0), closes [#2509](https://github.com/angular-ui/bootstrap/issues/2509), [#3159](https://github.com/angular-ui/bootstrap/issues/3159), [#3417](https://github.com/angular-ui/bootstrap/issues/3417))
@@ -516,8 +1011,8 @@ Closes #4080
## Bug Fixes
-- **tooltip:**
- - incorrect position when text wraps ([5726e3ef](http://github.com/angular-ui/bootstrap/commit/5726e3ef))
+- **tooltip:**
+ - incorrect position when text wraps ([5726e3ef](http://github.com/angular-ui/bootstrap/commit/5726e3ef))
# 0.12.0 (2014-11-16)
@@ -557,7 +1052,7 @@ Closes #4080
* `tooltip-trigger` and `popover-trigger` are no longer watched
attributes.
-([a65bea95](http://github.com/angular-ui/bootstrap/commit/a65bea95338802b026fd213805b095b5a0b5b393))
+([a65bea95](http://github.com/angular-ui/bootstrap/commit/a65bea95338802b026fd213805b095b5a0b5b393))
This affects both popovers and tooltips. The *triggers are now set up
once* and can no longer be changed after initialization.
@@ -581,125 +1076,125 @@ Revert breaking change in **dropdown** ([1a998c4](http://github.com/angular-ui/b
## Features
-- **modal:**
- - add backdropClass option, similar to windowClass option ([353e6127](http://github.com/angular-ui/bootstrap/commit/353e6127))
- - support alternative controllerAs syntax ([8d7c2a26](http://github.com/angular-ui/bootstrap/commit/8d7c2a26))
- - allow templateUrl to be a function ([990015fb](http://github.com/angular-ui/bootstrap/commit/990015fb))
+- **modal:**
+ - add backdropClass option, similar to windowClass option ([353e6127](http://github.com/angular-ui/bootstrap/commit/353e6127))
+ - support alternative controllerAs syntax ([8d7c2a26](http://github.com/angular-ui/bootstrap/commit/8d7c2a26))
+ - allow templateUrl to be a function ([990015fb](http://github.com/angular-ui/bootstrap/commit/990015fb))
## Bug Fixes
-- **alert:**
- - correct binding of alert type class ([aa188aec](http://github.com/angular-ui/bootstrap/commit/aa188aec))
-- **dateparser:**
- - do not parse if no format specified ([42cc3f26](http://github.com/angular-ui/bootstrap/commit/42cc3f26))
-- **datepicker:**
- - correct `datepicker-mode` binding for popup ([63ae06c9](http://github.com/angular-ui/bootstrap/commit/63ae06c9))
- - memory leak fix for datepicker ([08c150e1](http://github.com/angular-ui/bootstrap/commit/08c150e1))
-- **dropdown:**
- - close after selecting an item ([3ac3b487](http://github.com/angular-ui/bootstrap/commit/3ac3b487))
- - remove `C` restrictions to avoid conflicts ([7512b93f](http://github.com/angular-ui/bootstrap/commit/7512b93f))
-- **modal:**
- - allow modal.{dismiss,close} to be called again ([1590920c](http://github.com/angular-ui/bootstrap/commit/1590920c))
- - add a work-around for transclusion scope ([0b31e865](http://github.com/angular-ui/bootstrap/commit/0b31e865))
- - allow in-lined controller-as controllers ([79105368](http://github.com/angular-ui/bootstrap/commit/79105368))
- - respect autofocus on child elements ([e62ab94a](http://github.com/angular-ui/bootstrap/commit/e62ab94a))
- - controllerAs not checked ([7b7cdf84](http://github.com/angular-ui/bootstrap/commit/7b7cdf84))
-- **tabs:**
- - remove leading newline from a template ([a708fe6d](http://github.com/angular-ui/bootstrap/commit/a708fe6d))
-- **typeahead:**
- - timeout cancellation when deleting characters ([5dc57927](http://github.com/angular-ui/bootstrap/commit/5dc57927))
- - 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))
+- **alert:**
+ - correct binding of alert type class ([aa188aec](http://github.com/angular-ui/bootstrap/commit/aa188aec))
+- **dateparser:**
+ - do not parse if no format specified ([42cc3f26](http://github.com/angular-ui/bootstrap/commit/42cc3f26))
+- **datepicker:**
+ - correct `datepicker-mode` binding for popup ([63ae06c9](http://github.com/angular-ui/bootstrap/commit/63ae06c9))
+ - memory leak fix for datepicker ([08c150e1](http://github.com/angular-ui/bootstrap/commit/08c150e1))
+- **dropdown:**
+ - close after selecting an item ([3ac3b487](http://github.com/angular-ui/bootstrap/commit/3ac3b487))
+ - remove `C` restrictions to avoid conflicts ([7512b93f](http://github.com/angular-ui/bootstrap/commit/7512b93f))
+- **modal:**
+ - allow modal.{dismiss,close} to be called again ([1590920c](http://github.com/angular-ui/bootstrap/commit/1590920c))
+ - add a work-around for transclusion scope ([0b31e865](http://github.com/angular-ui/bootstrap/commit/0b31e865))
+ - allow in-lined controller-as controllers ([79105368](http://github.com/angular-ui/bootstrap/commit/79105368))
+ - respect autofocus on child elements ([e62ab94a](http://github.com/angular-ui/bootstrap/commit/e62ab94a))
+ - controllerAs not checked ([7b7cdf84](http://github.com/angular-ui/bootstrap/commit/7b7cdf84))
+- **tabs:**
+ - remove leading newline from a template ([a708fe6d](http://github.com/angular-ui/bootstrap/commit/a708fe6d))
+- **typeahead:**
+ - timeout cancellation when deleting characters ([5dc57927](http://github.com/angular-ui/bootstrap/commit/5dc57927))
+ - 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)
## Features
-- **accordion:**
- - support `is-disabled` state ([9c43ae7c](http://github.com/angular-ui/bootstrap/commit/9c43ae7c))
-- **alert:**
- - add WAI-ARIA markup ([9a2638bf](http://github.com/angular-ui/bootstrap/commit/9a2638bf))
-- **button:**
- - allow uncheckable radio button ([82df4fb1](http://github.com/angular-ui/bootstrap/commit/82df4fb1))
-- **carousel:**
- - Support swipe for touchscreen devices ([85140f84](http://github.com/angular-ui/bootstrap/commit/85140f84))
-- **dateParser:**
- - add `dateParser` service ([bd2ae0ee](http://github.com/angular-ui/bootstrap/commit/bd2ae0ee))
-- **datepicker:**
- - add `datepicker-mode`, `init-date` & today hint ([7f4b40eb](http://github.com/angular-ui/bootstrap/commit/7f4b40eb))
- - make widget accessible ([2423f6d4](http://github.com/angular-ui/bootstrap/commit/2423f6d4))
- - full six-week calendar ([b0b14343](http://github.com/angular-ui/bootstrap/commit/b0b14343))
-- **dropdown:**
- - add WAI-ARIA attributes ([22ebd230](http://github.com/angular-ui/bootstrap/commit/22ebd230))
- - focus toggle element when opening or closing with Esc` ([f715d052](http://github.com/angular-ui/bootstrap/commit/f715d052))
-- **dropdownToggle:**
- - support programmatic trigger & toggle callback ([ae31079c](http://github.com/angular-ui/bootstrap/commit/ae31079c))
- - add support for `escape` key ([1417c548](http://github.com/angular-ui/bootstrap/commit/1417c548))
-- **modal:**
- - support custom template for modal window ([96def3d6](http://github.com/angular-ui/bootstrap/commit/96def3d6))
- - support modal window sizes ([976f6083](http://github.com/angular-ui/bootstrap/commit/976f6083))
- - improve accessibility - add role='dialog' ([60cee9dc](http://github.com/angular-ui/bootstrap/commit/60cee9dc))
-- **pagination:**
- - plug into `ngModel` controller ([d65901cf](http://github.com/angular-ui/bootstrap/commit/d65901cf))
-- **progressbar:**
- - make widget accessible ([9dfe3157](http://github.com/angular-ui/bootstrap/commit/9dfe3157))
-- **rating:**
- - plug into `ngModel` controller ([47e227f6](http://github.com/angular-ui/bootstrap/commit/47e227f6))
- - make widget accessible ([4f56e60e](http://github.com/angular-ui/bootstrap/commit/4f56e60e))
-- **tooltip:**
- - support more positioning options ([3704db9a](http://github.com/angular-ui/bootstrap/commit/3704db9a))
-- **typeahead:**
- - add WAI-ARIA markup ([5ca23e97](http://github.com/angular-ui/bootstrap/commit/5ca23e97))
- - add `aria-owns` & `aria-activedescendant` roles ([4c76a858](http://github.com/angular-ui/bootstrap/commit/4c76a858))
+- **accordion:**
+ - support `is-disabled` state ([9c43ae7c](http://github.com/angular-ui/bootstrap/commit/9c43ae7c))
+- **alert:**
+ - add WAI-ARIA markup ([9a2638bf](http://github.com/angular-ui/bootstrap/commit/9a2638bf))
+- **button:**
+ - allow uncheckable radio button ([82df4fb1](http://github.com/angular-ui/bootstrap/commit/82df4fb1))
+- **carousel:**
+ - Support swipe for touchscreen devices ([85140f84](http://github.com/angular-ui/bootstrap/commit/85140f84))
+- **dateParser:**
+ - add `dateParser` service ([bd2ae0ee](http://github.com/angular-ui/bootstrap/commit/bd2ae0ee))
+- **datepicker:**
+ - add `datepicker-mode`, `init-date` & today hint ([7f4b40eb](http://github.com/angular-ui/bootstrap/commit/7f4b40eb))
+ - make widget accessible ([2423f6d4](http://github.com/angular-ui/bootstrap/commit/2423f6d4))
+ - full six-week calendar ([b0b14343](http://github.com/angular-ui/bootstrap/commit/b0b14343))
+- **dropdown:**
+ - add WAI-ARIA attributes ([22ebd230](http://github.com/angular-ui/bootstrap/commit/22ebd230))
+ - focus toggle element when opening or closing with Esc` ([f715d052](http://github.com/angular-ui/bootstrap/commit/f715d052))
+- **dropdownToggle:**
+ - support programmatic trigger & toggle callback ([ae31079c](http://github.com/angular-ui/bootstrap/commit/ae31079c))
+ - add support for `escape` key ([1417c548](http://github.com/angular-ui/bootstrap/commit/1417c548))
+- **modal:**
+ - support custom template for modal window ([96def3d6](http://github.com/angular-ui/bootstrap/commit/96def3d6))
+ - support modal window sizes ([976f6083](http://github.com/angular-ui/bootstrap/commit/976f6083))
+ - improve accessibility - add role='dialog' ([60cee9dc](http://github.com/angular-ui/bootstrap/commit/60cee9dc))
+- **pagination:**
+ - plug into `ngModel` controller ([d65901cf](http://github.com/angular-ui/bootstrap/commit/d65901cf))
+- **progressbar:**
+ - make widget accessible ([9dfe3157](http://github.com/angular-ui/bootstrap/commit/9dfe3157))
+- **rating:**
+ - plug into `ngModel` controller ([47e227f6](http://github.com/angular-ui/bootstrap/commit/47e227f6))
+ - make widget accessible ([4f56e60e](http://github.com/angular-ui/bootstrap/commit/4f56e60e))
+- **tooltip:**
+ - support more positioning options ([3704db9a](http://github.com/angular-ui/bootstrap/commit/3704db9a))
+- **typeahead:**
+ - add WAI-ARIA markup ([5ca23e97](http://github.com/angular-ui/bootstrap/commit/5ca23e97))
+ - add `aria-owns` & `aria-activedescendant` roles ([4c76a858](http://github.com/angular-ui/bootstrap/commit/4c76a858))
## Bug Fixes
-- **alert:**
- - use interpolation for type attribute ([f0a129ad](http://github.com/angular-ui/bootstrap/commit/f0a129ad))
- - add `alert-dismissable` class ([794954af](http://github.com/angular-ui/bootstrap/commit/794954af))
-- **carousel:**
- - correct glyphicon ([3b6ab25b](http://github.com/angular-ui/bootstrap/commit/3b6ab25b))
-- **datepicker:**
- - remove unneeded date creation ([68cb2e5a](http://github.com/angular-ui/bootstrap/commit/68cb2e5a))
- - `Today` button should not set time ([e1993491](http://github.com/angular-ui/bootstrap/commit/e1993491))
- - mark input field as invalid if the date is invalid ([467dd159](http://github.com/angular-ui/bootstrap/commit/467dd159))
- - rename `dateFormat` to `datepickerPopup` in datepickerPopupConfig ([93da30d5](http://github.com/angular-ui/bootstrap/commit/93da30d5))
- - parse input using dateParser ([e0eb1bce](http://github.com/angular-ui/bootstrap/commit/e0eb1bce))
+- **alert:**
+ - use interpolation for type attribute ([f0a129ad](http://github.com/angular-ui/bootstrap/commit/f0a129ad))
+ - add `alert-dismissable` class ([794954af](http://github.com/angular-ui/bootstrap/commit/794954af))
+- **carousel:**
+ - correct glyphicon ([3b6ab25b](http://github.com/angular-ui/bootstrap/commit/3b6ab25b))
+- **datepicker:**
+ - remove unneeded date creation ([68cb2e5a](http://github.com/angular-ui/bootstrap/commit/68cb2e5a))
+ - `Today` button should not set time ([e1993491](http://github.com/angular-ui/bootstrap/commit/e1993491))
+ - mark input field as invalid if the date is invalid ([467dd159](http://github.com/angular-ui/bootstrap/commit/467dd159))
+ - rename `dateFormat` to `datepickerPopup` in datepickerPopupConfig ([93da30d5](http://github.com/angular-ui/bootstrap/commit/93da30d5))
+ - parse input using dateParser ([e0eb1bce](http://github.com/angular-ui/bootstrap/commit/e0eb1bce))
- **dropdown:**
- - use $animate for adding and removing classes ([e8d5fefc](http://github.com/angular-ui/bootstrap/commit/e8d5fefc))
- - unbind toggle element event on scope destroy ([890e2d37](http://github.com/angular-ui/bootstrap/commit/890e2d37))
- - do not call `on-toggle` initially ([004dd1de](http://github.com/angular-ui/bootstrap/commit/004dd1de))
- - ensure `on-toggle` works when `is-open` is not used ([06ad3bd5](http://github.com/angular-ui/bootstrap/commit/06ad3bd5))
+ - use $animate for adding and removing classes ([e8d5fefc](http://github.com/angular-ui/bootstrap/commit/e8d5fefc))
+ - unbind toggle element event on scope destroy ([890e2d37](http://github.com/angular-ui/bootstrap/commit/890e2d37))
+ - do not call `on-toggle` initially ([004dd1de](http://github.com/angular-ui/bootstrap/commit/004dd1de))
+ - ensure `on-toggle` works when `is-open` is not used ([06ad3bd5](http://github.com/angular-ui/bootstrap/commit/06ad3bd5))
- **modal:**
- - destroy modal scope after animation end ([dfc36fd9](http://github.com/angular-ui/bootstrap/commit/dfc36fd9))
- - backdrop z-index when stacking modals ([94a7f593](http://github.com/angular-ui/bootstrap/commit/94a7f593))
- - give a reason of rejection when escape key pressed ([cb31b875](http://github.com/angular-ui/bootstrap/commit/cb31b875))
+ - destroy modal scope after animation end ([dfc36fd9](http://github.com/angular-ui/bootstrap/commit/dfc36fd9))
+ - backdrop z-index when stacking modals ([94a7f593](http://github.com/angular-ui/bootstrap/commit/94a7f593))
+ - give a reason of rejection when escape key pressed ([cb31b875](http://github.com/angular-ui/bootstrap/commit/cb31b875))
- prevent default event when closing via escape key ([da951222](http://github.com/angular-ui/bootstrap/commit/da951222))
- toggle 'modal-open' class after animation ([4d641ca7](http://github.com/angular-ui/bootstrap/commit/4d641ca7))
-- **pagination:**
- - take maxSize defaults into account ([a294c87f](http://github.com/angular-ui/bootstrap/commit/a294c87f))
-- **position:**
- - remove deprecated body scrollTop and scrollLeft ([1ba07c1b](http://github.com/angular-ui/bootstrap/commit/1ba07c1b))
-- **progressbar:**
- - allow fractional values for bar width ([0daa7a74](http://github.com/angular-ui/bootstrap/commit/0daa7a74))
- - number filter in bar template and only for percent ([378a9337](http://github.com/angular-ui/bootstrap/commit/378a9337))
-- **tabs:**
- - fire deselect before select callback ([7474c47b](http://github.com/angular-ui/bootstrap/commit/7474c47b))
- - use interpolation for type attribute ([83ceb78a](http://github.com/angular-ui/bootstrap/commit/83ceb78a))
- - remove `tabbable` class required for left/right tabs ([19468331](http://github.com/angular-ui/bootstrap/commit/19468331))
-- **timepicker:**
- - evaluate correctly the `readonly-input` attribute ([f9b6c496](http://github.com/angular-ui/bootstrap/commit/f9b6c496))
-- **tooltip:**
- - animation causes tooltip to hide on show ([2b429f5d](http://github.com/angular-ui/bootstrap/commit/2b429f5d))
-- **typeahead:**
- - correctly handle append to body attribute ([10785736](http://github.com/angular-ui/bootstrap/commit/10785736))
- - correctly higlight numeric matches ([09678b12](http://github.com/angular-ui/bootstrap/commit/09678b12))
- - loading callback updates after blur ([6a830116](http://github.com/angular-ui/bootstrap/commit/6a830116))
- - incompatibility with ng-focus ([d0024931](http://github.com/angular-ui/bootstrap/commit/d0024931))
+- **pagination:**
+ - take maxSize defaults into account ([a294c87f](http://github.com/angular-ui/bootstrap/commit/a294c87f))
+- **position:**
+ - remove deprecated body scrollTop and scrollLeft ([1ba07c1b](http://github.com/angular-ui/bootstrap/commit/1ba07c1b))
+- **progressbar:**
+ - allow fractional values for bar width ([0daa7a74](http://github.com/angular-ui/bootstrap/commit/0daa7a74))
+ - number filter in bar template and only for percent ([378a9337](http://github.com/angular-ui/bootstrap/commit/378a9337))
+- **tabs:**
+ - fire deselect before select callback ([7474c47b](http://github.com/angular-ui/bootstrap/commit/7474c47b))
+ - use interpolation for type attribute ([83ceb78a](http://github.com/angular-ui/bootstrap/commit/83ceb78a))
+ - remove `tabbable` class required for left/right tabs ([19468331](http://github.com/angular-ui/bootstrap/commit/19468331))
+- **timepicker:**
+ - evaluate correctly the `readonly-input` attribute ([f9b6c496](http://github.com/angular-ui/bootstrap/commit/f9b6c496))
+- **tooltip:**
+ - animation causes tooltip to hide on show ([2b429f5d](http://github.com/angular-ui/bootstrap/commit/2b429f5d))
+- **typeahead:**
+ - correctly handle append to body attribute ([10785736](http://github.com/angular-ui/bootstrap/commit/10785736))
+ - correctly higlight numeric matches ([09678b12](http://github.com/angular-ui/bootstrap/commit/09678b12))
+ - loading callback updates after blur ([6a830116](http://github.com/angular-ui/bootstrap/commit/6a830116))
+ - incompatibility with ng-focus ([d0024931](http://github.com/angular-ui/bootstrap/commit/d0024931))
## Breaking Changes
-- **alert:**
+- **alert:**
Use interpolation for type attribute.
Before:
@@ -722,13 +1217,13 @@ Revert breaking change in **dropdown** ([1a998c4](http://github.com/angular-ui/b
+ *
+ */
+ scrollbarPadding: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var elemStyle = $window.getComputedStyle(elem);
+ 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));
+
+ return {
+ scrollbarWidth: scrollbarWidth,
+ widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,
+ right: paddingRight + scrollbarWidth,
+ originalRight: paddingRight,
+ heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,
+ bottom: paddingBottom + scrollbarWidth,
+ originalBottom: paddingBottom
+ };
+ },
+
+ /**
+ * Checks to see if the element is scrollable.
+ *
+ * @param {element} elem - The element to check.
+ * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
+ * default is false.
+ *
+ * @returns {boolean} Whether the element is scrollable.
+ */
+ isScrollable: function(elem, includeHidden) {
+ elem = this.getRawNode(elem);
+
+ var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
+ var elemStyle = $window.getComputedStyle(elem);
+ return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);
+ },
+
+ /**
+ * Provides the closest scrollable ancestor.
+ * A port of the jQuery UI scrollParent method:
+ * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
+ *
+ * @param {element} elem - The element to find the scroll parent of.
+ * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
+ * default is false.
+ * @param {boolean=} [includeSelf=false] - Should the element being passed be
+ * included in the scrollable llokup.
+ *
+ * @returns {element} A HTML element.
+ */
+ scrollParent: function(elem, includeHidden, includeSelf) {
+ elem = this.getRawNode(elem);
+
+ var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
+ var documentEl = $document[0].documentElement;
+ var elemStyle = $window.getComputedStyle(elem);
+ if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
+ return elem;
+ }
+ var excludeStatic = elemStyle.position === 'absolute';
+ var scrollParent = elem.parentElement || documentEl;
+
+ if (scrollParent === documentEl || elemStyle.position === 'fixed') {
+ return documentEl;
+ }
+
+ while (scrollParent.parentElement && scrollParent !== documentEl) {
+ var spStyle = $window.getComputedStyle(scrollParent);
+ if (excludeStatic && spStyle.position !== 'static') {
+ excludeStatic = false;
+ }
+
+ if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
+ break;
+ }
+ scrollParent = scrollParent.parentElement;
+ }
+
+ return scrollParent;
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's position function:
+ * http://api.jquery.com/position/ - distance to closest positioned
+ * ancestor. Does not account for margins by default like jQuery position.
+ *
+ * @param {element} elem - The element to caclulate the position on.
+ * @param {boolean=} [includeMargins=false] - Should margins be accounted
+ * for, default is false.
+ *
+ * @returns {object} An object with the following properties:
+ *
+ *
+ */
+ position: function(elem, includeMagins) {
+ elem = this.getRawNode(elem);
+
+ var elemOffset = this.offset(elem);
+ if (includeMagins) {
+ var elemStyle = $window.getComputedStyle(elem);
+ elemOffset.top -= this.parseStyle(elemStyle.marginTop);
+ elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
+ }
+ var parent = this.offsetParent(elem);
+ var parentOffset = {top: 0, left: 0};
+
+ if (parent !== $document[0].documentElement) {
+ parentOffset = this.offset(parent);
+ parentOffset.top += parent.clientTop - parent.scrollTop;
+ parentOffset.left += parent.clientLeft - parent.scrollLeft;
+ }
+
+ return {
+ width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
+ height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
+ top: Math.round(elemOffset.top - parentOffset.top),
+ left: Math.round(elemOffset.left - parentOffset.left)
+ };
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's offset function:
+ * http://api.jquery.com/offset/ - distance to viewport. Does
+ * not account for borders, margins, or padding on the body
+ * element.
+ *
+ * @param {element} elem - The element to calculate the offset on.
+ *
+ * @returns {object} An object with the following properties:
+ *
+ *
+ */
+ offset: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var elemBCR = elem.getBoundingClientRect();
+ return {
+ width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
+ height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
+ top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
+ left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
+ };
+ },
+
+ /**
+ * Provides offset distance to the closest scrollable ancestor
+ * or viewport. Accounts for border and scrollbar width.
+ *
+ * Right and bottom dimensions represent the distance to the
+ * respective edge of the viewport element. If the element
+ * edge extends beyond the viewport, a negative value will be
+ * reported.
+ *
+ * @param {element} elem - The element to get the viewport offset for.
+ * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
+ * of the first scrollable element, default is false.
+ * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
+ * be accounted for, default is true.
+ *
+ * @returns {object} An object with the following properties:
+ *
+ *
+ */
+ viewportOffset: function(elem, useDocument, includePadding) {
+ elem = this.getRawNode(elem);
+ includePadding = includePadding !== false ? true : false;
+
+ var elemBCR = elem.getBoundingClientRect();
+ var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};
+
+ var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
+ var offsetParentBCR = offsetParent.getBoundingClientRect();
+
+ offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
+ offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
+ if (offsetParent === $document[0].documentElement) {
+ offsetBCR.top += $window.pageYOffset;
+ offsetBCR.left += $window.pageXOffset;
+ }
+ offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
+ offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;
+
+ if (includePadding) {
+ var offsetParentStyle = $window.getComputedStyle(offsetParent);
+ offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
+ offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
+ offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
+ offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
+ }
+
+ return {
+ top: Math.round(elemBCR.top - offsetBCR.top),
+ bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
+ left: Math.round(elemBCR.left - offsetBCR.left),
+ right: Math.round(offsetBCR.right - elemBCR.right)
+ };
+ },
+
+ /**
+ * Provides an array of placement values parsed from a placement string.
+ * Along with the 'auto' indicator, supported placement strings are:
+ *
+ *
+ * A placement string with an 'auto' indicator is expected to be
+ * space separated from the placement, i.e: 'auto bottom-left' If
+ * the primary and secondary placement values do not match 'top,
+ * bottom, left, right' then 'top' will be the primary placement and
+ * 'center' will be the secondary placement. If 'auto' is passed, true
+ * will be returned as the 3rd value of the array.
+ *
+ * @param {string} placement - The placement string to parse.
+ *
+ * @returns {array} An array with the following values
+ *
+ *
+ */
+ parsePlacement: function(placement) {
+ var autoPlace = PLACEMENT_REGEX.auto.test(placement);
+ if (autoPlace) {
+ placement = placement.replace(PLACEMENT_REGEX.auto, '');
+ }
+
+ placement = placement.split('-');
+
+ placement[0] = placement[0] || 'top';
+ if (!PLACEMENT_REGEX.primary.test(placement[0])) {
+ placement[0] = 'top';
+ }
+
+ placement[1] = placement[1] || 'center';
+ if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
+ placement[1] = 'center';
+ }
+
+ if (autoPlace) {
+ placement[2] = true;
+ } else {
+ placement[2] = false;
+ }
+
+ return placement;
+ },
+
+ /**
+ * Provides coordinates for an element to be positioned relative to
+ * another element. Passing 'auto' as part of the placement parameter
+ * will enable smart placement - where the element fits. i.e:
+ * 'auto left-top' will check to see if there is enough space to the left
+ * of the hostElem to fit the targetElem, if not place right (same for secondary
+ * top placement). Available space is calculated using the viewportOffset
+ * function.
+ *
+ * @param {element} hostElem - The element to position against.
+ * @param {element} targetElem - The element to position.
+ * @param {string=} [placement=top] - The placement for the targetElem,
+ * default is 'top'. 'center' is assumed as secondary placement for
+ * 'top', 'left', 'right', and 'bottom' placements. Available placements are:
+ *
+ *
+ * @param {boolean=} [appendToBody=false] - Should the top and left values returned
+ * be calculated from the body element, default is false.
+ *
+ * @returns {object} An object with the following properties:
+ *
+ *
+ */
+ positionElements: function(hostElem, targetElem, placement, appendToBody) {
+ hostElem = this.getRawNode(hostElem);
+ targetElem = this.getRawNode(targetElem);
+
+ // need to read from prop to support tests.
+ var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
+ var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');
+
+ placement = this.parsePlacement(placement);
+
+ var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
+ var targetElemPos = {top: 0, left: 0, placement: ''};
+
+ if (placement[2]) {
+ var viewportOffset = this.viewportOffset(hostElem, appendToBody);
+
+ var targetElemStyle = $window.getComputedStyle(targetElem);
+ var adjustedSize = {
+ width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
+ height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
+ };
+
+ placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
+ placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
+ placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
+ placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
+ placement[0];
+
+ placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
+ placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
+ placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
+ placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
+ placement[1];
+
+ if (placement[1] === 'center') {
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
+ if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
+ placement[1] = 'left';
+ } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
+ placement[1] = 'right';
+ }
+ } else {
+ var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
+ if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
+ placement[1] = 'top';
+ } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
+ placement[1] = 'bottom';
+ }
+ }
+ }
+ }
+
+ switch (placement[0]) {
+ case 'top':
+ targetElemPos.top = hostElemPos.top - targetHeight;
+ break;
+ case 'bottom':
+ targetElemPos.top = hostElemPos.top + hostElemPos.height;
+ break;
+ case 'left':
+ targetElemPos.left = hostElemPos.left - targetWidth;
+ break;
+ case 'right':
+ targetElemPos.left = hostElemPos.left + hostElemPos.width;
+ break;
+ }
+
+ switch (placement[1]) {
+ case 'top':
+ targetElemPos.top = hostElemPos.top;
+ break;
+ case 'bottom':
+ targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
+ break;
+ case 'left':
+ targetElemPos.left = hostElemPos.left;
+ break;
+ case 'right':
+ targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
+ break;
+ case 'center':
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
+ } else {
+ targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
+ }
+ break;
+ }
+
+ targetElemPos.top = Math.round(targetElemPos.top);
+ targetElemPos.left = Math.round(targetElemPos.left);
+ targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];
+
+ return targetElemPos;
+ },
+
+ /**
+ * Provides a way for positioning tooltip & dropdown
+ * arrows when using placement options beyond the standard
+ * left, right, top, or bottom.
+ *
+ * @param {element} elem - The tooltip/dropdown element.
+ * @param {string} placement - The placement for the elem.
+ */
+ positionArrow: function(elem, placement) {
+ elem = this.getRawNode(elem);
+
+ var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');
+ if (!innerElem) {
+ return;
+ }
+
+ var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');
+
+ var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
+ if (!arrowElem) {
+ return;
+ }
+
+ var arrowCss = {
+ top: '',
+ bottom: '',
+ left: '',
+ right: ''
+ };
+
+ placement = this.parsePlacement(placement);
+ if (placement[1] === 'center') {
+ // no adjustment necessary - just reset styles
+ angular.element(arrowElem).css(arrowCss);
+ return;
+ }
+
+ var borderProp = 'border-' + placement[0] + '-width';
+ var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];
+
+ var borderRadiusProp = 'border-';
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ borderRadiusProp += placement[0] + '-' + placement[1];
+ } else {
+ borderRadiusProp += placement[1] + '-' + placement[0];
+ }
+ borderRadiusProp += '-radius';
+ var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];
+
+ switch (placement[0]) {
+ case 'top':
+ arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'bottom':
+ arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'left':
+ arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'right':
+ arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ }
+
+ arrowCss[placement[1]] = borderRadius;
+
+ angular.element(arrowElem).css(arrowCss);
+ }
+ };
+ }]);
+
+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];
+ }
+ }
+ };
+ }
+ };
+ })
+
+/**
+ * Pluggable resolve mechanism for the modal resolve resolution
+ * Supports UI Router's $resolve service
+ */
+ .provider('$uibResolve', function() {
+ var resolve = this;
+ this.resolver = null;
+
+ this.setResolver = function(resolver) {
+ this.resolver = resolver;
+ };
+
+ this.$get = ['$injector', '$q', function($injector, $q) {
+ var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
+ return {
+ resolve: function(invocables, locals, parent, self) {
+ if (resolver) {
+ return resolver.resolve(invocables, locals, parent, self);
+ }
+
+ var promises = [];
+
+ angular.forEach(invocables, function(value) {
+ if (angular.isFunction(value) || angular.isArray(value)) {
+ promises.push($q.resolve($injector.invoke(value)));
+ } else if (angular.isString(value)) {
+ promises.push($q.resolve($injector.get(value)));
+ } else {
+ promises.push($q.resolve(value));
+ }
+ });
+
+ return $q.all(promises).then(function(resolves) {
+ var resolveObj = {};
+ var resolveIter = 0;
+ angular.forEach(invocables, function(value, key) {
+ resolveObj[key] = resolves[resolveIter++];
+ });
+
+ return resolveObj;
+ });
+ }
+ };
+ }];
+ })
+
+/**
+ * A helper directive for the $modal service. It creates a backdrop element.
+ */
+ .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',
+ function($animate, $injector, $modalStack) {
+ return {
+ replace: true,
+ templateUrl: 'uib/template/modal/backdrop.html',
+ compile: function(tElement, tAttrs) {
+ tElement.addClass(tAttrs.backdropClass);
+ return linkFn;
+ }
+ };
+
+ function linkFn(scope, element, attrs) {
+ if (attrs.modalInClass) {
+ $animate.addClass(element, attrs.modalInClass);
+
+ scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
+ var done = setIsAsync();
+ if (scope.modalOptions.animation) {
+ $animate.removeClass(element, attrs.modalInClass).then(done);
+ } else {
+ done();
+ }
+ });
+ }
+ }
+ }])
+
+ .directive('uibModalWindow', ['$uibModalStack', '$q', '$animateCss', '$document',
+ function($modalStack, $q, $animateCss, $document) {
+ return {
+ scope: {
+ index: '@'
+ },
+ replace: true,
+ transclude: true,
+ templateUrl: function(tElement, tAttrs) {
+ return tAttrs.templateUrl || 'uib/template/modal/window.html';
+ },
+ link: function(scope, element, attrs) {
+ element.addClass(attrs.windowClass || '');
+ element.addClass(attrs.windowTopClass || '');
+ scope.size = attrs.size;
+
+ scope.close = function(evt) {
+ var modal = $modalStack.getTop();
+ if (modal && modal.value.backdrop &&
+ modal.value.backdrop !== 'static' &&
+ evt.target === evt.currentTarget) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $modalStack.dismiss(modal.key, 'backdrop click');
+ }
+ };
+
+ // moved from template to fix issue #2280
+ element.on('click', scope.close);
+
+ // This property is only added to the scope for the purpose of detecting when this directive is rendered.
+ // We can detect that by using this property in the template associated with this directive and then use
+ // {@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.
+ var modalRenderDeferObj = $q.defer();
+ // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.
+ // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.
+ attrs.$observe('modalRender', function(value) {
+ if (value === 'true') {
+ modalRenderDeferObj.resolve();
+ }
+ });
+
+ modalRenderDeferObj.promise.then(function() {
+ var animationPromise = null;
+
+ if (attrs.modalInClass) {
+ animationPromise = $animateCss(element, {
+ addClass: attrs.modalInClass
+ }).start();
+
+ scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
+ var done = setIsAsync();
+ $animateCss(element, {
+ removeClass: attrs.modalInClass
+ }).start().then(done);
+ });
+ }
+
+
+ $q.when(animationPromise).then(function() {
+ // Notify {@link $modalStack} that modal is rendered.
+ var modal = $modalStack.getTop();
+ if (modal) {
+ $modalStack.modalRendered(modal.key);
+ }
+
+ /**
+ * 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.
+ */
+ if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
+ var inputWithAutofocus = element[0].querySelector('[autofocus]');
+ /**
+ * Auto-focusing of a freshly-opened modal element causes any child elements
+ * with the autofocus attribute to lose focus. This is an issue on touch
+ * based devices which will show and then hide the onscreen keyboard.
+ * Attempts to refocus the autofocus element via JavaScript will not reopen
+ * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
+ * the modal element if the modal does not contain an autofocus element.
+ */
+ if (inputWithAutofocus) {
+ inputWithAutofocus.focus();
+ } else {
+ element[0].focus();
+ }
+ }
+ });
+ });
+ }
+ };
+ }])
+
+ .directive('uibModalAnimationClass', function() {
+ return {
+ compile: function(tElement, tAttrs) {
+ if (tAttrs.modalAnimation) {
+ tElement.addClass(tAttrs.uibModalAnimationClass);
+ }
+ }
+ };
+ })
+
+ .directive('uibModalTransclude', function() {
+ return {
+ link: function(scope, element, attrs, controller, transclude) {
+ transclude(scope.$parent, function(clone) {
+ element.empty();
+ element.append(clone);
+ });
+ }
+ };
+ })
+
+ .factory('$uibModalStack', ['$animate', '$animateCss', '$document',
+ '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',
+ function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap, $uibPosition) {
+ var OPENED_MODAL_CLASS = 'modal-open';
+
+ var backdropDomEl, backdropScope;
+ var openedWindows = $$stackedMap.createNew();
+ var openedClasses = $$multiMap.createNew();
+ var $modalStack = {
+ NOW_CLOSING_EVENT: 'modal.stack.now-closing'
+ };
+ var topModalIndex = 0;
+ var previousTopOpenedModal = null;
+
+ //Modal focus behavior
+ var tabableSelector = 'a[href], area[href], input:not([disabled]), ' +
+ 'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' +
+ 'iframe, object, embed, *[tabindex], *[contenteditable=true]';
+ var scrollbarPadding;
+
+ function isVisible(element) {
+ return !!(element.offsetWidth ||
+ element.offsetHeight ||
+ element.getClientRects().length);
+ }
+
+ function backdropIndex() {
+ var topBackdropIndex = -1;
+ var opened = openedWindows.keys();
+ for (var i = 0; i < opened.length; i++) {
+ if (openedWindows.get(opened[i]).value.backdrop) {
+ topBackdropIndex = i;
+ }
+ }
+
+ // If any backdrop exist, ensure that it's index is always
+ // right below the top modal
+ if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {
+ topBackdropIndex = topModalIndex;
+ }
+ return topBackdropIndex;
+ }
+
+ $rootScope.$watch(backdropIndex, function(newBackdropIndex) {
+ if (backdropScope) {
+ backdropScope.index = newBackdropIndex;
+ }
+ });
+
+ function removeModalWindow(modalInstance, elementToReceiveFocus) {
+ var modalWindow = openedWindows.get(modalInstance).value;
+ var appendToElement = modalWindow.appendTo;
+
+ //clean up the stack
+ openedWindows.remove(modalInstance);
+ previousTopOpenedModal = openedWindows.top();
+ if (previousTopOpenedModal) {
+ topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);
+ }
+
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
+ var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
+ openedClasses.remove(modalBodyClass, modalInstance);
+ var areAnyOpen = openedClasses.hasKey(modalBodyClass);
+ appendToElement.toggleClass(modalBodyClass, areAnyOpen);
+ if (!areAnyOpen && scrollbarPadding && scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ if (scrollbarPadding.originalRight) {
+ appendToElement.css({paddingRight: scrollbarPadding.originalRight + 'px'});
+ } else {
+ appendToElement.css({paddingRight: ''});
+ }
+ scrollbarPadding = null;
+ }
+ toggleTopWindowClass(true);
+ }, modalWindow.closedDeferred);
+ checkRemoveBackdrop();
+
+ //move focus to specified element if available, or else to body
+ if (elementToReceiveFocus && elementToReceiveFocus.focus) {
+ elementToReceiveFocus.focus();
+ } else if (appendToElement.focus) {
+ appendToElement.focus();
+ }
+ }
+
+ // Add or remove "windowTopClass" from the top window in the stack
+ function toggleTopWindowClass(toggleSwitch) {
+ var modalWindow;
+
+ if (openedWindows.length() > 0) {
+ modalWindow = openedWindows.top().value;
+ modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
+ }
+ }
+
+ function checkRemoveBackdrop() {
+ //remove backdrop if no longer needed
+ if (backdropDomEl && backdropIndex() === -1) {
+ var backdropScopeRef = backdropScope;
+ removeAfterAnimate(backdropDomEl, backdropScope, function() {
+ backdropScopeRef = null;
+ });
+ backdropDomEl = undefined;
+ backdropScope = undefined;
+ }
+ }
+
+ function removeAfterAnimate(domEl, scope, done, closedDeferred) {
+ var asyncDeferred;
+ var asyncPromise = null;
+ var setIsAsync = function() {
+ if (!asyncDeferred) {
+ asyncDeferred = $q.defer();
+ asyncPromise = asyncDeferred.promise;
+ }
+
+ return function asyncDone() {
+ asyncDeferred.resolve();
+ };
+ };
+ scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);
+
+ // Note that it's intentional that asyncPromise might be null.
+ // That's when setIsAsync has not been called during the
+ // NOW_CLOSING_EVENT broadcast.
+ return $q.when(asyncPromise).then(afterAnimating);
+
+ function afterAnimating() {
+ if (afterAnimating.done) {
+ return;
+ }
+ afterAnimating.done = true;
+
+ $animate.leave(domEl).then(function() {
+ domEl.remove();
+ if (closedDeferred) {
+ closedDeferred.resolve();
+ }
+ });
+
+ scope.$destroy();
+ if (done) {
+ done();
+ }
+ }
+ }
+
+ $document.on('keydown', keydownListener);
+
+ $rootScope.$on('$destroy', function() {
+ $document.off('keydown', keydownListener);
+ });
+
+ function keydownListener(evt) {
+ if (evt.isDefaultPrevented()) {
+ return evt;
+ }
+
+ var modal = openedWindows.top();
+ if (modal) {
+ switch (evt.which) {
+ case 27: {
+ if (modal.value.keyboard) {
+ evt.preventDefault();
+ $rootScope.$apply(function() {
+ $modalStack.dismiss(modal.key, 'escape key press');
+ });
+ }
+ break;
+ }
+ case 9: {
+ var list = $modalStack.loadFocusElementList(modal);
+ var focusChanged = false;
+ if (evt.shiftKey) {
+ if ($modalStack.isFocusInFirstItem(evt, list) || $modalStack.isModalFocused(evt, modal)) {
+ focusChanged = $modalStack.focusLastFocusableElement(list);
+ }
+ } else {
+ if ($modalStack.isFocusInLastItem(evt, list)) {
+ focusChanged = $modalStack.focusFirstFocusableElement(list);
+ }
+ }
+
+ if (focusChanged) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ $modalStack.open = function(modalInstance, modal) {
+ var modalOpener = $document[0].activeElement,
+ modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;
+
+ toggleTopWindowClass(false);
+
+ // Store the current top first, to determine what index we ought to use
+ // for the current top modal
+ previousTopOpenedModal = openedWindows.top();
+
+ openedWindows.add(modalInstance, {
+ deferred: modal.deferred,
+ renderDeferred: modal.renderDeferred,
+ closedDeferred: modal.closedDeferred,
+ modalScope: modal.scope,
+ backdrop: modal.backdrop,
+ keyboard: modal.keyboard,
+ openedClass: modal.openedClass,
+ windowTopClass: modal.windowTopClass,
+ animation: modal.animation,
+ appendTo: modal.appendTo
+ });
+
+ openedClasses.put(modalBodyClass, modalInstance);
+
+ var appendToElement = modal.appendTo,
+ currBackdropIndex = backdropIndex();
+
+ if (!appendToElement.length) {
+ throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
+ }
+
+ if (currBackdropIndex >= 0 && !backdropDomEl) {
+ backdropScope = $rootScope.$new(true);
+ backdropScope.modalOptions = modal;
+ backdropScope.index = currBackdropIndex;
+ backdropDomEl = angular.element('');
+ backdropDomEl.attr('backdrop-class', modal.backdropClass);
+ if (modal.animation) {
+ backdropDomEl.attr('modal-animation', 'true');
+ }
+ $compile(backdropDomEl)(backdropScope);
+ $animate.enter(backdropDomEl, appendToElement);
+ scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
+ if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ appendToElement.css({paddingRight: scrollbarPadding.right + 'px'});
+ }
+ }
+
+ // Set the top modal index based on the index of the previous top modal
+ topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
+ var angularDomEl = angular.element('');
+ angularDomEl.attr({
+ 'template-url': modal.windowTemplateUrl,
+ 'window-class': modal.windowClass,
+ 'window-top-class': modal.windowTopClass,
+ 'size': modal.size,
+ 'index': topModalIndex,
+ 'animate': 'animate'
+ }).html(modal.content);
+ if (modal.animation) {
+ angularDomEl.attr('modal-animation', 'true');
+ }
+
+ appendToElement.addClass(modalBodyClass);
+ $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);
+
+ openedWindows.top().value.modalDomEl = angularDomEl;
+ openedWindows.top().value.modalOpener = modalOpener;
+ };
+
+ function broadcastClosing(modalWindow, resultOrReason, closing) {
+ return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
+ }
+
+ $modalStack.close = function(modalInstance, result) {
+ var modalWindow = openedWindows.get(modalInstance);
+ if (modalWindow && broadcastClosing(modalWindow, result, true)) {
+ modalInstance.callCloseFn(result);
+ 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);
+ if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
+ modalInstance.callDismissFn(reason);
+ modalWindow.value.modalScope.$$uibDestructionScheduled = true;
+ modalWindow.value.deferred.reject(reason);
+ removeModalWindow(modalInstance, modalWindow.value.modalOpener);
+ return true;
+ }
+ return !modalWindow;
+ };
+
+ $modalStack.dismissAll = function(reason) {
+ var topModal = this.getTop();
+ while (topModal && this.dismiss(topModal.key, reason)) {
+ topModal = this.getTop();
+ }
+ };
+
+ $modalStack.getTop = function() {
+ return openedWindows.top();
+ };
+
+ $modalStack.modalRendered = function(modalInstance) {
+ var modalWindow = openedWindows.get(modalInstance);
+ if (modalWindow) {
+ modalWindow.value.renderDeferred.resolve();
+ }
+ };
+
+ $modalStack.focusFirstFocusableElement = function(list) {
+ if (list.length > 0) {
+ list[0].focus();
+ return true;
+ }
+ return false;
+ };
+
+ $modalStack.focusLastFocusableElement = function(list) {
+ if (list.length > 0) {
+ list[list.length - 1].focus();
+ return true;
+ }
+ return false;
+ };
+
+ $modalStack.isModalFocused = function(evt, modalWindow) {
+ if (evt && modalWindow) {
+ var modalDomEl = modalWindow.value.modalDomEl;
+ if (modalDomEl && modalDomEl.length) {
+ return (evt.target || evt.srcElement) === modalDomEl[0];
+ }
+ }
+ return false;
+ };
+
+ $modalStack.isFocusInFirstItem = function(evt, list) {
+ if (list.length > 0) {
+ return (evt.target || evt.srcElement) === list[0];
+ }
+ return false;
+ };
+
+ $modalStack.isFocusInLastItem = function(evt, list) {
+ if (list.length > 0) {
+ return (evt.target || evt.srcElement) === list[list.length - 1];
+ }
+ return false;
+ };
+
+ $modalStack.loadFocusElementList = function(modalWindow) {
+ if (modalWindow) {
+ var modalDomE1 = modalWindow.value.modalDomEl;
+ if (modalDomE1 && modalDomE1.length) {
+ var elements = modalDomE1[0].querySelectorAll(tabableSelector);
+ return elements ?
+ Array.prototype.filter.call(elements, function(element) {
+ return isVisible(element);
+ }) : elements;
+ }
+ }
+ };
+
+ $modalStack.length = function() {
+ return openedWindows.length;
+ };
+
+ return $modalStack;
+ }])
+
+ .provider('$uibModal', function() {
+ var $modalProvider = {
+ options: {
+ animation: true,
+ backdrop: true, //can also be false or 'static'
+ keyboard: true,
+ modalOpenFn: function() {},
+ modalCloseFn: function() {},
+ modalDismissFn: function() {}
+ },
+ $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
+ function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
+ var $modal = {};
+
+ function getTemplatePromise(options) {
+ return options.template ? $q.when(options.template) :
+ $templateRequest(angular.isFunction(options.templateUrl) ?
+ options.templateUrl() : options.templateUrl);
+ }
+
+ var promiseChain = null;
+ $modal.getPromiseChain = function() {
+ return promiseChain;
+ };
+
+ $modal.setCallbacks = function(openFn, closeFn, dismissFn) {
+ angular.extend($modalProvider.options, {
+ modalOpenFn: openFn,
+ modalCloseFn: closeFn,
+ modalDismissFn: dismissFn
+ });
+ };
+
+ $modal.open = function(modalOptions) {
+ var modalResultDeferred = $q.defer();
+ var modalOpenedDeferred = $q.defer();
+ var modalClosedDeferred = $q.defer();
+ var modalRenderDeferred = $q.defer();
+
+ //prepare an instance of a modal to be injected into controllers and returned to a caller
+ var modalInstance = {
+ result: modalResultDeferred.promise,
+ opened: modalOpenedDeferred.promise,
+ closed: modalClosedDeferred.promise,
+ rendered: modalRenderDeferred.promise,
+ close: function (result) {
+ return $modalStack.close(modalInstance, result);
+ },
+ dismiss: function (reason) {
+ return $modalStack.dismiss(modalInstance, reason);
+ },
+ callDismissFn: function(reason) {
+ modalOptions.modalDismissFn(modalOptions, reason);
+ return true;
+ },
+ callCloseFn: function(result) {
+ modalOptions.modalCloseFn(modalOptions, result);
+ return true;
+ }
+ };
+
+ //merge and clean up options
+ modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
+ modalOptions.resolve = modalOptions.resolve || {};
+ modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);
+
+ //verify options
+ if (!modalOptions.template && !modalOptions.templateUrl) {
+ throw new Error('One of template or templateUrl options is required.');
+ }
+
+ var templateAndResolvePromise =
+ $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
+
+ function resolveWithTemplate() {
+ return templateAndResolvePromise;
+ }
+
+ // Wait for the resolution of the existing promise chain.
+ // Then switch to our own combined promise dependency (regardless of how the previous modal fared).
+ // Then add to $modalStack and resolve opened.
+ // Finally clean up the chain variable if no subsequent modal has overwritten it.
+ var samePromise;
+ samePromise = promiseChain = $q.all([promiseChain])
+ .then(resolveWithTemplate, resolveWithTemplate)
+ .then(function resolveSuccess(tplAndVars) {
+ var providedScope = modalOptions.scope || $rootScope;
+
+ var modalScope = providedScope.$new();
+ modalScope.$close = modalInstance.close;
+ modalScope.$dismiss = modalInstance.dismiss;
+
+ modalScope.$on('$destroy', function() {
+ if (!modalScope.$$uibDestructionScheduled) {
+ modalScope.$dismiss('$uibUnscheduledDestruction');
+ }
+ });
+
+ var ctrlInstance, ctrlInstantiate, ctrlLocals = {};
+
+ //controllers
+ if (modalOptions.controller) {
+ ctrlLocals.$scope = modalScope;
+ ctrlLocals.$scope.$resolve = {};
+ ctrlLocals.$uibModalInstance = modalInstance;
+ angular.forEach(tplAndVars[1], function(value, key) {
+ ctrlLocals[key] = value;
+ ctrlLocals.$scope.$resolve[key] = value;
+ });
+
+ // the third param will make the controller instantiate later,private api
+ // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126
+ ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);
+ if (modalOptions.controllerAs && modalOptions.bindToController) {
+ ctrlInstance = ctrlInstantiate.instance;
+ ctrlInstance.$close = modalScope.$close;
+ ctrlInstance.$dismiss = modalScope.$dismiss;
+ angular.extend(ctrlInstance, {
+ $resolve: ctrlLocals.$scope.$resolve
+ }, providedScope);
+ }
+
+ ctrlInstance = ctrlInstantiate();
+
+ if (angular.isFunction(ctrlInstance.$onInit)) {
+ ctrlInstance.$onInit();
+ }
+ }
+
+ $modalStack.open(modalInstance, {
+ scope: modalScope,
+ deferred: modalResultDeferred,
+ renderDeferred: modalRenderDeferred,
+ closedDeferred: modalClosedDeferred,
+ content: tplAndVars[0],
+ animation: modalOptions.animation,
+ backdrop: modalOptions.backdrop,
+ keyboard: modalOptions.keyboard,
+ backdropClass: modalOptions.backdropClass,
+ windowTopClass: modalOptions.windowTopClass,
+ windowClass: modalOptions.windowClass,
+ windowTemplateUrl: modalOptions.windowTemplateUrl,
+ size: modalOptions.size,
+ openedClass: modalOptions.openedClass,
+ appendTo: modalOptions.appendTo
+ });
+
+ modalOptions.modalOpenFn(modalOptions);
+ modalOpenedDeferred.resolve(true);
+
+ }, function resolveError(reason) {
+ modalOpenedDeferred.reject(reason);
+ modalResultDeferred.reject(reason);
+ })['finally'](function() {
+ if (promiseChain === samePromise) {
+ promiseChain = null;
+ }
+ });
+
+ return modalInstance;
+ };
+
+ return $modal;
+ }
+ ]
+ };
+
+ return $modalProvider;
+ });
+
+angular.module('ui.bootstrap.tabs', [])
+
+.controller('UibTabsetController', ['$scope', function ($scope) {
+ var ctrl = this,
+ oldIndex;
+ ctrl.tabs = [];
+
+ ctrl.select = function(index, evt) {
+ if (!destroyed) {
+ var previousIndex = findTabIndex(oldIndex);
+ var previousSelected = ctrl.tabs[previousIndex];
+ if (previousSelected) {
+ previousSelected.tab.onDeselect({
+ $event: evt,
+ $selectedIndex: index
+ });
+ if (evt && evt.isDefaultPrevented()) {
+ return;
+ }
+ previousSelected.tab.active = false;
+ }
+
+ var selected = ctrl.tabs[index];
+ if (selected) {
+ selected.tab.onSelect({
+ $event: evt
+ });
+ selected.tab.active = true;
+ ctrl.active = selected.index;
+ oldIndex = selected.index;
+ } else if (!selected && angular.isDefined(oldIndex)) {
+ ctrl.active = null;
+ oldIndex = null;
+ }
+ }
+ };
+
+ ctrl.addTab = function addTab(tab) {
+ ctrl.tabs.push({
+ tab: tab,
+ index: tab.index
+ });
+ ctrl.tabs.sort(function(t1, t2) {
+ if (t1.index > t2.index) {
+ return 1;
+ }
+
+ if (t1.index < t2.index) {
+ return -1;
+ }
+
+ return 0;
+ });
+
+ if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {
+ var newActiveIndex = findTabIndex(tab.index);
+ ctrl.select(newActiveIndex);
+ }
+ };
+
+ ctrl.removeTab = function removeTab(tab) {
+ var index;
+ for (var i = 0; i < ctrl.tabs.length; i++) {
+ if (ctrl.tabs[i].tab === tab) {
+ index = i;
+ break;
+ }
+ }
+
+ if (ctrl.tabs[index].index === ctrl.active) {
+ var newActiveTabIndex = index === ctrl.tabs.length - 1 ?
+ index - 1 : index + 1 % ctrl.tabs.length;
+ ctrl.select(newActiveTabIndex);
+ }
+
+ ctrl.tabs.splice(index, 1);
+ };
+
+ $scope.$watch('tabset.active', function(val) {
+ if (angular.isDefined(val) && val !== oldIndex) {
+ ctrl.select(findTabIndex(val));
+ }
+ });
+
+ var destroyed;
+ $scope.$on('$destroy', function() {
+ destroyed = true;
+ });
+
+ function findTabIndex(index) {
+ for (var i = 0; i < ctrl.tabs.length; i++) {
+ if (ctrl.tabs[i].index === index) {
+ return i;
+ }
+ }
+ }
+}])
+
+.directive('uibTabset', function() {
+ return {
+ transclude: true,
+ replace: true,
+ scope: {},
+ bindToController: {
+ active: '=?',
+ type: '@'
+ },
+ controller: 'UibTabsetController',
+ controllerAs: 'tabset',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/tabs/tabset.html';
+ },
+ link: function(scope, element, attrs) {
+ scope.vertical = angular.isDefined(attrs.vertical) ?
+ scope.$parent.$eval(attrs.vertical) : false;
+ scope.justified = angular.isDefined(attrs.justified) ?
+ scope.$parent.$eval(attrs.justified) : false;
+ }
+ };
+})
+
+.directive('uibTab', ['$parse', function($parse) {
+ return {
+ require: '^uibTabset',
+ replace: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/tabs/tab.html';
+ },
+ transclude: true,
+ scope: {
+ heading: '@',
+ index: '=?',
+ classes: '@?',
+ onSelect: '&select', //This callback is called in contentHeadingTransclude
+ //once it inserts the tab's content into the dom
+ onDeselect: '&deselect'
+ },
+ controller: function() {
+ //Empty controller so other directives can require being 'under' a tab
+ },
+ controllerAs: 'tab',
+ link: function(scope, elm, attrs, tabsetCtrl, transclude) {
+ scope.disabled = false;
+ if (attrs.disable) {
+ scope.$parent.$watch($parse(attrs.disable), function(value) {
+ scope.disabled = !! value;
+ });
+ }
+
+ if (angular.isUndefined(attrs.index)) {
+ if (tabsetCtrl.tabs && tabsetCtrl.tabs.length) {
+ scope.index = Math.max.apply(null, tabsetCtrl.tabs.map(function(t) { return t.index; })) + 1;
+ } else {
+ scope.index = 0;
+ }
+ }
+
+ if (angular.isUndefined(attrs.classes)) {
+ scope.classes = '';
+ }
+
+ scope.select = function(evt) {
+ if (!scope.disabled) {
+ var index;
+ for (var i = 0; i < tabsetCtrl.tabs.length; i++) {
+ if (tabsetCtrl.tabs[i].tab === scope) {
+ index = i;
+ break;
+ }
+ }
+
+ tabsetCtrl.select(index, evt);
+ }
+ };
+
+ tabsetCtrl.addTab(scope);
+ scope.$on('$destroy', function() {
+ tabsetCtrl.removeTab(scope);
+ });
+
+ //We need to transclude later, once the content container is ready.
+ //when this link happens, we're inside a tab heading.
+ scope.$transcludeFn = transclude;
+ }
+ };
+}])
+
+.directive('uibTabHeadingTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^uibTab',
+ link: function(scope, elm) {
+ scope.$watch('headingElement', function updateHeadingElement(heading) {
+ if (heading) {
+ elm.html('');
+ elm.append(heading);
+ }
+ });
+ }
+ };
+})
+
+.directive('uibTabContentTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^uibTabset',
+ link: function(scope, elm, attrs) {
+ var tab = scope.$eval(attrs.uibTabContentTransclude).tab;
+
+ //Now our tab is ready to be transcluded: both the tab heading area
+ //and the tab content area are loaded. Transclude 'em both.
+ tab.$transcludeFn(tab.$parent, function(contents) {
+ angular.forEach(contents, function(node) {
+ if (isTabHeading(node)) {
+ //Let tabHeadingTransclude know.
+ tab.headingElement = node;
+ } else {
+ elm.append(node);
+ }
+ });
+ });
+ }
+ };
+
+ function isTabHeading(node) {
+ return node.tagName && (
+ node.hasAttribute('uib-tab-heading') ||
+ node.hasAttribute('data-uib-tab-heading') ||
+ node.hasAttribute('x-uib-tab-heading') ||
+ node.tagName.toLowerCase() === 'uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'data-uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'x-uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'uib:tab-heading'
+ );
+ }
+});
+
+/**
+ * The following features are still outstanding: animation as a
+ * function, placement as a function, inside, support for more triggers than
+ * just mouse enter/leave, html tooltips, and selector delegation.
+ */
+angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])
+
+/**
+ * The $tooltip service creates tooltip- and popover-like directives as well as
+ * houses global options for them.
+ */
+.provider('$uibTooltip', function() {
+ // The default options tooltip and popover.
+ var defaultOptions = {
+ placement: 'top',
+ placementClassPrefix: '',
+ animation: true,
+ popupDelay: 0,
+ popupCloseDelay: 0,
+ useContentExp: false
+ };
+
+ // Default hide triggers for each show trigger
+ var triggerMap = {
+ 'mouseenter': 'mouseleave',
+ 'click': 'click',
+ 'outsideClick': 'outsideClick',
+ 'focus': 'blur',
+ 'none': ''
+ };
+
+ // The options specified to the provider globally.
+ var globalOptions = {};
+
+ /**
+ * `options({})` allows global configuration of all tooltips in the
+ * application.
+ *
+ * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
+ * // place tooltips left instead of top by default
+ * $tooltipProvider.options( { placement: 'left' } );
+ * });
+ */
+ this.options = function(value) {
+ angular.extend(globalOptions, value);
+ };
+
+ /**
+ * This allows you to extend the set of trigger mappings available. E.g.:
+ *
+ * $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );
+ */
+ this.setTriggers = function setTriggers(triggers) {
+ angular.extend(triggerMap, triggers);
+ };
+
+ /**
+ * This is a helper function for translating camel-case to snake_case.
+ */
+ function snake_case(name) {
+ var regexp = /[A-Z]/g;
+ var separator = '-';
+ return name.replace(regexp, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+ }
+
+ /**
+ * Returns the actual instance of the $tooltip service.
+ * TODO support multiple triggers
+ */
+ this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
+ var openedTooltips = $$stackedMap.createNew();
+ $document.on('keypress', keypressListener);
+
+ $rootScope.$on('$destroy', function() {
+ $document.off('keypress', keypressListener);
+ });
+
+ function keypressListener(e) {
+ if (e.which === 27) {
+ var last = openedTooltips.top();
+ if (last) {
+ last.value.close();
+ openedTooltips.removeTop();
+ last = null;
+ }
+ }
+ }
+
+ return function $tooltip(ttType, prefix, defaultTriggerShow, options) {
+ options = angular.extend({}, defaultOptions, globalOptions, options);
+
+ /**
+ * Returns an object of show and hide triggers.
+ *
+ * If a trigger is supplied,
+ * it is used to show the tooltip; otherwise, it will use the `trigger`
+ * option passed to the `$tooltipProvider.options` method; else it will
+ * default to the trigger supplied to this directive factory.
+ *
+ * The hide trigger is based on the show trigger. If the `trigger` option
+ * was passed to the `$tooltipProvider.options` method, it will use the
+ * mapped trigger from `triggerMap` or the passed trigger if the map is
+ * undefined; otherwise, it uses the `triggerMap` value of the show
+ * trigger; else it will just use the show trigger.
+ */
+ function getTriggers(trigger) {
+ var show = (trigger || options.trigger || defaultTriggerShow).split(' ');
+ var hide = show.map(function(trigger) {
+ return triggerMap[trigger] || trigger;
+ });
+ return {
+ show: show,
+ hide: hide
+ };
+ }
+
+ var directiveName = snake_case(ttType);
+
+ var startSym = $interpolate.startSymbol();
+ var endSym = $interpolate.endSymbol();
+ var template =
+ 's&&a>A},a.noIncrementMinutes=function(){var a=p(s,y);return B||a>A||as&&a>A},a.noIncrementSeconds=function(){var a=q(s,C);return B||a>A||as&&a>A},a.noToggleMeridian=function(){return s.getHours()<12?B||p(s,720)>A:B||p(s,-720)
+ *
+ */
+ scrollbarPadding: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var elemStyle = $window.getComputedStyle(elem);
+ 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));
+
+ return {
+ scrollbarWidth: scrollbarWidth,
+ widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,
+ right: paddingRight + scrollbarWidth,
+ originalRight: paddingRight,
+ heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,
+ bottom: paddingBottom + scrollbarWidth,
+ originalBottom: paddingBottom
+ };
+ },
+
+ /**
+ * Checks to see if the element is scrollable.
+ *
+ * @param {element} elem - The element to check.
+ * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
+ * default is false.
+ *
+ * @returns {boolean} Whether the element is scrollable.
+ */
+ isScrollable: function(elem, includeHidden) {
+ elem = this.getRawNode(elem);
+
+ var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
+ var elemStyle = $window.getComputedStyle(elem);
+ return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);
+ },
+
+ /**
+ * Provides the closest scrollable ancestor.
+ * A port of the jQuery UI scrollParent method:
+ * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
+ *
+ * @param {element} elem - The element to find the scroll parent of.
+ * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
+ * default is false.
+ * @param {boolean=} [includeSelf=false] - Should the element being passed be
+ * included in the scrollable llokup.
+ *
+ * @returns {element} A HTML element.
+ */
+ scrollParent: function(elem, includeHidden, includeSelf) {
+ elem = this.getRawNode(elem);
+
+ var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
+ var documentEl = $document[0].documentElement;
+ var elemStyle = $window.getComputedStyle(elem);
+ if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
+ return elem;
+ }
+ var excludeStatic = elemStyle.position === 'absolute';
+ var scrollParent = elem.parentElement || documentEl;
+
+ if (scrollParent === documentEl || elemStyle.position === 'fixed') {
+ return documentEl;
+ }
+
+ while (scrollParent.parentElement && scrollParent !== documentEl) {
+ var spStyle = $window.getComputedStyle(scrollParent);
+ if (excludeStatic && spStyle.position !== 'static') {
+ excludeStatic = false;
+ }
+
+ if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
+ break;
+ }
+ scrollParent = scrollParent.parentElement;
+ }
+
+ return scrollParent;
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's position function:
+ * http://api.jquery.com/position/ - distance to closest positioned
+ * ancestor. Does not account for margins by default like jQuery position.
+ *
+ * @param {element} elem - The element to caclulate the position on.
+ * @param {boolean=} [includeMargins=false] - Should margins be accounted
+ * for, default is false.
+ *
+ * @returns {object} An object with the following properties:
+ *
+ *
+ */
+ position: function(elem, includeMagins) {
+ elem = this.getRawNode(elem);
+
+ var elemOffset = this.offset(elem);
+ if (includeMagins) {
+ var elemStyle = $window.getComputedStyle(elem);
+ elemOffset.top -= this.parseStyle(elemStyle.marginTop);
+ elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
+ }
+ var parent = this.offsetParent(elem);
+ var parentOffset = {top: 0, left: 0};
+
+ if (parent !== $document[0].documentElement) {
+ parentOffset = this.offset(parent);
+ parentOffset.top += parent.clientTop - parent.scrollTop;
+ parentOffset.left += parent.clientLeft - parent.scrollLeft;
+ }
+
+ return {
+ width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
+ height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
+ top: Math.round(elemOffset.top - parentOffset.top),
+ left: Math.round(elemOffset.left - parentOffset.left)
+ };
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's offset function:
+ * http://api.jquery.com/offset/ - distance to viewport. Does
+ * not account for borders, margins, or padding on the body
+ * element.
+ *
+ * @param {element} elem - The element to calculate the offset on.
+ *
+ * @returns {object} An object with the following properties:
+ *
+ *
+ */
+ offset: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var elemBCR = elem.getBoundingClientRect();
+ return {
+ width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
+ height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
+ top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
+ left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
+ };
+ },
+
+ /**
+ * Provides offset distance to the closest scrollable ancestor
+ * or viewport. Accounts for border and scrollbar width.
+ *
+ * Right and bottom dimensions represent the distance to the
+ * respective edge of the viewport element. If the element
+ * edge extends beyond the viewport, a negative value will be
+ * reported.
+ *
+ * @param {element} elem - The element to get the viewport offset for.
+ * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
+ * of the first scrollable element, default is false.
+ * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
+ * be accounted for, default is true.
+ *
+ * @returns {object} An object with the following properties:
+ *
+ *
+ */
+ viewportOffset: function(elem, useDocument, includePadding) {
+ elem = this.getRawNode(elem);
+ includePadding = includePadding !== false ? true : false;
+
+ var elemBCR = elem.getBoundingClientRect();
+ var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};
+
+ var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
+ var offsetParentBCR = offsetParent.getBoundingClientRect();
+
+ offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
+ offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
+ if (offsetParent === $document[0].documentElement) {
+ offsetBCR.top += $window.pageYOffset;
+ offsetBCR.left += $window.pageXOffset;
+ }
+ offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
+ offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;
+
+ if (includePadding) {
+ var offsetParentStyle = $window.getComputedStyle(offsetParent);
+ offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
+ offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
+ offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
+ offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
+ }
+
+ return {
+ top: Math.round(elemBCR.top - offsetBCR.top),
+ bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
+ left: Math.round(elemBCR.left - offsetBCR.left),
+ right: Math.round(offsetBCR.right - elemBCR.right)
+ };
+ },
+
+ /**
+ * Provides an array of placement values parsed from a placement string.
+ * Along with the 'auto' indicator, supported placement strings are:
+ *
+ *
+ * A placement string with an 'auto' indicator is expected to be
+ * space separated from the placement, i.e: 'auto bottom-left' If
+ * the primary and secondary placement values do not match 'top,
+ * bottom, left, right' then 'top' will be the primary placement and
+ * 'center' will be the secondary placement. If 'auto' is passed, true
+ * will be returned as the 3rd value of the array.
+ *
+ * @param {string} placement - The placement string to parse.
+ *
+ * @returns {array} An array with the following values
+ *
+ *
+ */
+ parsePlacement: function(placement) {
+ var autoPlace = PLACEMENT_REGEX.auto.test(placement);
+ if (autoPlace) {
+ placement = placement.replace(PLACEMENT_REGEX.auto, '');
+ }
+
+ placement = placement.split('-');
+
+ placement[0] = placement[0] || 'top';
+ if (!PLACEMENT_REGEX.primary.test(placement[0])) {
+ placement[0] = 'top';
+ }
+
+ placement[1] = placement[1] || 'center';
+ if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
+ placement[1] = 'center';
+ }
+
+ if (autoPlace) {
+ placement[2] = true;
+ } else {
+ placement[2] = false;
+ }
+
+ return placement;
+ },
+
+ /**
+ * Provides coordinates for an element to be positioned relative to
+ * another element. Passing 'auto' as part of the placement parameter
+ * will enable smart placement - where the element fits. i.e:
+ * 'auto left-top' will check to see if there is enough space to the left
+ * of the hostElem to fit the targetElem, if not place right (same for secondary
+ * top placement). Available space is calculated using the viewportOffset
+ * function.
+ *
+ * @param {element} hostElem - The element to position against.
+ * @param {element} targetElem - The element to position.
+ * @param {string=} [placement=top] - The placement for the targetElem,
+ * default is 'top'. 'center' is assumed as secondary placement for
+ * 'top', 'left', 'right', and 'bottom' placements. Available placements are:
+ *
+ *
+ * @param {boolean=} [appendToBody=false] - Should the top and left values returned
+ * be calculated from the body element, default is false.
+ *
+ * @returns {object} An object with the following properties:
+ *
+ *
+ */
+ positionElements: function(hostElem, targetElem, placement, appendToBody) {
+ hostElem = this.getRawNode(hostElem);
+ targetElem = this.getRawNode(targetElem);
+
+ // need to read from prop to support tests.
+ var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
+ var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');
+
+ placement = this.parsePlacement(placement);
+
+ var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
+ var targetElemPos = {top: 0, left: 0, placement: ''};
+
+ if (placement[2]) {
+ var viewportOffset = this.viewportOffset(hostElem, appendToBody);
+
+ var targetElemStyle = $window.getComputedStyle(targetElem);
+ var adjustedSize = {
+ width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
+ height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
+ };
+
+ placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
+ placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
+ placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
+ placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
+ placement[0];
+
+ placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
+ placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
+ placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
+ placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
+ placement[1];
+
+ if (placement[1] === 'center') {
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
+ if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
+ placement[1] = 'left';
+ } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
+ placement[1] = 'right';
+ }
+ } else {
+ var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
+ if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
+ placement[1] = 'top';
+ } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
+ placement[1] = 'bottom';
+ }
+ }
+ }
+ }
+
+ switch (placement[0]) {
+ case 'top':
+ targetElemPos.top = hostElemPos.top - targetHeight;
+ break;
+ case 'bottom':
+ targetElemPos.top = hostElemPos.top + hostElemPos.height;
+ break;
+ case 'left':
+ targetElemPos.left = hostElemPos.left - targetWidth;
+ break;
+ case 'right':
+ targetElemPos.left = hostElemPos.left + hostElemPos.width;
+ break;
+ }
+
+ switch (placement[1]) {
+ case 'top':
+ targetElemPos.top = hostElemPos.top;
+ break;
+ case 'bottom':
+ targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
+ break;
+ case 'left':
+ targetElemPos.left = hostElemPos.left;
+ break;
+ case 'right':
+ targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
+ break;
+ case 'center':
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
+ } else {
+ targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
+ }
+ break;
+ }
+
+ targetElemPos.top = Math.round(targetElemPos.top);
+ targetElemPos.left = Math.round(targetElemPos.left);
+ targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];
+
+ return targetElemPos;
+ },
+
+ /**
+ * Provides a way for positioning tooltip & dropdown
+ * arrows when using placement options beyond the standard
+ * left, right, top, or bottom.
+ *
+ * @param {element} elem - The tooltip/dropdown element.
+ * @param {string} placement - The placement for the elem.
+ */
+ positionArrow: function(elem, placement) {
+ elem = this.getRawNode(elem);
+
+ var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');
+ if (!innerElem) {
+ return;
+ }
+
+ var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');
+
+ var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
+ if (!arrowElem) {
+ return;
+ }
+
+ var arrowCss = {
+ top: '',
+ bottom: '',
+ left: '',
+ right: ''
+ };
+
+ placement = this.parsePlacement(placement);
+ if (placement[1] === 'center') {
+ // no adjustment necessary - just reset styles
+ angular.element(arrowElem).css(arrowCss);
+ return;
+ }
+
+ var borderProp = 'border-' + placement[0] + '-width';
+ var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];
+
+ var borderRadiusProp = 'border-';
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ borderRadiusProp += placement[0] + '-' + placement[1];
+ } else {
+ borderRadiusProp += placement[1] + '-' + placement[0];
+ }
+ borderRadiusProp += '-radius';
+ var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];
+
+ switch (placement[0]) {
+ case 'top':
+ arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'bottom':
+ arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'left':
+ arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'right':
+ arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ }
+
+ arrowCss[placement[1]] = borderRadius;
+
+ angular.element(arrowElem).css(arrowCss);
+ }
+ };
+ }]);
+
+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];
+ }
+ }
+ };
+ }
+ };
+ })
+
+/**
+ * Pluggable resolve mechanism for the modal resolve resolution
+ * Supports UI Router's $resolve service
+ */
+ .provider('$uibResolve', function() {
+ var resolve = this;
+ this.resolver = null;
+
+ this.setResolver = function(resolver) {
+ this.resolver = resolver;
+ };
+
+ this.$get = ['$injector', '$q', function($injector, $q) {
+ var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
+ return {
+ resolve: function(invocables, locals, parent, self) {
+ if (resolver) {
+ return resolver.resolve(invocables, locals, parent, self);
+ }
+
+ var promises = [];
+
+ angular.forEach(invocables, function(value) {
+ if (angular.isFunction(value) || angular.isArray(value)) {
+ promises.push($q.resolve($injector.invoke(value)));
+ } else if (angular.isString(value)) {
+ promises.push($q.resolve($injector.get(value)));
+ } else {
+ promises.push($q.resolve(value));
+ }
+ });
+
+ return $q.all(promises).then(function(resolves) {
+ var resolveObj = {};
+ var resolveIter = 0;
+ angular.forEach(invocables, function(value, key) {
+ resolveObj[key] = resolves[resolveIter++];
+ });
+
+ return resolveObj;
+ });
+ }
+ };
+ }];
+ })
+
+/**
+ * A helper directive for the $modal service. It creates a backdrop element.
+ */
+ .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',
+ function($animate, $injector, $modalStack) {
+ return {
+ replace: true,
+ templateUrl: 'uib/template/modal/backdrop.html',
+ compile: function(tElement, tAttrs) {
+ tElement.addClass(tAttrs.backdropClass);
+ return linkFn;
+ }
+ };
+
+ function linkFn(scope, element, attrs) {
+ if (attrs.modalInClass) {
+ $animate.addClass(element, attrs.modalInClass);
+
+ scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
+ var done = setIsAsync();
+ if (scope.modalOptions.animation) {
+ $animate.removeClass(element, attrs.modalInClass).then(done);
+ } else {
+ done();
+ }
+ });
+ }
+ }
+ }])
+
+ .directive('uibModalWindow', ['$uibModalStack', '$q', '$animateCss', '$document',
+ function($modalStack, $q, $animateCss, $document) {
+ return {
+ scope: {
+ index: '@'
+ },
+ replace: true,
+ transclude: true,
+ templateUrl: function(tElement, tAttrs) {
+ return tAttrs.templateUrl || 'uib/template/modal/window.html';
+ },
+ link: function(scope, element, attrs) {
+ element.addClass(attrs.windowClass || '');
+ element.addClass(attrs.windowTopClass || '');
+ scope.size = attrs.size;
+
+ scope.close = function(evt) {
+ var modal = $modalStack.getTop();
+ if (modal && modal.value.backdrop &&
+ modal.value.backdrop !== 'static' &&
+ evt.target === evt.currentTarget) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $modalStack.dismiss(modal.key, 'backdrop click');
+ }
+ };
+
+ // moved from template to fix issue #2280
+ element.on('click', scope.close);
+
+ // This property is only added to the scope for the purpose of detecting when this directive is rendered.
+ // We can detect that by using this property in the template associated with this directive and then use
+ // {@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.
+ var modalRenderDeferObj = $q.defer();
+ // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.
+ // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.
+ attrs.$observe('modalRender', function(value) {
+ if (value === 'true') {
+ modalRenderDeferObj.resolve();
+ }
+ });
+
+ modalRenderDeferObj.promise.then(function() {
+ var animationPromise = null;
+
+ if (attrs.modalInClass) {
+ animationPromise = $animateCss(element, {
+ addClass: attrs.modalInClass
+ }).start();
+
+ scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
+ var done = setIsAsync();
+ $animateCss(element, {
+ removeClass: attrs.modalInClass
+ }).start().then(done);
+ });
+ }
+
+
+ $q.when(animationPromise).then(function() {
+ // Notify {@link $modalStack} that modal is rendered.
+ var modal = $modalStack.getTop();
+ if (modal) {
+ $modalStack.modalRendered(modal.key);
+ }
+
+ /**
+ * 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.
+ */
+ if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
+ var inputWithAutofocus = element[0].querySelector('[autofocus]');
+ /**
+ * Auto-focusing of a freshly-opened modal element causes any child elements
+ * with the autofocus attribute to lose focus. This is an issue on touch
+ * based devices which will show and then hide the onscreen keyboard.
+ * Attempts to refocus the autofocus element via JavaScript will not reopen
+ * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
+ * the modal element if the modal does not contain an autofocus element.
+ */
+ if (inputWithAutofocus) {
+ inputWithAutofocus.focus();
+ } else {
+ element[0].focus();
+ }
+ }
+ });
+ });
+ }
+ };
+ }])
+
+ .directive('uibModalAnimationClass', function() {
+ return {
+ compile: function(tElement, tAttrs) {
+ if (tAttrs.modalAnimation) {
+ tElement.addClass(tAttrs.uibModalAnimationClass);
+ }
+ }
+ };
+ })
+
+ .directive('uibModalTransclude', function() {
+ return {
+ link: function(scope, element, attrs, controller, transclude) {
+ transclude(scope.$parent, function(clone) {
+ element.empty();
+ element.append(clone);
+ });
+ }
+ };
+ })
+
+ .factory('$uibModalStack', ['$animate', '$animateCss', '$document',
+ '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',
+ function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap, $uibPosition) {
+ var OPENED_MODAL_CLASS = 'modal-open';
+
+ var backdropDomEl, backdropScope;
+ var openedWindows = $$stackedMap.createNew();
+ var openedClasses = $$multiMap.createNew();
+ var $modalStack = {
+ NOW_CLOSING_EVENT: 'modal.stack.now-closing'
+ };
+ var topModalIndex = 0;
+ var previousTopOpenedModal = null;
+
+ //Modal focus behavior
+ var tabableSelector = 'a[href], area[href], input:not([disabled]), ' +
+ 'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' +
+ 'iframe, object, embed, *[tabindex], *[contenteditable=true]';
+ var scrollbarPadding;
+
+ function isVisible(element) {
+ return !!(element.offsetWidth ||
+ element.offsetHeight ||
+ element.getClientRects().length);
+ }
+
+ function backdropIndex() {
+ var topBackdropIndex = -1;
+ var opened = openedWindows.keys();
+ for (var i = 0; i < opened.length; i++) {
+ if (openedWindows.get(opened[i]).value.backdrop) {
+ topBackdropIndex = i;
+ }
+ }
+
+ // If any backdrop exist, ensure that it's index is always
+ // right below the top modal
+ if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {
+ topBackdropIndex = topModalIndex;
+ }
+ return topBackdropIndex;
+ }
+
+ $rootScope.$watch(backdropIndex, function(newBackdropIndex) {
+ if (backdropScope) {
+ backdropScope.index = newBackdropIndex;
+ }
+ });
+
+ function removeModalWindow(modalInstance, elementToReceiveFocus) {
+ var modalWindow = openedWindows.get(modalInstance).value;
+ var appendToElement = modalWindow.appendTo;
+
+ //clean up the stack
+ openedWindows.remove(modalInstance);
+ previousTopOpenedModal = openedWindows.top();
+ if (previousTopOpenedModal) {
+ topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);
+ }
+
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
+ var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
+ openedClasses.remove(modalBodyClass, modalInstance);
+ var areAnyOpen = openedClasses.hasKey(modalBodyClass);
+ appendToElement.toggleClass(modalBodyClass, areAnyOpen);
+ if (!areAnyOpen && scrollbarPadding && scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ if (scrollbarPadding.originalRight) {
+ appendToElement.css({paddingRight: scrollbarPadding.originalRight + 'px'});
+ } else {
+ appendToElement.css({paddingRight: ''});
+ }
+ scrollbarPadding = null;
+ }
+ toggleTopWindowClass(true);
+ }, modalWindow.closedDeferred);
+ checkRemoveBackdrop();
+
+ //move focus to specified element if available, or else to body
+ if (elementToReceiveFocus && elementToReceiveFocus.focus) {
+ elementToReceiveFocus.focus();
+ } else if (appendToElement.focus) {
+ appendToElement.focus();
+ }
+ }
+
+ // Add or remove "windowTopClass" from the top window in the stack
+ function toggleTopWindowClass(toggleSwitch) {
+ var modalWindow;
+
+ if (openedWindows.length() > 0) {
+ modalWindow = openedWindows.top().value;
+ modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
+ }
+ }
+
+ function checkRemoveBackdrop() {
+ //remove backdrop if no longer needed
+ if (backdropDomEl && backdropIndex() === -1) {
+ var backdropScopeRef = backdropScope;
+ removeAfterAnimate(backdropDomEl, backdropScope, function() {
+ backdropScopeRef = null;
+ });
+ backdropDomEl = undefined;
+ backdropScope = undefined;
+ }
+ }
+
+ function removeAfterAnimate(domEl, scope, done, closedDeferred) {
+ var asyncDeferred;
+ var asyncPromise = null;
+ var setIsAsync = function() {
+ if (!asyncDeferred) {
+ asyncDeferred = $q.defer();
+ asyncPromise = asyncDeferred.promise;
+ }
+
+ return function asyncDone() {
+ asyncDeferred.resolve();
+ };
+ };
+ scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);
+
+ // Note that it's intentional that asyncPromise might be null.
+ // That's when setIsAsync has not been called during the
+ // NOW_CLOSING_EVENT broadcast.
+ return $q.when(asyncPromise).then(afterAnimating);
+
+ function afterAnimating() {
+ if (afterAnimating.done) {
+ return;
+ }
+ afterAnimating.done = true;
+
+ $animate.leave(domEl).then(function() {
+ domEl.remove();
+ if (closedDeferred) {
+ closedDeferred.resolve();
+ }
+ });
+
+ scope.$destroy();
+ if (done) {
+ done();
+ }
+ }
+ }
+
+ $document.on('keydown', keydownListener);
+
+ $rootScope.$on('$destroy', function() {
+ $document.off('keydown', keydownListener);
+ });
+
+ function keydownListener(evt) {
+ if (evt.isDefaultPrevented()) {
+ return evt;
+ }
+
+ var modal = openedWindows.top();
+ if (modal) {
+ switch (evt.which) {
+ case 27: {
+ if (modal.value.keyboard) {
+ evt.preventDefault();
+ $rootScope.$apply(function() {
+ $modalStack.dismiss(modal.key, 'escape key press');
+ });
+ }
+ break;
+ }
+ case 9: {
+ var list = $modalStack.loadFocusElementList(modal);
+ var focusChanged = false;
+ if (evt.shiftKey) {
+ if ($modalStack.isFocusInFirstItem(evt, list) || $modalStack.isModalFocused(evt, modal)) {
+ focusChanged = $modalStack.focusLastFocusableElement(list);
+ }
+ } else {
+ if ($modalStack.isFocusInLastItem(evt, list)) {
+ focusChanged = $modalStack.focusFirstFocusableElement(list);
+ }
+ }
+
+ if (focusChanged) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ $modalStack.open = function(modalInstance, modal) {
+ var modalOpener = $document[0].activeElement,
+ modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;
+
+ toggleTopWindowClass(false);
+
+ // Store the current top first, to determine what index we ought to use
+ // for the current top modal
+ previousTopOpenedModal = openedWindows.top();
+
+ openedWindows.add(modalInstance, {
+ deferred: modal.deferred,
+ renderDeferred: modal.renderDeferred,
+ closedDeferred: modal.closedDeferred,
+ modalScope: modal.scope,
+ backdrop: modal.backdrop,
+ keyboard: modal.keyboard,
+ openedClass: modal.openedClass,
+ windowTopClass: modal.windowTopClass,
+ animation: modal.animation,
+ appendTo: modal.appendTo
+ });
+
+ openedClasses.put(modalBodyClass, modalInstance);
+
+ var appendToElement = modal.appendTo,
+ currBackdropIndex = backdropIndex();
+
+ if (!appendToElement.length) {
+ throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
+ }
+
+ if (currBackdropIndex >= 0 && !backdropDomEl) {
+ backdropScope = $rootScope.$new(true);
+ backdropScope.modalOptions = modal;
+ backdropScope.index = currBackdropIndex;
+ backdropDomEl = angular.element('');
+ backdropDomEl.attr('backdrop-class', modal.backdropClass);
+ if (modal.animation) {
+ backdropDomEl.attr('modal-animation', 'true');
+ }
+ $compile(backdropDomEl)(backdropScope);
+ $animate.enter(backdropDomEl, appendToElement);
+ scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
+ if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ appendToElement.css({paddingRight: scrollbarPadding.right + 'px'});
+ }
+ }
+
+ // Set the top modal index based on the index of the previous top modal
+ topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
+ var angularDomEl = angular.element('');
+ angularDomEl.attr({
+ 'template-url': modal.windowTemplateUrl,
+ 'window-class': modal.windowClass,
+ 'window-top-class': modal.windowTopClass,
+ 'size': modal.size,
+ 'index': topModalIndex,
+ 'animate': 'animate'
+ }).html(modal.content);
+ if (modal.animation) {
+ angularDomEl.attr('modal-animation', 'true');
+ }
+
+ appendToElement.addClass(modalBodyClass);
+ $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);
+
+ openedWindows.top().value.modalDomEl = angularDomEl;
+ openedWindows.top().value.modalOpener = modalOpener;
+ };
+
+ function broadcastClosing(modalWindow, resultOrReason, closing) {
+ return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
+ }
+
+ $modalStack.close = function(modalInstance, result) {
+ var modalWindow = openedWindows.get(modalInstance);
+ if (modalWindow && broadcastClosing(modalWindow, result, true)) {
+ modalInstance.callCloseFn(result);
+ 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);
+ if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
+ modalInstance.callDismissFn(reason);
+ modalWindow.value.modalScope.$$uibDestructionScheduled = true;
+ modalWindow.value.deferred.reject(reason);
+ removeModalWindow(modalInstance, modalWindow.value.modalOpener);
+ return true;
+ }
+ return !modalWindow;
+ };
+
+ $modalStack.dismissAll = function(reason) {
+ var topModal = this.getTop();
+ while (topModal && this.dismiss(topModal.key, reason)) {
+ topModal = this.getTop();
+ }
+ };
+
+ $modalStack.getTop = function() {
+ return openedWindows.top();
+ };
+
+ $modalStack.modalRendered = function(modalInstance) {
+ var modalWindow = openedWindows.get(modalInstance);
+ if (modalWindow) {
+ modalWindow.value.renderDeferred.resolve();
+ }
+ };
+
+ $modalStack.focusFirstFocusableElement = function(list) {
+ if (list.length > 0) {
+ list[0].focus();
+ return true;
+ }
+ return false;
+ };
+
+ $modalStack.focusLastFocusableElement = function(list) {
+ if (list.length > 0) {
+ list[list.length - 1].focus();
+ return true;
+ }
+ return false;
+ };
+
+ $modalStack.isModalFocused = function(evt, modalWindow) {
+ if (evt && modalWindow) {
+ var modalDomEl = modalWindow.value.modalDomEl;
+ if (modalDomEl && modalDomEl.length) {
+ return (evt.target || evt.srcElement) === modalDomEl[0];
+ }
+ }
+ return false;
+ };
+
+ $modalStack.isFocusInFirstItem = function(evt, list) {
+ if (list.length > 0) {
+ return (evt.target || evt.srcElement) === list[0];
+ }
+ return false;
+ };
+
+ $modalStack.isFocusInLastItem = function(evt, list) {
+ if (list.length > 0) {
+ return (evt.target || evt.srcElement) === list[list.length - 1];
+ }
+ return false;
+ };
+
+ $modalStack.loadFocusElementList = function(modalWindow) {
+ if (modalWindow) {
+ var modalDomE1 = modalWindow.value.modalDomEl;
+ if (modalDomE1 && modalDomE1.length) {
+ var elements = modalDomE1[0].querySelectorAll(tabableSelector);
+ return elements ?
+ Array.prototype.filter.call(elements, function(element) {
+ return isVisible(element);
+ }) : elements;
+ }
+ }
+ };
+
+ $modalStack.length = function() {
+ return openedWindows.length;
+ };
+
+ return $modalStack;
+ }])
+
+ .provider('$uibModal', function() {
+ var $modalProvider = {
+ options: {
+ animation: true,
+ backdrop: true, //can also be false or 'static'
+ keyboard: true,
+ modalOpenFn: function() {},
+ modalCloseFn: function() {},
+ modalDismissFn: function() {}
+ },
+ $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
+ function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
+ var $modal = {};
+
+ function getTemplatePromise(options) {
+ return options.template ? $q.when(options.template) :
+ $templateRequest(angular.isFunction(options.templateUrl) ?
+ options.templateUrl() : options.templateUrl);
+ }
+
+ var promiseChain = null;
+ $modal.getPromiseChain = function() {
+ return promiseChain;
+ };
+
+ $modal.setCallbacks = function(openFn, closeFn, dismissFn) {
+ angular.extend($modalProvider.options, {
+ modalOpenFn: openFn,
+ modalCloseFn: closeFn,
+ modalDismissFn: dismissFn
+ });
+ };
+
+ $modal.open = function(modalOptions) {
+ var modalResultDeferred = $q.defer();
+ var modalOpenedDeferred = $q.defer();
+ var modalClosedDeferred = $q.defer();
+ var modalRenderDeferred = $q.defer();
+
+ //prepare an instance of a modal to be injected into controllers and returned to a caller
+ var modalInstance = {
+ result: modalResultDeferred.promise,
+ opened: modalOpenedDeferred.promise,
+ closed: modalClosedDeferred.promise,
+ rendered: modalRenderDeferred.promise,
+ close: function (result) {
+ return $modalStack.close(modalInstance, result);
+ },
+ dismiss: function (reason) {
+ return $modalStack.dismiss(modalInstance, reason);
+ },
+ callDismissFn: function(reason) {
+ modalOptions.modalDismissFn(modalOptions, reason);
+ return true;
+ },
+ callCloseFn: function(result) {
+ modalOptions.modalCloseFn(modalOptions, result);
+ return true;
+ }
+ };
+
+ //merge and clean up options
+ modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
+ modalOptions.resolve = modalOptions.resolve || {};
+ modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);
+
+ //verify options
+ if (!modalOptions.template && !modalOptions.templateUrl) {
+ throw new Error('One of template or templateUrl options is required.');
+ }
+
+ var templateAndResolvePromise =
+ $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
+
+ function resolveWithTemplate() {
+ return templateAndResolvePromise;
+ }
+
+ // Wait for the resolution of the existing promise chain.
+ // Then switch to our own combined promise dependency (regardless of how the previous modal fared).
+ // Then add to $modalStack and resolve opened.
+ // Finally clean up the chain variable if no subsequent modal has overwritten it.
+ var samePromise;
+ samePromise = promiseChain = $q.all([promiseChain])
+ .then(resolveWithTemplate, resolveWithTemplate)
+ .then(function resolveSuccess(tplAndVars) {
+ var providedScope = modalOptions.scope || $rootScope;
+
+ var modalScope = providedScope.$new();
+ modalScope.$close = modalInstance.close;
+ modalScope.$dismiss = modalInstance.dismiss;
+
+ modalScope.$on('$destroy', function() {
+ if (!modalScope.$$uibDestructionScheduled) {
+ modalScope.$dismiss('$uibUnscheduledDestruction');
+ }
+ });
+
+ var ctrlInstance, ctrlInstantiate, ctrlLocals = {};
+
+ //controllers
+ if (modalOptions.controller) {
+ ctrlLocals.$scope = modalScope;
+ ctrlLocals.$scope.$resolve = {};
+ ctrlLocals.$uibModalInstance = modalInstance;
+ angular.forEach(tplAndVars[1], function(value, key) {
+ ctrlLocals[key] = value;
+ ctrlLocals.$scope.$resolve[key] = value;
+ });
+
+ // the third param will make the controller instantiate later,private api
+ // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126
+ ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);
+ if (modalOptions.controllerAs && modalOptions.bindToController) {
+ ctrlInstance = ctrlInstantiate.instance;
+ ctrlInstance.$close = modalScope.$close;
+ ctrlInstance.$dismiss = modalScope.$dismiss;
+ angular.extend(ctrlInstance, {
+ $resolve: ctrlLocals.$scope.$resolve
+ }, providedScope);
+ }
+
+ ctrlInstance = ctrlInstantiate();
+
+ if (angular.isFunction(ctrlInstance.$onInit)) {
+ ctrlInstance.$onInit();
+ }
+ }
+
+ $modalStack.open(modalInstance, {
+ scope: modalScope,
+ deferred: modalResultDeferred,
+ renderDeferred: modalRenderDeferred,
+ closedDeferred: modalClosedDeferred,
+ content: tplAndVars[0],
+ animation: modalOptions.animation,
+ backdrop: modalOptions.backdrop,
+ keyboard: modalOptions.keyboard,
+ backdropClass: modalOptions.backdropClass,
+ windowTopClass: modalOptions.windowTopClass,
+ windowClass: modalOptions.windowClass,
+ windowTemplateUrl: modalOptions.windowTemplateUrl,
+ size: modalOptions.size,
+ openedClass: modalOptions.openedClass,
+ appendTo: modalOptions.appendTo
+ });
+
+ modalOptions.modalOpenFn(modalOptions);
+ modalOpenedDeferred.resolve(true);
+
+ }, function resolveError(reason) {
+ modalOpenedDeferred.reject(reason);
+ modalResultDeferred.reject(reason);
+ })['finally'](function() {
+ if (promiseChain === samePromise) {
+ promiseChain = null;
+ }
+ });
+
+ return modalInstance;
+ };
+
+ return $modal;
+ }
+ ]
+ };
+
+ return $modalProvider;
+ });
+
+angular.module('ui.bootstrap.tabs', [])
+
+.controller('UibTabsetController', ['$scope', function ($scope) {
+ var ctrl = this,
+ oldIndex;
+ ctrl.tabs = [];
+
+ ctrl.select = function(index, evt) {
+ if (!destroyed) {
+ var previousIndex = findTabIndex(oldIndex);
+ var previousSelected = ctrl.tabs[previousIndex];
+ if (previousSelected) {
+ previousSelected.tab.onDeselect({
+ $event: evt,
+ $selectedIndex: index
+ });
+ if (evt && evt.isDefaultPrevented()) {
+ return;
+ }
+ previousSelected.tab.active = false;
+ }
+
+ var selected = ctrl.tabs[index];
+ if (selected) {
+ selected.tab.onSelect({
+ $event: evt
+ });
+ selected.tab.active = true;
+ ctrl.active = selected.index;
+ oldIndex = selected.index;
+ } else if (!selected && angular.isDefined(oldIndex)) {
+ ctrl.active = null;
+ oldIndex = null;
+ }
+ }
+ };
+
+ ctrl.addTab = function addTab(tab) {
+ ctrl.tabs.push({
+ tab: tab,
+ index: tab.index
+ });
+ ctrl.tabs.sort(function(t1, t2) {
+ if (t1.index > t2.index) {
+ return 1;
+ }
+
+ if (t1.index < t2.index) {
+ return -1;
+ }
+
+ return 0;
+ });
+
+ if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {
+ var newActiveIndex = findTabIndex(tab.index);
+ ctrl.select(newActiveIndex);
+ }
+ };
+
+ ctrl.removeTab = function removeTab(tab) {
+ var index;
+ for (var i = 0; i < ctrl.tabs.length; i++) {
+ if (ctrl.tabs[i].tab === tab) {
+ index = i;
+ break;
+ }
+ }
+
+ if (ctrl.tabs[index].index === ctrl.active) {
+ var newActiveTabIndex = index === ctrl.tabs.length - 1 ?
+ index - 1 : index + 1 % ctrl.tabs.length;
+ ctrl.select(newActiveTabIndex);
+ }
+
+ ctrl.tabs.splice(index, 1);
+ };
+
+ $scope.$watch('tabset.active', function(val) {
+ if (angular.isDefined(val) && val !== oldIndex) {
+ ctrl.select(findTabIndex(val));
+ }
+ });
+
+ var destroyed;
+ $scope.$on('$destroy', function() {
+ destroyed = true;
+ });
+
+ function findTabIndex(index) {
+ for (var i = 0; i < ctrl.tabs.length; i++) {
+ if (ctrl.tabs[i].index === index) {
+ return i;
+ }
+ }
+ }
+}])
+
+.directive('uibTabset', function() {
+ return {
+ transclude: true,
+ replace: true,
+ scope: {},
+ bindToController: {
+ active: '=?',
+ type: '@'
+ },
+ controller: 'UibTabsetController',
+ controllerAs: 'tabset',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/tabs/tabset.html';
+ },
+ link: function(scope, element, attrs) {
+ scope.vertical = angular.isDefined(attrs.vertical) ?
+ scope.$parent.$eval(attrs.vertical) : false;
+ scope.justified = angular.isDefined(attrs.justified) ?
+ scope.$parent.$eval(attrs.justified) : false;
+ }
+ };
+})
+
+.directive('uibTab', ['$parse', function($parse) {
+ return {
+ require: '^uibTabset',
+ replace: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/tabs/tab.html';
+ },
+ transclude: true,
+ scope: {
+ heading: '@',
+ index: '=?',
+ classes: '@?',
+ onSelect: '&select', //This callback is called in contentHeadingTransclude
+ //once it inserts the tab's content into the dom
+ onDeselect: '&deselect'
+ },
+ controller: function() {
+ //Empty controller so other directives can require being 'under' a tab
+ },
+ controllerAs: 'tab',
+ link: function(scope, elm, attrs, tabsetCtrl, transclude) {
+ scope.disabled = false;
+ if (attrs.disable) {
+ scope.$parent.$watch($parse(attrs.disable), function(value) {
+ scope.disabled = !! value;
+ });
+ }
+
+ if (angular.isUndefined(attrs.index)) {
+ if (tabsetCtrl.tabs && tabsetCtrl.tabs.length) {
+ scope.index = Math.max.apply(null, tabsetCtrl.tabs.map(function(t) { return t.index; })) + 1;
+ } else {
+ scope.index = 0;
+ }
+ }
+
+ if (angular.isUndefined(attrs.classes)) {
+ scope.classes = '';
+ }
+
+ scope.select = function(evt) {
+ if (!scope.disabled) {
+ var index;
+ for (var i = 0; i < tabsetCtrl.tabs.length; i++) {
+ if (tabsetCtrl.tabs[i].tab === scope) {
+ index = i;
+ break;
+ }
+ }
+
+ tabsetCtrl.select(index, evt);
+ }
+ };
+
+ tabsetCtrl.addTab(scope);
+ scope.$on('$destroy', function() {
+ tabsetCtrl.removeTab(scope);
+ });
+
+ //We need to transclude later, once the content container is ready.
+ //when this link happens, we're inside a tab heading.
+ scope.$transcludeFn = transclude;
+ }
+ };
+}])
+
+.directive('uibTabHeadingTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^uibTab',
+ link: function(scope, elm) {
+ scope.$watch('headingElement', function updateHeadingElement(heading) {
+ if (heading) {
+ elm.html('');
+ elm.append(heading);
+ }
+ });
+ }
+ };
+})
+
+.directive('uibTabContentTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^uibTabset',
+ link: function(scope, elm, attrs) {
+ var tab = scope.$eval(attrs.uibTabContentTransclude).tab;
+
+ //Now our tab is ready to be transcluded: both the tab heading area
+ //and the tab content area are loaded. Transclude 'em both.
+ tab.$transcludeFn(tab.$parent, function(contents) {
+ angular.forEach(contents, function(node) {
+ if (isTabHeading(node)) {
+ //Let tabHeadingTransclude know.
+ tab.headingElement = node;
+ } else {
+ elm.append(node);
+ }
+ });
+ });
+ }
+ };
+
+ function isTabHeading(node) {
+ return node.tagName && (
+ node.hasAttribute('uib-tab-heading') ||
+ node.hasAttribute('data-uib-tab-heading') ||
+ node.hasAttribute('x-uib-tab-heading') ||
+ node.tagName.toLowerCase() === 'uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'data-uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'x-uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'uib:tab-heading'
+ );
+ }
+});
+
+/**
+ * The following features are still outstanding: animation as a
+ * function, placement as a function, inside, support for more triggers than
+ * just mouse enter/leave, html tooltips, and selector delegation.
+ */
+angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])
+
+/**
+ * The $tooltip service creates tooltip- and popover-like directives as well as
+ * houses global options for them.
+ */
+.provider('$uibTooltip', function() {
+ // The default options tooltip and popover.
+ var defaultOptions = {
+ placement: 'top',
+ placementClassPrefix: '',
+ animation: true,
+ popupDelay: 0,
+ popupCloseDelay: 0,
+ useContentExp: false
+ };
+
+ // Default hide triggers for each show trigger
+ var triggerMap = {
+ 'mouseenter': 'mouseleave',
+ 'click': 'click',
+ 'outsideClick': 'outsideClick',
+ 'focus': 'blur',
+ 'none': ''
+ };
+
+ // The options specified to the provider globally.
+ var globalOptions = {};
+
+ /**
+ * `options({})` allows global configuration of all tooltips in the
+ * application.
+ *
+ * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
+ * // place tooltips left instead of top by default
+ * $tooltipProvider.options( { placement: 'left' } );
+ * });
+ */
+ this.options = function(value) {
+ angular.extend(globalOptions, value);
+ };
+
+ /**
+ * This allows you to extend the set of trigger mappings available. E.g.:
+ *
+ * $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );
+ */
+ this.setTriggers = function setTriggers(triggers) {
+ angular.extend(triggerMap, triggers);
+ };
+
+ /**
+ * This is a helper function for translating camel-case to snake_case.
+ */
+ function snake_case(name) {
+ var regexp = /[A-Z]/g;
+ var separator = '-';
+ return name.replace(regexp, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+ }
+
+ /**
+ * Returns the actual instance of the $tooltip service.
+ * TODO support multiple triggers
+ */
+ this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
+ var openedTooltips = $$stackedMap.createNew();
+ $document.on('keypress', keypressListener);
+
+ $rootScope.$on('$destroy', function() {
+ $document.off('keypress', keypressListener);
+ });
+
+ function keypressListener(e) {
+ if (e.which === 27) {
+ var last = openedTooltips.top();
+ if (last) {
+ last.value.close();
+ openedTooltips.removeTop();
+ last = null;
+ }
+ }
+ }
+
+ return function $tooltip(ttType, prefix, defaultTriggerShow, options) {
+ options = angular.extend({}, defaultOptions, globalOptions, options);
+
+ /**
+ * Returns an object of show and hide triggers.
+ *
+ * If a trigger is supplied,
+ * it is used to show the tooltip; otherwise, it will use the `trigger`
+ * option passed to the `$tooltipProvider.options` method; else it will
+ * default to the trigger supplied to this directive factory.
+ *
+ * The hide trigger is based on the show trigger. If the `trigger` option
+ * was passed to the `$tooltipProvider.options` method, it will use the
+ * mapped trigger from `triggerMap` or the passed trigger if the map is
+ * undefined; otherwise, it uses the `triggerMap` value of the show
+ * trigger; else it will just use the show trigger.
+ */
+ function getTriggers(trigger) {
+ var show = (trigger || options.trigger || defaultTriggerShow).split(' ');
+ var hide = show.map(function(trigger) {
+ return triggerMap[trigger] || trigger;
+ });
+ return {
+ show: show,
+ hide: hide
+ };
+ }
+
+ var directiveName = snake_case(ttType);
+
+ var startSym = $interpolate.startSymbol();
+ var endSym = $interpolate.endSymbol();
+ var template =
+ '\n" +
+ "
\n" +
+ " \n" +
+ "
\n" +
+ "");
+}]);
+
+angular.module("uib/template/datepicker/month.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/datepicker/month.html",
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " {{::label.abbr}} \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "{{ weekNumbers[$index] }} \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "
\n" +
+ "");
+}]);
+
+angular.module("uib/template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/datepicker/popup.html",
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "
\n" +
+ "");
+}]);
+
+angular.module("uib/template/datepicker/year.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/datepicker/year.html",
+ "\n" +
+ " \n" +
+ "
\n" +
+ "");
+}]);
+
+angular.module("uib/template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/accordion/accordion-group.html",
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " {{heading}}\n" +
+ "
\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "
\n" +
+ "s&&a>A},a.noIncrementMinutes=function(){var a=p(s,y);return B||a>A||as&&a>A},a.noIncrementSeconds=function(){var a=q(s,C);return B||a>A||as&&a>A},a.noToggleMeridian=function(){return s.getHours()<12?B||p(s,720)>A:B||p(s,-720)\n \n
\n')}]),angular.module("uib/template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/datepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n : \n \n \n \n : \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n
\n')}]),angular.module("uib/template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/month.html",'\n \n \n \n \n \n \n \n \n \n {{::label.abbr}} \n \n \n \n{{ weekNumbers[$index] }} \n \n \n \n \n \n
\n')}]),angular.module("uib/template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/popup.html",'\n')}]),angular.module("uib/template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/year.html",'\n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
\n')}]),angular.module("uib/template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("uib/template/accordion/accordion-group.html",'\n \n \n \n \n \n \n \n \n \n\n \n \n \n {{heading}}\n
\n Dependencies
JavaScript is required. The only required dependencies are:
ui.bootstrap module:angular.module('myModule', ['ui.bootstrap']);
+ If you are using UI Bootstrap in the CSP mode, e.g. in an extension, make sure you link to the ui-bootstrap-csp.css in your HTML manually.
You can fork one of the plunkers from this page to see a working example of what is described here.
Since version 0.14.0 we started to prefix all our components. If you are upgrading from ui-bootstrap 0.13.4 or earlier, @@ -193,15 +196,21 @@
ui-bootstrap have documentation and interactive Plunker examples.
- For the directives, we list the different attributes with their default values, and whether they are readonly. In addition to this, some settings - have an eye icon next to them like this . The eye means that the setting has an Angular - $watch listener applied to it. + For the directives, we list the different attributes with their default values. In addition to this, some settings have a badge on it: + +
For the services (you will recognize them with the $ prefix), we list all the possible parameters you can pass to them and their default values if any.
- Also, some components have default values that you can override globally within a .config function for example.
+ * Some directives have a config service that follows the next pattern: uibDirectiveConfig. The service's settings use camel case. The services can be configured in a .config function for example.
<%- module.docs.html %>
<%- module.docs.js %>