Compare commits

...

1845 Commits

Author SHA1 Message Date
Adam Gordon a2dee1bdeb docs: add steps to reproduce section to template (#6443)
* add new steps to reproduce section to github issue template to ask
issue filers to provide explicit steps to reproduce the issue so people
aren't left to guess or parse poorly written ones.
2017-01-30 13:13:38 -08:00
Wesley Cho 409eec4019 chore(release): starting 2.5.1 2017-01-28 05:34:16 -08:00
Wesley Cho b90485b2a4 chore(release): 2.5.0 2017-01-28 05:30:11 -08:00
Daniel Smith 0d79005f8d fix(angular): add compatibility with Angular 1.6
- Change how ngModelOptions is used to conform to Angular 1.6
- Catch rejections as per change to $q

Closes #6427
Fixes #6360
2017-01-28 05:26:34 -08:00
mattcollier e538d2f71f docs(collapse): fix typo
Closes #6398
Closes #6421
2017-01-23 11:31:37 -08:00
Matthias Dailey f5b357fd11 fix(tooltip): unbind keypress listener on hide
- Unbind listener on hide to fix memory leak

Closes #6423
Fixes #6405
2017-01-23 11:30:23 -08:00
Alex (Jinghao) Yan 761db7b4b7 fix(dropdown): do nothing if not open when clicking
- When clicking, do nothing if dropdown is closed on document listener

Closes #6414
2017-01-23 03:07:20 -08:00
tariqporter 86ee770834 fix(carousel): remove transition buffering
- Remove transition buffering

Closes #6367
Fixes #5967
2017-01-23 02:27:05 -08:00
david.humphrey@senecacollege.ca 47c4544e23 chore(npm): add fields to package.json
Closes #6418
2017-01-21 07:07:47 -08:00
Wesley Cho e8479514cd chore(release): bump to 2.5.0 2017-01-21 07:06:41 -08:00
Sherry Chang cf3f870735 Add CDNJS version badge in README.md (#6297)
This will add the badge to show its version on CDNJS and also link to its page on CDNJS!
2017-01-20 13:16:27 -08:00
Umer Farooq 7d3a7502fa feat(dropdown): make dropdown-append-to-body configurable (#6356)
* feat(dropdown): make dropdown-append-to-body configurable

Make dropdown-append-to-body accept a value which will be evaluated to
determine if the menu should be appended to body. If no value is
specified, or a non-false value is specified then the menu will be
appended to body. If the value is `false` then the menu will not be
appended to body.

* feat(dropdown): append and remove menu when menu is opened or closed

Only append and remove append-to and append-to-body menus when the
menu is opened or closed. This allows for the values of append-to and
append-to-body to be evaluated when the menu is toggled open, and also
prevents littering of the DOM.

* fix(dropdown): don't remove the dropdown-menu on close

Instead of removing the dropdown-menu on close, append it back to the
original element.
2017-01-20 13:14:29 -08:00
Jeff Carey 71dc691323 feat(pagination): Added menu and menuitem roles (closes #6383) (#6386)
feat(pagination): Added test
2017-01-20 13:13:54 -08:00
Scott Kao 42f3cc847a chore(license): update year to 2017 2017-01-10 05:23:17 -08:00
Wesley Cho b755559ec9 chore(release): starting 2.4.1 2016-12-29 23:19:51 -08:00
Wesley Cho 9e6d2a0a14 chore(changelog): update for 2.4.0 2016-12-29 23:17:21 -08:00
Wesley Cho 2596b9805f chore(release): 2.4.0 2016-12-29 23:15:22 -08:00
Douglas Ludlow 5a3e44a146 feat(dateparser): allow overriding of parsers
- Add ability to override parser

Closes #6370
Closes #6373
2016-12-29 23:12:17 -08:00
Wesley Cho 4872c05a32 docs(accordion): remove unnecessary div
- Remove unnecessary div creating a doubled border

Closes #6378
2016-12-27 03:01:04 -08:00
Wesley Cho fc686bb7a3 chore(release): starting 2.3.3 2016-12-27 01:59:02 -08:00
Wesley Cho 7f664f9f45 chore(release): 2.3.2 2016-12-27 01:54:51 -08:00
khlevon98 955848c3b1 fix(dropdown): re-add close
- Re-add closing via service

Closes #6382
Fixes #6321
Fixes #6357
Fixes #6364
2016-12-27 01:47:15 -08:00
Wesley Cho 7a1d54c8c3 chore(release): starting 2.3.2 2016-12-10 03:18:18 -08:00
Wesley Cho 0ed1a59aef chore(release): 2.3.1 2016-12-10 03:14:22 -08:00
Wesley Cho f2722b59a5 fix(dateparser): add new date format for angular 1.5+ only
- Only add parsing ability for new date format for angular 1.5+

Fixes #6349
2016-12-10 03:06:50 -08:00
béla 57ed7e4f7f chore(readme): fix variable used
Closes #6344
2016-12-02 06:23:16 -08:00
Steven Yeh 90848144e8 chore(changelog): fix generated links
- Fix links to use proper tags

Closes #6340
2016-12-01 22:35:18 -08:00
Wesley Cho a4d7076c8e chore(dropdown): fix accidental deletion 2016-11-29 23:25:21 -08:00
Wesley Cho c824731ae8 revert(dropdown): undo addition of unbind 2016-11-29 23:19:43 -08:00
Wesley Cho 1653afa210 refactor(dropdown): use container for class toggle detection 2016-11-29 01:47:23 -08:00
Wesley Cho 7e2f2c1bad chore(datepickerPopup): change to on/off 2016-11-29 00:19:19 -08:00
Wesley Cho 61f365abfd chore(timepicker): change to on/off 2016-11-29 00:18:36 -08:00
Wesley Cho ec2d9ad605 chore(typeahead): change to on/off 2016-11-29 00:17:13 -08:00
Wesley Cho 08b50ccb1c chore(dropdown): change to on/off 2016-11-29 00:14:33 -08:00
patricksmms 44ab0a8106 fix(dropDown): remove dropdown on close
- Unbind keybind on close

Closes #6326
Fixes #6314
2016-11-29 00:09:08 -08:00
Wesley Cho 1962485504 fix(datepickerPopup): change to toTimezone
- Change conversion to use `toTimezone`, as the date is going from UI date with timezone applied to timezone set by `ngModelOptions`

Fixes #6235
2016-11-27 02:26:52 -08:00
Jonathan Perez 8a4f625ef6 fix(modal): revert focus behavior on open
- On open, do not focus the first focusable element

Closes #6295
2016-11-27 02:18:17 -08:00
Wesley Cho 7be665399f chore(release): starting 2.3.1 2016-11-26 07:43:50 -08:00
Wesley Cho 2edb5d38cb chore(release): update changelog 2016-11-26 07:41:20 -08:00
Wesley Cho 4e06553f7c chore(release): 2.3.0 2016-11-26 07:38:21 -08:00
Janne 25ff206767 feat(dateparser): add LLLL support
- Add LLLL support. This requires Angular 1.5+ to take advantage of this.

Closes #6281
2016-11-26 07:35:37 -08:00
Wesley Cho 997813f0eb chore(release): starting 2.2.1 2016-10-10 08:30:03 -07:00
Wesley Cho 25db68e903 chore(release): 2.2.0 2016-10-10 08:26:52 -07:00
Mark Wheeldon 78559761dc fix(tooltip): cancel timeout when hidden
- Cancel timeout when hidden so that positioning does not incorrectly occur when not visible

Closes #6226
Fixes #6221
2016-10-10 07:47:56 -07:00
nmccready 14384fc40f fix(dropdown): exit keybind is not open
- Exit keybindFilter if the $scope is not present

Closes #6278
Fixes #6208
2016-10-10 07:44:34 -07:00
JuliaUsanova 58f1813aca fix(position): correct scrollbar width calculation
Closes #6273
2016-10-10 07:42:36 -07:00
Eric Schneider 9666c64f4a feat(timepicker): add validation information
- Add validation information for specific violations, allowing users to style classes generated by Angular

Closes #6230
Closes #6259
2016-09-24 21:14:55 -04:00
Nicholas Heiner f9f7e02d15 fix(modal): improve ARIA support.
- Add accessibility with multiple modals

Closes #6203
2016-09-23 23:21:25 -05:00
Wesley Cho a4bea6f229 chore(release): starting 2.2.0 2016-09-23 23:19:16 -05:00
Wesley Cho c00851a18b chore(release): 2.1.4 2016-09-23 23:15:28 -05:00
Sergey Lysenko c687acd489 docs: create retina-ready favicon
- Update favicon with retina-friendly icon

Closes #6255
2016-09-23 23:09:24 -05:00
Eric Schneider 3f70d76327 fix(datepicker): improve accessibility
- Improve accessibility with forward and previous buttons with screen readers

Closes #6247
2016-09-23 23:06:17 -05:00
Nathan Herzing 08ee30a91e fix(dropdown): prevent premature scope removal
- Toggle false after focus executes

Closes #6238
Fixes #6225
2016-09-23 23:03:16 -05:00
ravi-123 7671bd6ed4 docs(popover): add popover-class 2016-09-23 23:01:31 -05:00
Evan Theurer 1a132dd757 docs(collapse): add navigation collapse example
- Add an example for using collapse with the bootstrap navbar

Closes #3481
Closes #6217
2016-09-01 20:18:59 -07:00
Wesley Cho 9881a27397 chore(release): starting 2.1.4 2016-08-25 08:38:42 -07:00
Wesley Cho 294b151342 chore(release): 2.1.3 2016-08-25 08:35:57 -07:00
Axel Navarro 969eb9c74d fix(modal): compile only once with component
- When using the component option, do not compile content in order to take advantage of later compilation

Closes #6202
Fixes #6201
2016-08-24 20:26:33 -07:00
Wesley Cho 048d85a2ad chore(release): starting 2.1.3 2016-08-22 10:04:12 -07:00
Wesley Cho 876e72a0df chore(release): 2.1.2 2016-08-22 10:01:02 -07:00
Wesley Cho 6734908108 test(modal): fix custom matchers
- Trigger a test failure if resolved on rejected promise and rejected on resolved promise
- Trigger a test failure if neither resolved or rejected when expected resolved/rejected promise

Closes #6195
2016-08-22 09:57:20 -07:00
Wesley Cho 515bcf2933 fix(collapse): revert change to transition css
- Revert change to `getScrollFromElement` function

Closes #6196
Fixes #6194
2016-08-22 09:54:30 -07:00
Wesley Cho 148371fb6d docs(tooltip): add info on Safari bug
- Add information on Safari bug, affecting all versions up to 9 at the least

Closes #5445
2016-08-22 09:53:11 -07:00
Axel Navarro 8047c06258 docs(modal): added a simple component modal demo
Closes #6193
2016-08-22 08:03:06 -07:00
Axel Navarro 3e8ecfffe0 fix(modal): close and dismiss bindings on component
- Correctly bind close and dismiss handlers on component usage

Closes #6192
Fixes #6191
2016-08-21 12:12:44 -07:00
Georgii Dolzhykov ddcacb7a83 fix(datepicker): fix accidental global
- Fix accidental global usage

Closes #6188
2016-08-21 04:42:13 -07:00
Wesley Cho 915eda0540 chore(release): starting 2.1.2 2016-08-20 22:54:15 -07:00
Wesley Cho f9eede7555 chore(release): 2.1.1 2016-08-20 22:49:30 -07:00
Axel Navarro fb5fabf580 fix(modal): switch to .append
- Switch to `append` since `html` is jQuery specific

Closes #6187
Fixes #6186
2016-08-20 22:46:35 -07:00
Wesley Cho aef24cde4b fix(collapse): default to css
- Default to value set from CSS for height/width

Closes #6182
Fixes #6045
2016-08-20 05:58:59 -07:00
Wesley Cho b893a93f82 docs(collapse): fix height on horizontal
- Fix height on horizontal collapse usage

Closes #6050
Closes #6183
2016-08-20 05:58:03 -07:00
Wesley Cho 6352f13e85 chore(release): starting 2.1.1 2016-08-19 14:34:37 -07:00
Wesley Cho 76cd65ef1a chore(release): 2.1.0 2016-08-19 14:31:32 -07:00
Wesley Cho 84cc2cf5cc fix(collapse): set overflow to hidden on transition
- When collapse is transitioning, set `overflow: hidden` to avoid possibility of scrollbars changing size

Closes #6180
Fixes #5474
2016-08-19 10:37:06 -07:00
Wesley Cho 2ade0545a9 feat(modal): add component support
- Add support for `component` option

Closes #5683
Closes #6179
2016-08-19 09:54:05 -07:00
Stuart Forster f5ff12c0a4 fix(tooltip): close tooltip on esc
- On keypress of escape, close tooltip/popover

Closes #6177
Fixes #6108
2016-08-18 14:10:17 -07:00
Wesley Cho f147d22f5c fix(datepickerPopup): apply timezone conversion
- Apply timezone conversion to selecting today

Closes #6173
Fixes #6147
2016-08-18 13:21:15 -07:00
Wesley Cho f798a47d48 chore: bump angular version 2016-08-18 10:12:21 -07:00
Wesley Cho 43a1f75e7c chore(demo): bump versions 2016-08-18 10:11:55 -07:00
Nick Heiner 4a5e6a7418 fix(modal): improve ARIA support
- Add aria-labelledby and aria-described by support

Closes #4772
2016-08-17 22:09:30 -07:00
Wesley Cho af6c2aaca0 chore(release): starting 2.1.0 2016-08-17 22:09:18 -07:00
Kirkland 61415e1968 Adding roles to the datepicker templates to resolve an ADA violation. (#6170)
Closes #6170
2016-08-17 17:45:34 -07:00
Wesley Cho 5123e38a49 docs(tooltip): add ngSanitize to Plunker
- Add ngSanitize to Plunkers for uib-tooltip-html and uib-popover-html Plunkers

Closes #6165
Fixes #6157
2016-08-16 08:36:00 -07:00
Wesley Cho ca20be4667 fix(collapse): remove unnecessary inherit
- Remove unnecessary `inherit` property, which causes issues when custom widths are used, including percentage based widths

Closes #6164
Fixes #6163
2016-08-16 08:35:09 -07:00
Wesley Cho d9dd5803ae chore(release): starting 2.0.3 2016-08-15 13:45:53 -07:00
Wesley Cho 86f528730b chore(release): 2.0.2 2016-08-15 13:42:33 -07:00
Wesley Cho fbd0845c95 fix(datepickerPopup): correctly format to timezone
- Format according to ngModelOptions timezone if specified

Closes #6159
Fixes #6105
Fixes #6146
Fixes #6147
2016-08-15 13:39:17 -07:00
Patrick Johnmeyer 5597e2fa99 docs(carousel): switch to unsplash.it
- Change image hosting services due to expired SSL cert for lorempixel

Closes #6144
2016-08-15 07:50:14 -07:00
Matt Lewis 6bad7592b9 fix(dropdown): fix keyboard-nav
- Fix keyboard-nav for when not using append-to or append-to-body

Fixes #6102
Closes #6154
2016-08-11 04:38:14 -07:00
Wesley Cho 0023d1bd97 chore(typeahead): adjust regex comment 2016-08-08 23:09:09 -07:00
Wesley Cho be0d0564c2 docs(demo): add link to ng-bootstrap
- Add link to ng-bootstrap project on demo site

Closes #6083
Closes #6145
2016-08-08 02:52:06 -07:00
Gerardo 9f3e387473 docs(accordion): add wrapping div
Closes #6139
2016-08-08 02:44:57 -07:00
Martin Staffa 58e0433b96 chore(demo): use https in the generated link
This avoids the popup about an unsecure connection when opening examples in plnkr.

Closes #6132
2016-08-02 08:36:06 +02:00
Wesley Cho 87a373936d chore(release): starting 2.0.2 2016-08-02 08:33:35 +02:00
Wesley Cho e8e4ef1070 chore(release): 2.0.1 2016-08-02 08:28:25 +02:00
Francesco Pipita c61d16a933 fix(modal): restore broken stacked modals
Closes #6103
Closes #6104
2016-07-22 00:25:10 +01:00
Adam Gordon 6bfb4cdbdf chore(docs): fix specified sizes
Closes #6110
Closes #6111
2016-07-21 23:33:51 +01:00
Wesley Cho cac6a45345 chore(changelog): update with changes 2016-07-20 00:10:00 -07:00
Bryan Gillespie 8a53327bd6 docs(tooltip): add inline html example
- Make demo more clear on html tooltip capability

Closes #4738
Closes #6067
2016-07-20 00:06:27 -07:00
Wesley Cho 9f06a8bfdb chore(release): starting 2.0.1 2016-07-20 00:02:45 -07:00
Wesley Cho 5173779f84 chore(release): 2.0.0 2016-07-19 23:59:40 -07:00
Wesley Cho 1616e9720d feat(tooltip): remove replace usage
- Remove `replace: true` usage

BREAKING CHANGE: The template structure changed slightly due to the removal of `replace: true` - see documentation examples in action to see differences in practice.

Closes #5994
2016-07-19 13:40:38 -07:00
Ashton b77f02cdce docs(readme): change to https
- Change from http to https

Closes #6064
2016-06-30 08:45:49 -07:00
craig 39d9b9886d feat(datepicker): add monthColumns
- Add `monthColumns` option

Closes #5515
Closes #5935
2016-06-27 09:45:30 -07:00
Dolev Dori 2d831bcc2a fix(dropdown): align position correctly with scrollbar
- Fix horizontal alignment independent of the presence of a vertical scrollbar

Closes #6008
Fixes #5942
2016-06-27 09:32:13 -07:00
Wesley Cho d846e2d788 fix(dateparser): correctly format with literals
- Fix formatting of dates with literal usage

Closes #6055
Fixes #5620
Fixes #5802
2016-06-27 09:18:25 -07:00
Anthony Cleaver 409b7aa3b3 fix(modal): remove window class after animation
- Wait until animations are complete before removing window class

BREAKING CHANGE: This introduces a minor behavior change in when the class is removed

Closes #6056
Fixes #6051
2016-06-27 08:42:20 -07:00
Manuel Siggen ed3400bb68 fix(typeahead): clear validity in $digest
- Clear within $digest cycle

Closes #6033
Fixes #6032
2016-06-26 17:17:46 -07:00
Anthony Cleaver 1cbd73d227 feat(modal): append using $animate
- Use $animate.enter to append transcluded content

Closes #6023
Closes #6029
2016-06-26 17:07:01 -07:00
robjacobs 433e536e6b fix(modal): check for overflow hidden
Check if appendToElement has scrolling disabled before adding
the scrollbar padding.

Fixes #6037
Closes #6041
2016-06-21 15:35:26 -04:00
squelix 1ec099767f feat(collapse): add horizontal support
- Add support for horizontal collapsing

Closes #3593
Closes #6010
2016-06-16 10:52:31 -07:00
Wesley Cho 4e0e34f47a revert(dropdown): change back to .constant() 2016-06-15 10:12:14 -07:00
Wei Wang 7457fb0e63 feat(dropdown): use .value() for uibDropdownConfig
Closes #6004
Closes #6006
2016-06-15 06:44:55 -07:00
Wei Wang 23ef372a17 docs(README): add modal to index-nocss list
Closes #6005
2016-06-14 14:04:25 -07:00
Andrij Fedyk 164811ab35 fix(tooltip): missed dependency for cjs
Closes #5999
2016-06-14 14:03:19 -07:00
Andrij Fedyk 1de58a3e5d fix(modal): remove unused template from modal 2016-06-14 14:03:17 -07:00
dirk 7e320e0e92 fix(datepickerPopup): use value instead of viewValue
Closes #6007
2016-06-14 14:02:22 -07:00
Wesley Cho d6fe9c7e7a feat(rating): remove replace usage
- Remove `replace: true` usage

BREAKING CHANGE: Due to the removal of `replace: true`, this results in a slight change to the HTML structure - see the documentation examples to see it in action.

Closes #5998
2016-06-13 20:17:38 -07:00
Wesley Cho 75188211aa feat(timepicker): remove replace usage
- Remove `replace: true` usage

BREAKING CHANGE: This removes `replace: true`, which changes the HTML structure slightly - see the documentation examples to see it in action.

Closes #5997
2016-06-13 20:17:03 -07:00
johanneskrtek 4e68778561 feat(timepicker): avoid allowing to tab to controls
- Prevent the ability to tab to timepicker controls, leaving incrementing/decrementing to keyboard actions on the individual inputs

Closes #5930
2016-06-13 20:15:34 -07:00
Wesley Cho a68cc20dd4 chore(dropdown): add guard when closing 2016-06-13 12:54:15 -07:00
Wesley Cho ba113a050e chore(pager): add tabindex module dep 2016-06-13 10:35:53 -07:00
Wesley Cho 0d8cec6e4f feat(pager): toggle tabindex when disabled
- Add `tabindex="-1"` when disabled and remove it when not for accessibility

Closes #5996
2016-06-13 10:34:52 -07:00
Wesley Cho a47bcedad4 feat(datepickerPopup): remove replace usage
- Remove `replace: true` usage

BREAKING CHANGE: Due to the nature of `replace: true`, this has a slight structural HTML change in the popup as a result - see documentation examples for the change in action.

Closes #5993
2016-06-13 10:18:37 -07:00
Wesley Cho 387c6e7bbc feat(pagination): remove replace usage
- Remove `replace: true` usage

BREAKING CHANGE: Due to the removal of `replace: true`, this affects the HTML structure slightly - see documentation examples to see new usage.

Closes #5992
2016-06-13 10:17:53 -07:00
Wesley Cho 9b24e1dfed feat(pager): remove replace usage
- Remove `replace: true usage

BREAKING CHANGE: This removes `replace: true` usage from the pager, which causes a slight usage change - see documentation examples for new usage.

Closes #5991
2016-06-13 10:08:01 -07:00
Wesley Cho 5f4eedd0e7 feat(accordion): add appropriate tabindex on disabled
- Add `tabindex="-1"` to accordion group header when disabled and remove when not to assist with accessibility

Closes #4067
Closes #5990
2016-06-13 10:07:24 -07:00
Wesley Cho 96d52ce150 feat(modal): remove replace usage
- Remove `replace: true` usage

BREAKING CHANGE: This removes `replace: true` usage, causing some structural changes to the HTML - the major part here is that there is no more backdrop template, and the top level elements for the window/backdrop elements lose a little flexibility. See documentation examples for new structure.

Closes #5989
2016-06-13 10:06:48 -07:00
renhao 55cf26bf28 chore(datepicker): remove dead code
Closes #5995
2016-06-13 10:05:31 -07:00
Wesley Cho 5fdcbd6b90 chore(dropdown): add guard 2016-06-13 00:21:39 -07:00
Wesley Cho e92fb7fa7c feat(datepicker): remove replace: true usage
- Remove `replace: true` usage

BREAKING CHANGE: As a result of removal of `replace: true`, there is the potential that this may break some CSS layout due to the slightly different HTML. Refer to the documentation examples to see the new structure.

Closes #5988
2016-06-12 23:53:11 -07:00
Wesley Cho 1a870a3bb1 feat(pagination): disable tabbing when disabled
- Add directive for toggling `tabindex="-1"` when ngDisabled is true, and removing tabindex when false

Closes #5984
2016-06-12 23:52:20 -07:00
Wesley Cho 6038403179 fix(dropdown): bind event listener on dropdown menu
- Bind keypress listener to dropdown menu for handling keyboard navigation

Closes #5982
2016-06-12 23:51:25 -07:00
Wesley Cho fb38d0db2e chore(position): add missing , 2016-06-12 15:18:32 -07:00
Wesley Cho 5046bd4e56 feat(carousel): remove replace: true usage
- Remove `replace: true` usage from the carousel and the slide

BREAKING CHANGE: Due to the removal of `replace: true`, this causes a slight HTML structure change to the carousel and the slide elements - see documentation demos to see how it changes. This also caused removal of the ngTouch built in support - if one is using ng-touch, one needs to add the `ng-swipe-left` and `ng-swipe-right` directives to the carousel element with relevant logic.

Closes #5987
2016-06-12 15:13:26 -07:00
Wesley Cho 2458c2863d feat(alert): remove replace: true usage
- Remove `replace: true` usage

BREAKING CHANGE: This removes the `replace: true` usage, so this has an effect on how one uses the directive in the template - see documentation for reference

Closes #5986
2016-06-12 15:12:25 -07:00
Wesley Cho 3819bbe8fa feat(accordion): remove replace: true usage
- Remove usage of `replace: true`
- Remove unnecessary `panel-class` feature

BREAKING CHANGE: This removes usage of `replace: true` in the accordion group, which results in a template change where the template no longer needs to contain the panel itself, but its contents. The accordion group will add the `panel` class by default, so the user just needs to add the appropriate classes to the accordion group element. This allows the user to use ng-class as well to fully control the panel related classes, so `panel-class` now is unnecessary

Closes #5985
2016-06-12 15:11:10 -07:00
Wesley Cho e2016fd2eb refactor(position): abstract out common logic
- Abstracting out conditional to position service adjustTop method to increase readability and to prepare it for use in dropdown/typeahead

Closes #5983
2016-06-12 15:10:15 -07:00
Wesley Cho 34a1443a85 fix(tooltip): reposition for placement top
- Reposition the tooltip when the placement option contains top in order to account for resizing of tooltip from right side

Closes #5959
2016-06-11 15:47:04 -07:00
atrinh 35ced04445 fix(modal): filter out non-tabbable elements
- Ensure non-tabbable elements with taxindex of -1 are not tabbed to

Closes #5963
Fixes #5955
2016-06-09 14:25:22 -07:00
Wesley Cho 90fa2f682a docs(readme): add note about versioning policy
- Add information on versioning policy

Closes #5800
Closes #5958
2016-06-03 21:40:23 -07:00
cherry-geqi 4fef0377bb fix(datepickerPopup): specify dependency on datepicker
- Specify dependency on datepicker module

Closes #5954
2016-06-02 23:27:38 -07:00
rcholic b0466d9e6e fix(datepickerPopup): clear date when button is clicked
- Fix clearing the date when the clear button is clicked

Closes #5945
Fixes #5906
2016-05-31 08:50:12 -07:00
Wesley Cho 4b912228be feat(tooltip): add expression support
- Add expression support for tooltip-trigger
- Add support for object event bindings for showing/hiding tooltips

BREAKING CHANGE: This removes support for plain strings and interpolations in tooltip-trigger and popover-trigger - please change these appropriately. See test changes in this commit for reference

Closes #5221
Closes #5938
2016-05-28 22:14:05 -07:00
Wesley Cho 9a606dca7c chore(typeahead): add matcher class 2016-05-28 18:21:36 -07:00
Adam Gordon 6d5b84a0ba fix(typeahead): remove duplicate id attribute
* remove any duplicate `id` attribute on the typeahead hint element if used on
  the original input element.

BREAKING CHANGE: This change removes the `id` attribute on the first `<input>`
element placed into the DOM when the `typeahead-show-hint` attribute is used
and there is an `id` attribute present on the original `uib-typeahead` element.
This could affect selectors if they are being used.

Closes #5936
Fixes #5926
2016-05-28 17:27:20 -07:00
Wesley Cho cce00970f1 feat(dropdown): focus toggle on close from click
- Focus the toggle element when the click causes the dropdown menu to close

BREAKING CHANGE: This changes the focus behavior of the dropdown slightly, and potentially may break code built around current usage

Closes #5934
Fixes #5782
2016-05-28 17:18:39 -07:00
Wesley Cho 23b91d951e feat(datepicker): add ngModelOptions support
- Adds support for ngModelOptions in the `datepicker-options` object

BREAKING CHANGE: This modifies the current behavior around the datepicker & popup's ngModelOptions, which may affect custom components that are built around both

Closes #5933
Fixes #5825
2016-05-28 09:09:18 -07:00
Wesley Cho 053035234c chore: bump angular to 1.5.5
Closes #5920
2016-05-28 07:27:45 -07:00
deplay a075824087 feat(stackedMap): improve perf of removeTop
- Change `removeTop` from `slice` to `pop`

Closes #5925
Closes #5932
2016-05-28 07:24:25 -07:00
Wesley Cho 13c14af9a2 fix(typeahead): change to select class
- Change to select `.uib-typeahead-match` class instead of the `li` tag

BREAKING CHANGE: This changes the selector used so that it doesn't select for the `li` tag specifically, but the elements with the class `uib-typeahead-match` - if using a custom template, this class needs to be added to the `li` element in the typeahead popup template.

Closes #5922
Fixes #5848
2016-05-24 11:31:34 -07:00
Wesley Cho 280ddaf47e chore(release): starting 2.0.0 2016-05-22 20:09:55 -07:00
Wesley Cho dc85f67b2d chore(release): 1.3.3 2016-05-22 20:05:01 -07:00
Christopher Rued 2ffb86f201 feat(typeahead): Add support for should-select
By default behaves as before. If specified, allows a custom function
to be defined to determine whether the keydown event should trigger
selection based on the `typeahead-should-select` attribute.

Closes #5671
Closes #5794
2016-05-21 22:33:00 -07:00
Adam Gordon aec5304ef5 chore(button): add known issue for tooltip/popover
* add known issue to button docs indicating a CSS issue when using a tooltip or
  a popover.

Closes #5890
2016-05-16 08:47:26 -07:00
robjacobs eb02778297 chore(tab): code cleanup
Removing unnecessary code added under PR #5489

Closes #5891
Fixes #5888
2016-05-10 14:09:39 -04:00
robjacobs 26d399557e feat(tab): allow strings for index
- Allows the use of strings for the tab index and active value
on the tabset.

Closes #5713
Closes #5827
2016-05-09 16:09:47 -04:00
Adam Gordon 9436b9e7bd docs: add note for datepicker/datepicker-popup
* update the datepicker and datepicker popup docs to let user know
  about using the `uibDateParser` service to convert a date string
  into a `Date` object.

Closes #5880
2016-05-08 07:57:28 -07:00
kwiateusz b2984b0416 docs(tabs): mention that index needs to be number
Closes #5876
2016-05-07 07:53:22 -06:00
Guillaume Royer 5188463f69 fix(datepickerPopup): convert numbers to date before parsing
Closes #5873
Fixes #5871
2016-05-04 09:04:55 -06:00
Wesley Cho a417ec2ab9 fix(datepicker): add intermediary valid date check
- Add intermediary check for whether the date is valid due to an IE quirk of turning a valid date into an invalid date when using the date constructor

Closes #5872
Fixes #5865
2016-05-03 13:15:34 -07:00
Wesley Cho d923df9100 chore(dateparser): port logic from Angular
- Port logic from timezone converter from Angular

Closes #5870
2016-05-03 09:47:07 -07:00
Wesley Cho dd09148893 feat(modal): add resolve values to template
- Expose resolve in template as $resolve for those modals opened with a controller

BREAKING CHANGE: 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

Closes #5808
Closes #5857
2016-04-29 12:02:34 -07:00
ruiann 5741be9d5b chore(modal): use $controller to apply controllerAs
- Change to use `$controller` to apply the `controllerAs` feature

Closes #5861
2016-04-29 08:58:49 -07:00
Scotty Waggoner 1611248daa docs(progressbar): fix danger reference
Closes #5854
2016-04-28 08:35:25 -07:00
Bohdan L e51373d84b chore(readme): fix link
Closes #5852
2016-04-28 07:40:43 -07:00
Perry Hoffman 4c40d9db7f feat(accordion): add alternative attribute support
- Add support for alternative attributes

Closes #5834
Closes #5839
2016-04-27 21:24:56 -07:00
crhistian26 f88067a04f docs(accordion): fix typo
Closes #5838
2016-04-24 21:32:27 -07:00
Wesley Cho 0137179ee6 docs(accordion): add example with custom header
- Add an example with custom header template

Closes #5831
Fixes #5829
2016-04-21 09:53:53 -07:00
Dolev Dori 2b48259a35 fix(dropdown): align position with vertical scrollbar
- Correctly aligns the dropdown when a vertical scrollbar is present

Closes #5830
Fixes #4317
2016-04-20 07:38:04 -07:00
Karl Sieburg 241fea8355 feat(tabs): pass the selected index to onDeselect
-  Add the index of the tab the user attempted to open to the onDeselect call
Closes #5820
Closes #5821
2016-04-19 13:24:01 -07:00
bryanbak f0e661c7c0 docs(tabs): get rid of 'active' option on uib-tab directive
Update demo to remove deprecated active attribute

Closes #5809
2016-04-14 13:31:27 -07:00
Wesley Cho 78db2cefe7 chore(release): starting 1.3.3 2016-04-14 08:32:07 -07:00
Wesley Cho 5eab8ffc49 chore(release): 1.3.2 2016-04-14 08:27:49 -07:00
Daniel Gornstein 68200bbccb fix(dropdown): stop esc keydown event
Fixes #5778
Closes #5787

BREAKING CHANGE: Stops propagation of keydown event when escape key is pressed. Removes keydown event from the document and moves it to the dropdown element.
2016-04-13 10:11:54 -07:00
Jean-Francois Larouche 68ed7ab477 docs(datepicker): fix customClass and dateDisabled
- Fix documentation for customClass and dateDisabled functions

Closes #5797
Fixes #5757
2016-04-13 06:37:22 -07:00
robjacobs d96d53ec32 fix(tooltip): arrow position
- Ensure the arrow position gets recalculated if the tooltip
position changes while open.

Closes #5785
Fixes #5779
2016-04-12 12:43:47 -07:00
robjacobs aef08d5555 fix(modal): scroll padding only added once
- Ensure the scroll padding meant to offset the modal-open class
only gets added once when mulitple modal windows are open.

Closes #5790
Fixes #5789
2016-04-12 12:41:42 -07:00
Wesley Cho a27a4e2204 feat(modal): add no css import script
- Add index-nocss.js for modals

Closes #5788
2016-04-12 09:09:15 -07:00
Mike Chen a887d2b4c9 fix(modal): missing require in modal
- Fix incorrect require of css instead of position module

Closes #5786
2016-04-12 08:21:33 -07:00
Paul des Garets bba3f27e3d fix(typeahead): use $setViewValue on blur
Use $setViewValue instead of setting directly $viewValue to '', to make new value go through validators.

Closes #5769
Fixes #5694
2016-04-07 15:26:13 -07:00
Wesley Cho 3d7191cc06 chore(isClass): clean up code style 2016-04-06 15:19:38 -07:00
Wesley Cho 32f78b8718 chore(isClass): clean up code style 2016-04-06 15:19:27 -07:00
Wesley Cho 4044f08980 chore(isClass): clean up code style 2016-04-06 15:19:16 -07:00
Wesley Cho 33cbd0f4a2 fix(datepicker): ensure datepicker is focused
- When date is selected, ensure datepicker is selected in Chrome

Closes #5761
Fixes #5754
2016-04-06 13:32:41 -07:00
Wesley Cho 3b8f18e373 chore(datepicker): change to single quotes 2016-04-06 10:34:08 -07:00
Wesley Cho 0f3a5214f4 chore(site): add guard to accessing global 2016-04-06 09:04:48 -07:00
Chris Thielen 37f9cd26e5 fix(site): allow FastClick to be blocked
Some users' adblock and virus protection is accidentally blocking third party `fastclick.js`.

Put a guard around the line that invokes the FastClick api

Closes #5756
2016-04-06 08:41:18 -07:00
Abdellatif Ait boudad 169c50403c docs(datepicker): remove popup example.
Closes #5755
2016-04-06 06:24:11 -07:00
Wesley Cho 38a334c7d8 chore(timepicker): remove inline style
- Remove inline style due to style being present in CSS

Closes #5751
2016-04-06 06:22:49 -07:00
Wesley Cho c05aefe96d chore(release): start 1.3.2 for real 2016-04-05 10:05:44 -07:00
Daniel Gornstein 98eb8f1a77 fix(datepickerPopup): do not show incorrect warning
This stops the datepicker popup from incorrectly showing a warning when not supplying any datepicker options.

Fixes #5743
Closes #5747
2016-04-05 09:46:25 -07:00
Wesley Cho 1c6c7b913c chore(release): starting 1.3.2 2016-04-05 07:39:19 -07:00
Wesley Cho 1519c4b46d chore(release): 1.3.1 2016-04-05 07:36:01 -07:00
Abdellatif Ait boudad 86ee9c3af1 fix(datepickerPopup): register popup module
Closes #5745
2016-04-05 07:34:25 -07:00
Pem Taira a08ad700f6 fix(modal): ensure correct index is set
- Fixes index set to avoid potential concurrent z-index values for multiple modals

Closes #5733
Fixes #5670
2016-04-04 22:20:00 -07:00
Wesley Cho 4ec35e4dcb chore(release): starting 1.3.1 2016-04-04 21:19:11 -07:00
Wesley Cho daf5c820e3 chore(release): 1.3.0 2016-04-04 21:16:08 -07:00
Adam Gordon d767afbd2a fix(tab): fix event handler call
* switch event handler call to look at `event.isDefaultPrevented()` instead of
  `event.defaultPrevented` as angular has implemented that method on jqlite
  events.

Fixes #5720
Closes #5738
2016-04-04 09:48:43 -06:00
robjacobs 701e0cbded feat(dateparser): use 68 as the yy format pivot year
- Use the same pivot year (68) for 2 digit date years as moment.js.
68 becomes 2068, 69 becomes 1969.

Closes #5735
2016-04-04 08:16:58 -07:00
Wesley Cho fc02fd1e30 feat(datepicker): deprecate literal usage
- Deprecate support for non-date objects with the datepicker

Closes #5658
Closes #5732
2016-04-04 08:15:09 -07:00
Türker Teke 4fe5d9936d docs(datepicker): fix creation of afterTomorrow
Closes #5714
2016-03-31 14:57:12 -07:00
Adam Gordon e0fcc004c0 fix(tab): add support for tab deselect prevention
* add ability for user to prevent currently selected tab's deselection by
calling `$event.preventDefault()` in tab's `deselect` callback.

Fixes #5720
Addresses #2715, #4836, and #5716.
Closes #5723
2016-03-31 14:15:08 -06:00
robjacobs cca1460eb0 fix(popover): rename title attribute
- Using an attribute of title on the tooltip template was
causing the browser tooltip to display.

Fixes #5719
Closes #5721
2016-03-31 13:47:12 -04:00
robjacobs c83d0a8daf fix(modal): body content shift
- Implements TWBS body padding fix to keep content in an element
with a container class from shifting when the body overflow is
set to hidden with the modal-open class.

Fixes #2631
Closes #5711
2016-03-30 18:01:49 -07:00
plondon a3964d4d81 feat(carousel): disable prev/next arrows if at bounds
- When at bounds and noWrap is enabled, disable the prev and next arrows when appropriate

BREAKING CHANGE: 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

Closes #5704
Closes #5708
2016-03-30 08:29:30 -07:00
Charlie Rudolph 434c1c595b fix(carousel): use proper sort comparison
Fixes #5638
Closes #5702
2016-03-28 12:49:42 -07:00
Foxandxss 48f62a6dad chore(timepicker): remove css require on noncss 2016-03-27 19:05:25 +02:00
Foxandxss 1fa358fa6b chore: update devDependencies 2016-03-27 13:55:22 +02:00
Foxandxss 393d00e415 chore: update to Angular 1.5.3 2016-03-27 13:43:48 +02:00
Wei Wang 80748994a3 fix: modify CSS loaded for modules with dependencies
- Modify loading of CSS to be purely in the index.js files for modules that depend on other modules with CSS files

Closes #5698
2016-03-26 22:56:47 -07:00
Wesley Cho e50f602488 chore: add another exclusion 2016-03-26 15:16:27 -07:00
Wesley Cho f57302707c chore: fix improper build 2016-03-26 15:14:58 -07:00
Wei Wang de504fb512 feat: add support for loading without CSS
- Add support for loading components without bringing along the CSS,
  which is necessary for SystemJS/JSPM users

Closes #5696
2016-03-26 14:57:10 -07:00
Wesley Cho daf3b2e7f7 chore: remove patch version 2016-03-26 14:56:31 -07:00
Wesley Cho 41e670c34a chore: update node on Travis 2016-03-26 14:52:12 -07:00
Wesley Cho d1c49fe342 docs(timepicker): add note about DST
- Add note about DST, and declare explicit intent to not support
  concurrent usage of the date object with the timepicker and datepicker

Closes #5693
2016-03-25 22:21:32 -07:00
Wesley Cho f6735dc2bb test(dateparser): add literal tests
- Add broken tests for dateparser literals

Closes #5692
2016-03-25 22:20:35 -07:00
Tom Yau 03e60479d4 fix(tab): correctly identify index on removal
- Fix tab remove when tabs are destroyed in the middle

Closes #5689
2016-03-24 12:26:21 -07:00
Alexander Surinov 449c0d11d6 feat(timepicker): remove automatic padding when empty
- Removes automatic padding when input is empty to allow ability to manipulate inputs on user's side

Closes #5293
Closes #5299

BREAKING CHANGE: This removes automatic padding done by the timepicker
when the input is empty - if that behavior is desired, write a custom
directive implementing it
2016-03-24 06:54:10 -07:00
Ryan McKeel c534cb4a94 feat(dropdown): remove $locationChangeSuccess listener
- Remove listener for $locationChangeSuccess event

BREAKING CHANGE: 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.

Closes #5648
Closes #5680
2016-03-22 12:19:32 -07:00
Wesley Cho 45165ba58b feat(datepicker): watch for changes when falsy
- When initial value is falsy, continue to watch for changes to update

Closes #5672
Closes #5677
2016-03-22 11:36:37 -07:00
Wesley Cho 8590ea7240 chore(dropdown): avoid IE11/Edge rendering bug
- Add `dropdown-menu` class to avoid rendering bug in IE11/Edge

Closes #5675
Fixes #5595
2016-03-22 11:35:59 -07:00
Wesley Cho 44fb19bc83 fix(carousel): fix animation from programmatic trigger
- Fix animations of slides when programmatically changing active slide
  index

Closes #5674
Fixes #5601
2016-03-22 11:35:19 -07:00
Wesley Cho fbc873cfb2 feat(datepickerPopup): split off popup from datepicker
- Split off datepicker popup into new datepickerPopup module

BREAKING CHANGE: 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

Closes #5676
2016-03-22 07:46:19 -07:00
Wesley Cho ad91c82164 feat(datepicker): remove deprecated code
- Remove all deprecated attribute support

BREAKING CHANGE: This removes inline datepicker attribute support and
attribute pass-throughs in the popup

Closes #5660
2016-03-21 11:11:13 -07:00
Adam Misiorny 46ff62dd75 docs(tooltip): fix example
Closes #5666
2016-03-21 11:06:31 -07:00
Adam Misiorny 34adfbce01 chore(tooltip): add missing space
Closes #5664
2016-03-21 09:03:54 -07:00
Foxandxss 307d8992a8 chore: update to Angular 1.5.2
Closes #5663
2016-03-21 09:02:20 -07:00
Wesley Cho fa46e16eab chore(release): starting 1.3.0 2016-03-20 09:04:42 -07:00
Wesley Cho 6955cf0079 chore(release): 1.2.5 2016-03-20 08:59:14 -07:00
Wesley Cho c7be087ca0 feat(timepicker): add pad-hours support
- Add support for optionally padding hours

Closes #4288
Closes #5633
2016-03-18 11:29:48 -07:00
Wesley Cho 1b888d4b0e fix(datepicker): dereference date initialization
- Dereference the date set to active date to prevent model automatically
  updating from equal reference

Closes #5643
Fixes #5441
2016-03-18 11:27:25 -07:00
Wesley Cho 5ef56e2de8 feat(modal): exclude hidden elements from query
- Modify element query to exclude hidden elements

Closes #5512
Closes #5644
2016-03-18 09:00:12 -07:00
mbisioli bc7c55aec8 fix(typeahead): reset errors when clearing
- Reset validation errors when clearing

Closes #5641
2016-03-16 19:31:42 -07:00
Wesley Cho 316e96c9b0 fix(datepicker): fix today button disabled condition
- Fix conditional for today button in popup

Closes #5637
Fixes #5622
2016-03-16 10:46:09 -07:00
Kaiyu Hsu 8747b585f4 feat(rating): ability to disable rating reset
Closes #5532
Closes #5631
2016-03-15 09:18:01 -07:00
Wesley Cho e15a22a8d4 fix(modal): dynamically fetch elements
- Dynamically fetch elements for determination of which is the first/last to tab/shift+tab to

Closes #5630
Fixes #5050
Fixes #5421
2016-03-15 08:58:58 -07:00
Wesley Cho bb36e40582 feat(tab): add select expressions
- Add support for event being available in select/deselect
  callbacks

Closes #5438
2016-03-14 12:33:39 -07:00
Thorsten Möller 7f93bfc16f docs(popover): add popover-enable
Closes #5615
Closes #5626
2016-03-14 12:19:57 -07:00
Spencer 1714a388b4 docs(popover): add popoverHtml usage
Closes #5617
2016-03-10 16:48:53 -08:00
robjacobs 66c416cf77 fix(tooltip): css to support arrow positioning
- Added css selectors to support arrow positioning on
popover/tooltip html and template directives.

Fixes #5610
Closes #5611
2016-03-09 09:40:26 -08:00
Ivan Voznyakovsky f2004a9186 docs(tab): remove old incorrect attribute blurb 2016-03-09 07:01:02 -08:00
philjones 54ac06af80 fix(popover): add popover-html css
- Add base CSS for popover-html

Closes #5603
Fixes #5602
2016-03-08 09:17:34 -08:00
Daniel Blanco ffb5529771 feat(accordion): add bound panel-class support
- Add `@` binding support for `panel-class`

Closes #5368
Closes #5596
2016-03-07 14:14:11 -08:00
Wesley Cho d6b9ee17e5 chore(release): starting 1.2.5 2016-03-06 07:08:57 -08:00
Wesley Cho 7cbf957a0e chore(release): 1.2.4 2016-03-06 07:05:09 -08:00
Wesley Cho 800c153ebd chore(release): starting 1.2.4 2016-03-05 22:48:32 -08:00
Wesley Cho 6f3800f860 chore(changelog): update with 1.2.3 changes 2016-03-05 22:47:23 -08:00
Wesley Cho fe30e5151e chore(release): 1.2.3 2016-03-05 22:43:30 -08:00
Wesley Cho a945dd247a fix(tabs): support heading with :
- Support `uib:tab-heading`

Closes #5590
Fixes #5568
2016-03-05 20:53:43 -08:00
Wesley Cho aac0d2b8fe fix(dropdown): correctly update isOpen
- Update bound value of `isOpen` correctly on toggle

Closes #5589
Fixes #3261
2016-03-05 17:46:29 -08:00
Wesley Cho 7949494493 fix(typeahead): change to original scope
- Change to original scope for running $digest

Closes #5588
Fixes #5467
2016-03-05 11:32:55 -08:00
Wesley Cho dd62c73a1a fix(modal): switch to $animate
- Change to adding backdrop with $animate.addClass due to $animateCss
  issues when animation is disabled

Closes #5585
Fixes #5298
2016-03-05 10:47:04 -08:00
Daniel Gornstein 313ba83793 fix(typeahead): update isOpen on escape
This updates isOpen immediately when pressing escape button.

Fixes #5579
Closes #5587
2016-03-05 10:46:08 -08:00
Dave Anderson 94c34b781f docs(datepicker): link to ngModelOptions documentation
fixes #5583
closes #5586
2016-03-05 10:06:27 -08:00
Wesley Cho 0beb06f24a chore(modal): remove unnecessary injection
- Remove unnecessary variable

Closes #5584
2016-03-05 08:02:23 -08:00
robjacobs a516178635 fix(position): auto position append to body
- Use the body as the viewport to determine available size for
auto position when the target element is append-to-body

Closes #5582
Fixes #5576
2016-03-04 12:21:46 -05:00
Wesley Cho c15dcbd1d1 feat(datepicker): add helpers for styling
- Add helper variables available for custom templates to hook into for styling

Closes #5580
2016-03-03 16:16:50 -08:00
Wesley Cho 4b06b0bcda chore(release): starting 1.2.3 2016-03-03 07:41:38 -08:00
Wesley Cho 55d9c3f48d chore(release): 1.2.2 2016-03-03 07:37:05 -08:00
Kuitos 5e43870c5d fix(modal): fix bindToController props
- Bind provided $scope props to controller before instantiation
- Make $onInit available regardless of controllerAs usage

Closes #5569
2016-03-03 07:27:33 -08:00
Adam Gordon 9d74d6ce50 fix(tabs): update doc and fix tab demo
* update tab documentation to clarify proper use and intended behavior of the
  `active` attribute on both the `tabset` and `tab` directives.
* fix the tab select buttons in the tab demo.

Closes #5575
Fixes #5551
2016-03-02 13:18:32 -08:00
Wesley Cho 4369800682 fix(rating): fix usage of aria-valuetext
- Fix usage to be on top level element

Closes #5573
Fixes #5571
2016-03-02 13:16:55 -08:00
Wesley Cho 09b2150eb0 docs(pager): fix templateUrl reference 2016-03-01 16:28:38 -08:00
Wesley Cho a816251c9f fix(Gruntfile): add per module flag
- Add flag per module

Closes #5567
2016-03-01 13:11:35 -08:00
dasu908 299f7517b6 fix(modal): fire ng-leave on close
- Have $animate execute class changes on window close

Closes #5556
Fixes #5399
2016-03-01 10:43:41 -08:00
Foxandxss d68086f978 fix(position): add CSS for webpack support
Closes #5561
2016-03-01 10:42:38 -08:00
Kyle Upchurch dd844ad8b3 docs(popover): correct default trigger
Closes #5564
Closes #5566
2016-03-01 10:41:41 -08:00
Matt Lewis 679a8d54a7 docs(changelog): add missing carousel breaking change
Closes #5565
2016-03-01 10:40:41 -08:00
Corey Wilson cc2d1b90c3 fix(tests): add style tag once
- Add style tag once to avoid multiplied DOM creation

Closes #5557
Fixes #5548
2016-02-29 19:14:00 -08:00
Matt Lewis c8922a2f04 fix(tooltip): import CSS
- Import the CSS in the tooltip index.js

Closes #5552
2016-02-29 14:26:27 -08:00
Adam Gordon 7d79cdddd2 docs: fix changelog for tab breaking change
* add breaking change note for 1.2.0 release for tab change in #5430.

Closes #5555
2016-02-29 12:45:30 -08:00
Wesley Cho bd55e14de5 chore(release): starting 1.2.2 2016-02-27 09:31:04 -08:00
Wesley Cho a9e810d0af chore(release): 1.2.1 2016-02-27 09:24:52 -08:00
Wesley Cho 70c1c9079a fix(popover): add missing selector
Closes #5549
2016-02-27 09:21:24 -08:00
Wesley Cho 1b709e5a5c chore(release): starting 1.2.1 2016-02-26 11:07:21 -08:00
Wesley Cho 43daa97561 chore(changelog): update changelog 2016-02-26 11:06:55 -08:00
Wesley Cho a69f4d29a8 chore(release): 1.2.0 2016-02-26 11:01:22 -08:00
Wesley Cho deedaea250 chore(pagination): minor tweaks 2016-02-26 07:32:20 -08:00
Andrew Shaffer 785c373241 feat(pagination): add custom label support
- Add ability to customize labels with `pageLabel` attribute

Closes #2532
Closes #5547
2016-02-26 07:31:29 -08:00
Ayman Mahfouz 8364e76bb4 feat(tabs): support optional classes on tab
- Add support for optional classes on each tab

Closes #5430
2016-02-25 14:23:27 -08:00
Foxandxss 85751551e3 docs(tooltip): add badge to appendToBody
Closes #5544
2016-02-25 10:25:12 -08:00
Wesley Cho d546671717 chore(ci): bump up node to 5.7 2016-02-25 09:43:13 -08:00
Graham Rounds 19e4171dfe docs(pager): add current page indicator
Add current page indicator to better convey pager behavior.

Closes #5524
Closes #5543
2016-02-25 09:37:23 -08:00
Foxandxss 2968f4cb9e docs(modal): document $onInit
Closes #5542
2016-02-25 09:35:58 -08:00
Foxandxss 876974973e fix(datepicker): assign initDate correctly to the controller
Closes #5541
2016-02-25 09:35:31 -08:00
Foxandxss 97244c7e64 chore(datepicker): change deprecation message for popup
Closes #5540
2016-02-25 09:34:51 -08:00
Foxandxss 1cc142b225 docs(datepicker): update to latest usage
Closes #5539
2016-02-25 09:34:11 -08:00
AndriIushchuk ab5941315f fix(datepicker): check if initDate is valid
Closes #5190
Closes #5266
2016-02-24 14:26:04 -08:00
robjacobs 4bb178ac5b fix(position): move inline styles to a class
- Move all inline styles supporting the auto position and
flicker suppression to a class.
- Refine how placement classes get applied to the tooltip

Closes #5535
Fixes #5470
2016-02-24 14:20:26 -08:00
Wesley Cho bbc4912d55 feat(datepicker): preserve popup attributes
- Preserve usage of specific popup attributes
- Change from attributes to options in demo

Closes #5537
2016-02-24 13:18:35 -08:00
Wesley Cho d880aea9b6 feat(datepicker): move attribute support to options
- Move some attribute usage to datepickerOptions

Closes #5528
2016-02-24 10:54:27 -08:00
rasenplanscher b24524280c fix(buttons): fix uncheckable attribute
- Fix behavior of `uib-uncheckable` to agree with intention

Closes #5451
Fixes #5412
2016-02-23 17:12:44 -08:00
Igor Bulovski 47e412ec0b fix(datepicker): fix popup updateOn: default support
- Fix support for ng-model-options with `updateOn: blur`

Closes #5529
2016-02-23 17:09:51 -08:00
Wesley Cho 74a1d04e27 feat(datepicker): move datepicker mode to options
- Fully move datepickerMode support to datepickerOptions, deprecate attribute usage

Closes #5526
2016-02-23 13:30:12 -08:00
robjacobs 3c0a7cd57c feat(position): add isScrollable
Add the isScrollable function that will check if the element passed
in is scrollable.

Closes #5508
2016-02-22 13:39:09 -05:00
robjacobs fa17c483e0 feat(tooltip): arrow position
- Move arrow position style overrides to a class instead of inline
styles.  This will allow for consumers to position the arrow to
suit their needs by setting margins on the arrow element.
- Optimize when the positionTooltip function calls the
positionArrow function.  Now the arrow position will only be
recalced when the tooltip placement changes.

Fixes #5464
Closes #5502
2016-02-22 13:30:57 -05:00
Adam Gordon 6fd47892ce chore(docs): create new issue template
* create new template for UIBS issues

Closes #5507
2016-02-19 10:15:44 -07:00
Foxandxss 69aae3547f chore: add angular-touch instructions to homepage 2016-02-19 13:12:01 +01:00
Daniel Gornstein 96c686611d chore(readme): Update installation notes
Note that the carousel requires ngTouch for swiping.

Closes #5499
Closes #5500
2016-02-19 13:04:59 +01:00
Daniel Smith 834975899b feat(modal): Call $onInit on controller if defined
Fixes #5472
Closes #5509
2016-02-19 13:03:32 +01:00
Daniel Gornstein 64e3127479 fix(typeahead): fix shift tab
Stops the tab completion action from happening when shift key is also pressed.

Closes #5494
Fixes #5493
2016-02-16 22:15:11 -05:00
robjacobs d1553a450f fix(tab): make active optional
This change makes the active binding added under #5425 optional.

Closes #5489
2016-02-16 17:51:12 -08:00
robjacobs 8b3e86f2c6 fix(position): getRawNode to handle select/ul elem
The getRawNode function was not returning the correct object
for collection elements (select, ul, etc...).

Closes #5491
Fixes #5354
2016-02-16 17:47:53 -08:00
Daniel Gornstein 417850001d fix(typeahead): Fix tab index for hint input
Fixes needing to hit tab twice to tab into typeahead with show hint enabled.

Fixes #5478
Closes #5492
2016-02-16 14:05:18 -08:00
Dave Birch 3814fe3ad1 fix(tabs): adding bootstrap 4 specific class
- Add `nav-link` class for Bootstrap 4

Closes #5488
2016-02-16 14:58:57 -05:00
Tuomo Jokimies 979fe0bad1 fix(modal): fix race condition with openedClass
- Fixes race condition with modal if it is closed before animation is complete

Closes #5483
2016-02-16 11:11:44 -05:00
Alejandro Vales 57326a9b35 docs(typeahead): improve setting definitions
Closes #5480
2016-02-15 21:51:40 +01:00
robjacobs f9903baf14 feat(datepicker): implement auto position
Added popup-placement attribute that implements the auto position
feature that exists in the tooltip directive.  Accepts the same
placement options as the tooltip.

Closes #5444
2016-02-12 23:33:54 -08:00
Cameron Chamberlain b8353322be docs(progressbar): fix reference to -danger
Closes #5462
2016-02-11 06:56:57 -08:00
Wesley Cho b95d1e2b2a chore(npm): add index.js
Closes #5461
2016-02-10 15:07:58 -08:00
Graham Rounds 54c51c4ffc feat(tab): add template-url support
- Adds support for `template-url` for tabset and tab directives

Closes #5405
Closes #5443
2016-02-09 06:13:53 -08:00
Foxandxss c5397a893b chore: lock angular version
Closes #5447
2016-02-09 06:12:20 -08:00
Foxandxss b808c0ddfe refactor(datepicker): normalize variable naming
Closes #5450
2016-02-09 06:10:29 -08:00
Wesley Cho cd2f050f2f chore: update with version support
- Update to note support for 1.5
- Bump up the ngversion for Plunker

Closes #5437
2016-02-08 14:36:29 -08:00
Wesley Cho 32a247471f refactor(carousel): change to use centralized active state
- Change so active state is primarily on two-way bound variable

Closes #5353
Closes #5432

BREAKING CHANGE: This changes the active state to be in line with
similar components centralizing the information. Please refer to the
carousel documentation for usage.
2016-02-08 12:03:20 -08:00
Foxandxss a35a63d4f9 refactor(paging): remove extra
Closes #5442
2016-02-08 12:02:34 -08:00
Wesley Cho d7b6aa1206 docs(tab): add backticks 2016-02-08 07:23:38 -08:00
Wesley Cho 74e129dc28 docs(tab): remove old property 2016-02-08 06:28:01 -08:00
Wesley Cho 5ec19b643b refactor(tab): change to use centralized active state
- Change to store active index on tabset controller
- Set index on tab by tab basis

Closes #5425

BREAKING CHANGE: The tab API is changed - please refer to the
documentation on new usage of tabs. Note that if you are using custom
templates, the templates will need to be changed slightly.
2016-02-08 06:22:45 -08:00
zach_lysobey 946b7e040b docs(contributing): fix conventions link
Closes #5434
Fixes #5429
2016-02-07 13:06:10 -08:00
zach_lysobey d5a757d46d fix(rating): change to read-only
Closes #5371
Closes #5435

BREAKING CHANGE: Attribute supported has been changed to `read-only`
from `readonly`
2016-02-07 12:54:36 -08:00
Wesley Cho 01e199815f test(modal): gc elements
Closes #5433
2016-02-07 07:55:40 -08:00
Prayag Verma 2116f7e4a4 docs(contributing): fix typo
- Remove redundant word
2016-02-05 23:15:13 -08:00
Wesley Cho 10eac7c22b feat(datepicker): add deprecation notices
- Add deprecation notices for datepicker & popup

Closes #5415
2016-02-05 16:08:27 -08:00
Patrick Lawler e4fc20167b fix(datepicker): fallback to current date
- Fallback to current date if model not present

Closes #5418
Fixes #5417
2016-02-05 14:44:44 -08:00
Jacobs 068d18189b test(tab): fix ng-repeat select twice callback
The select callback for the ng-repeat select test twice was bound
to the scope callback instead of the select property in the tabs
array.

Closes #5419
2016-02-05 13:34:10 -08:00
josh_burson@intuit.com 9c0acf67eb chore(dropdown): avoid toggling class on first load
- Avoid toggling class on first load of directive

Closes #5341
2016-02-04 17:11:28 -08:00
Sam Julien ca6b177db1 feat(accordion): use attribute for heading insertion
- Change to use `uibAccordionHeader` attribute for insertion point for header transclusion

Closes #5324
Closes #5396

BREAKING CHANGE: This changes to use the `uibAccordionHeader` attribute instead of a `<span>` 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.
2016-02-04 13:31:48 -08:00
Nicolas del Valle a5aebda854 docs(modal): fix service reference
- Fix reference to $uibModalInstance

Closes #5411
2016-02-03 14:46:25 -08:00
germannj f81d440ba6 feat(typeahead): add dynamic min length support
- Add support for dynamically changed min length

Closes #5363
2016-02-03 09:25:38 -08:00
Wesley Cho 42fb486735 fix(modal): fix modal rendered promise
- Fix timing of rendered promise to be after animation is complete

Closes #5401
Fixes #5331
2016-02-03 09:17:21 -08:00
Wesley Cho e283cea0e4 fix(datepicker): stop event bubbling from buttons
- Stop event bubbling from clicks in popup

Closes #5400
Fixes #5347

BREAKING CHANGE: This requires $event to be passed in the second
argument of the select function and in the close argument for the popup
template
2016-02-03 09:08:15 -08:00
Foxandxss 853d302356 chore(changelog): remove doc line 2016-02-03 18:03:46 +01:00
Martin Nuc 258b3413be fix(progressbar): fix default max value
- Fix logic around falling back to default max value

Closes #5374
Fixes #5373
2016-02-02 14:35:30 -08:00
Jenny Gebske 81498a7c6a docs: add info about CSS with CSP
Closes #5397
2016-02-02 14:31:28 -08:00
Wesley Cho 4b2ee0fa85 fix(datepicker): default to current date
- When model is empty, default to current date

Closes #5395
Fixes #5190
2016-02-02 14:17:03 -08:00
Graham Rounds f125537610 fix(datepicker): adjust datepicker header buttons
- Adjust the CSS for the datepicker header buttons to not have inconsistent spacing due to Chrome browser differences

Closes #5393
Fixes #5392

BREAKING CHANGE: 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
2016-02-02 10:07:16 -08:00
Wesley Cho 5c565df024 fix(dateparser): append end of format
- Ensure trailing format string is appended to generated date string

Closes #5385
Fixes #5387
2016-02-02 06:03:46 -08:00
Foxandxss 3a03f293b5 chore: add lodash as devDependency
Closes #5383
2016-02-02 00:31:08 +01:00
Foxandxss e4c88bf54b chore: fix version mapping
Closes #5382
2016-02-01 15:17:03 -08:00
Foxandxss e645ab78a2 chore: add support for webpack
Closes #5375
2016-02-01 09:11:57 -08:00
Wesley Cho 3e10184c1c feat(datepicker): pass options from popup to inline
- Pass through options object wholesale from popup to inline datepicker

Closes #5355

BREAKING CHANGE: This breaks any snake-cased key usage, i.e.
`show-weeks`. Convert all keys used to camelCase.
2016-02-01 09:11:20 -08:00
Wesley Cho d88c0fb117 chore(release): start 1.2.0 2016-02-01 09:04:59 -08:00
Wesley Cho 15c5c503a4 chore(changelog): update for 1.1.2 2016-02-01 09:04:43 -08:00
Wesley Cho dbd3947002 chore(release): 1.1.2 2016-02-01 08:58:21 -08:00
Wesley Cho c3b14315d9 fix(datepicker): fix validation for M! & d!
- Fix display & validation for M! & d!

Closes #5376
Fixes #5225
2016-02-01 08:14:25 -08:00
Matthew McLeod 48c9cd8f51 fix(tooltip): prevent closing on $locationChangeSuccess
- Remove incorrect logic for closing tooltip/popover on
  $locationChangeSuccess

Closes #5360
Fixes #5337
2016-01-28 09:14:21 -08:00
Wesley Cho 0b7e742f6e docs(carousel): make sure request is made to http
- Ensure request uses http protocol and not https potentially

Closes #5359
2016-01-28 09:13:47 -08:00
Wesley Cho dbe9e8171f fix(typeahead): add guard for no $viewValue
- Add guard when $viewValue is undefined, and when showHint & min-length
  0 is used

Closes #5358
Fixes #5357
2016-01-28 09:12:20 -08:00
AndriIushchuk d2621e3f98 fix(modal): ensure shift+tab is trapped in modal
- Fixes where shift+tab keystrokes are not causing focus to remain
  trapped in modal

Closes #5294
Fixes #5229
2016-01-28 06:16:40 -08:00
Foxandxss b1ad080741 docs(datepicker): fix italics 2016-01-28 00:36:21 +01:00
Wesley Cho e58c42c5b2 feat(datepicker): add datepickerOptions support
- Add support for options object to concisely configure datepicker

Closes #5340
2016-01-27 04:19:08 -08:00
Towne, Jeremy 61cdef1ee6 feat(accordion): add aria tags
- Improve accessibility of accordion

Closes #5338
2016-01-26 08:11:29 -08:00
Wesley Cho 56f5c82c72 chore(release): start 1.1.2 2016-01-25 08:13:31 -08:00
Wesley Cho 2af95a2cd4 chore(release): 1.1.1 2016-01-25 08:06:36 -08:00
Foxandxss 096e171137 test(datepicker): refactorize some tests
Closes #5336
2016-01-25 00:56:19 +01:00
Foxandxss 97af6a99dd fix(datepicker): allow using min/max mode/date with datepickerOptions
Closes #5334
Fixes #5315
2016-01-23 16:11:02 -08:00
andrej.anafinow d5a48eaff0 fix(modal): fix modal closed resolution
- Correctly resolve modal closed promise on close or dismissal

Closes #5322
Closes #5326
2016-01-21 10:52:15 -08:00
Wesley Cho 5fcca2e83b chore(docs): bump angular to 1.4.9 2016-01-21 09:56:33 -08:00
Adam Gordon 8f94fe84b0 fix(doc): fix changelog for issue 5186
* update changelog to indicate bug fix #4753.
* update changelog to indicate PR #4975.
* update changelog breaking changes to indicate change made.

Fixes #5186
Closes #5325
2016-01-21 10:17:34 -07:00
Wesley Cho f303df419b docs(accordion): add note about ng-class
- Adds note about custom class usage for the accordion-group

Closes #5317
2016-01-20 22:13:50 -08:00
Alexander Artemenko 9050949b79 chore(changelog): unify markdown to template
Closes #5308
2016-01-20 10:15:58 -08:00
Adam Gordon 5325559795 chore(docs): add note for tooltip and popover on mobile
* update popover readme indicating we will not support issues on mobile devices.
* update tooltip readme indicating we will not support issues on mobile devices.

Closes #5307
2016-01-19 17:20:20 -07:00
Wesley Cho 594a312645 chore(datepicker): change bind method 2016-01-19 12:48:17 -08:00
Wesley Cho b477165816 chore(tooltip): clean up code style 2016-01-19 12:45:24 -08:00
Foxandxss 826228de85 chore: fix version mapping for 1.0.0+
Closes #5302
2016-01-19 17:56:03 +01:00
Wesley Cho 38ba6ec9ea chore(changelog): remove excessive whitespace
Closes #5296
2016-01-18 11:23:31 -08:00
Adam Gordon 77fa33022b chore(doc): clean up changelog
* remove tab CSS bullet since that commit was OBE due to tab template revert.
* combine `position` bullet entries.
* remove trailing whitespace.
2016-01-18 11:54:33 -07:00
Wesley Cho 2a1f1bc182 chore(changelog): update changelog 2016-01-18 10:42:14 -08:00
Wesley Cho c10280618a Revert "chore(changelog): update changelog"
This reverts commit ca04d5bc31.
2016-01-18 10:39:59 -08:00
Wesley Cho ca04d5bc31 chore(changelog): update changelog 2016-01-18 10:39:28 -08:00
Wesley Cho ee889ca841 chore(release): starting v1.1.1 2016-01-18 10:38:29 -08:00
Wesley Cho 3c2b57e9f9 chore(release): v1.1.0 2016-01-18 10:35:14 -08:00
Wesley Cho 332eefb464 feat(datepicker): use $locale for starting day
- Change to fallback to $locale.DATETIME_FORMATS.FIRSTDAYOFWEEK for
  first day column

Closes #4954
Closes #5281
2016-01-18 10:27:27 -08:00
Foxandxss 3b7be53bbe docs: add angular-animate to dependencies
Closes #5290
2016-01-18 06:48:48 -08:00
Wesley Cho 8a3c4b8a6d chore(modal): clean up code style 2016-01-17 07:45:43 -08:00
Foxandxss 4cf6a8334c docs: tune up callbacks
Closes #5285
2016-01-17 07:27:32 -08:00
Foxandxss e4eeb4b55b docs(collapse): order settings
Closes #5284
2016-01-17 06:35:16 -08:00
Wesley Cho 3f809affd3 fix(timepicker): garbage collect parent watchers
- Garbage collect parent $$watchers on $destroy

Closes #5277
2016-01-16 12:17:38 -08:00
Wesley Cho 32b88f1fc7 fix(paging): garbage collect parent $watchers
- Garbage collect parent $watchers on $destroy

Closes #5276
2016-01-16 12:14:39 -08:00
Daniel Gornstein c4171a2de2 chore(datepicker): unregister parent watchers on $destroy
Closes #5242
Closes #5260
2016-01-16 12:12:11 -08:00
Foxandxss a5797b9302 docs(datepicker): add clarifications for the popup
Closes #5280
2016-01-16 11:07:44 -08:00
kwiateusz e105e85d7a fix(typeahead): add guard for destroyed $scope
- Add guard against accessing $scope when it has been destroyed

Closes #5267
2016-01-16 10:51:14 -08:00
Daniel Gornstein f19b657658 docs(datepicker): fix demo input type
- Fixes input demo type and adds note on native datepickers

Closes #5115
Closes #5239
2016-01-16 10:48:22 -08:00
Wesley Cho 62213208e0 docs(timepicker): add note about updating model
- Add note on updating the model value programmatically

Closes #5144
Closes #5278
2016-01-16 05:00:32 -08:00
Mohammed Nauage 1dbad8a057 fix(modal): change to compile before appending
- Change to compile the modal window before inserting into the DOM

Closes #5224
Fixes #5183
2016-01-15 21:40:03 -08:00
Wesley Cho 78ba137383 fix(datepicker): pass through null
- When `minDate` or `maxDate` is `null` in the popup, pass through value to inline datepicker

Closes #5275
Fixes #5238
2016-01-15 16:49:58 -08:00
Daniel Gornstein 2cb3bc2e76 fix(datepicker): fix popup element garbage collection
- Ensures the correct element is selected due to ng-if replacing element with comment tag

Closes #5274
Fixes #5058
2016-01-15 16:09:12 -08:00
jpmitche11 c6504f8fa5 docs(dropdown): add on-toggle attribute
- Add on-toggle attribute to documentation

Closes #5271
2016-01-15 16:07:28 -08:00
Wesley Cho ca0eaab5bb docs(datepicker): fix mention on string literals
Closes #5269
2016-01-15 09:41:46 -08:00
Lubomyr Vyhovskyy 7e93ec95cb fix(datepicker): allow expressions for minMode/maxMode
- Fixes expressions not being parsed for `min-mode` and `max-mode`

Closes #5264
Closes #5268
Fixes #5240
2016-01-15 09:37:09 -08:00
Wesley Cho bcaa221e4b chore(datepicker): fix indentation 2016-01-15 09:05:50 -08:00
Wesley Cho b76e98e16f chore(release): bump to 1.1.0-SNAPSHOT 2016-01-15 07:04:05 -08:00
Wesley Cho 39d8bc699c refactor(accordion): change back to anchor element
- Change back from div element to anchor element

BREAKING CHANGE: This changes the div element in the accordion-group
element back to an anchor element. If one wishes to use more complex
templates inside the accordion group heading, one must override the
template and add the `cursor: pointer` CSS targeting that element.

Closes #5263
2016-01-15 06:38:20 -08:00
Bogdan Alexe 57219aa153 fix(collapse): avoid initial animation when expanded
- Ensures collapse does not animate expanding when initialized as
  expanded

Closes #5199
Fixes #4414
Fixes #5192
2016-01-14 21:17:16 -08:00
Wesley Cho 907c851fd0 fix(tab): revert template change
- Reverts template change to tab
- Adds warning if one desires more complex HTML inside the tab

BREAKING CHANGE: 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

Closes #5262
Fixes #5254
2016-01-14 20:47:51 -08:00
Adam Gordon de249270a8 chore(docs): update readme with requirements
* update readme to list Angular version requirememts.
* update readme to list Bootstrap CSS version requirements.

Closes #5249
2016-01-14 18:53:24 -08:00
Daniel Gornstein b3e6d1750c fix(datepicker): fix popup CSS
Closes #5258
2016-01-14 18:51:54 -08:00
Jeeva Kandasamy 717ea692b9 feat(timepicker): add placeholder for seconds input
- Adds `SS` placeholder for seconds input

Closes #5257
2016-01-14 16:02:54 -08:00
Adam Gordon a47580ed62 fix(tabs): fix tab css cursor
* fix tab cursor for hover state on non-disabled tab.

Closes #5250
Fixes #5247
2016-01-14 13:07:24 -08:00
Daniel Gornstein f523361e9e feat(typeahead): add title to matches
Closes #5252
2016-01-14 12:05:07 -08:00
robjacobs e8b6a83a71 fix(position): positionArrow descendant selector
- The element selector was not limited to direct descendants so
nested tooltip/popover arrow elements were getting selected instead
of the direct descendant arrow element.

Closes #5246
Fixes #5230
2016-01-14 14:48:24 -05:00
robjacobs ea542213bb Revert "Merge branch 'position-fix' of https://github.com/RobJacobs/bootstrap"
This reverts commit a25caa7c00, reversing
changes made to 00ac93e3ec.
2016-01-14 13:10:20 -05:00
robjacobs a25caa7c00 Merge branch 'position-fix' of https://github.com/RobJacobs/bootstrap 2016-01-14 13:00:11 -05:00
Daniel Gornstein 00ac93e3ec fix(typeahead): fix css selector
Closes #5251
2016-01-14 09:44:57 -08:00
robjacobs 9f4c3a5ac8 fix(position): positionArrow descendant selector
- The element selector was not limited to direct descendants so
nested tooltip/popover arrow elements were getting selected instead
of the direct descendant arrow element.

Closes #5246
Fixes #5230
2016-01-14 09:15:52 -05:00
Wesley Cho 3468888ae2 test(tooltip): add test for class change
- Add test for adding the appropriate classes to the tooltip

Closes #5244
2016-01-14 05:47:27 -08:00
Nick 6a2d91bf7c fix(tooltip): fix addClass signature
- Fix the addition of multiple classes

Closes #5235
2016-01-14 04:49:47 -08:00
Stepan Riha 446364ad1b feat(collapse): add callback hooks
- Adds support for collapsing, collapsed, expanding, and expanded
  callbacks

Closes #5194
Closes #5226
2016-01-13 23:00:05 -08:00
Wesley Cho e8201d1f34 feat(typeahead): move inline style to stylesheet
- Move inline style to stylesheet

Closes #5219
2016-01-12 08:11:31 -08:00
Wesley Cho b658b03afe feat(timepicker): move inline styles to stylesheet
- Moves the inline styles in template to stylesheet

Closes #5218
2016-01-12 08:10:50 -08:00
Wesley Cho 6843ab6ea1 feat(datepicker): extract inline styles to stylesheet
- Move inline styles to stylesheet

Closes #5215
2016-01-12 08:10:17 -08:00
Foxandxss 3bacd454e8 refactor(datepicker): order config options
Closes #5222
2016-01-12 08:05:49 -08:00
Wesley Cho 1038c5422f Merge pull request #5216 from nunoarruda/patch-1
chore(license): update copyright year range
2016-01-11 20:40:29 -08:00
Nuno Arruda 5daa6de160 chore(license): update copyright year range 2016-01-12 11:26:24 +07:00
Wesley Cho f608b143c5 chore(build): fix indentation 2016-01-11 19:43:50 -08:00
Wesley Cho 2ebe83e93b chore(release): starting v1.0.4 2016-01-11 19:33:22 -08:00
Wesley Cho c1fbf4d940 chore(release): v1.0.3 2016-01-11 19:30:41 -08:00
Wesley Cho 627a451f53 fix(timepicker): fix injection 2016-01-11 19:26:52 -08:00
Wesley Cho bae7bc809a chore(release): v1.0.2 2016-01-11 19:23:28 -08:00
Wesley Cho 74be568c65 fix(tabs): fix csp check
- Fix CSP check for inline styles

Fixes #5214
2016-01-11 19:18:21 -08:00
Wesley Cho 66d4300734 chore: fix strange indentation 2016-01-11 19:15:23 -08:00
Wesley Cho 234992470e chore(release): fix coverage in npmignore 2016-01-11 18:57:41 -08:00
Wesley Cho 11d18a5252 chore(release): starting v1.0.2 2016-01-11 18:48:48 -08:00
Wesley Cho 2f6fb2abda chore(release): v1.0.1 2016-01-11 18:42:01 -08:00
Daniel Gornstein 3dac5e3450 fix(typeahead): scroll only parent element
- Changes to scroll only parent element when keyboard navigation is used

Closes #5212
Fixes #5180
2016-01-11 18:23:31 -08:00
Wesley Cho db7adf737e feat(tabs): add CSS to css file
- Add tab specific CSS to separate CSS file

Closes #5211
2016-01-11 15:25:06 -08:00
Foxandxss 79fa363d91 docs: add expression badges to popover and tooltip
Closes #5210
2016-01-11 13:53:37 -08:00
Anders D. Johnson 0d1ca858be docs(modal): document DI notation
- Document array notation being allowed for controller for dependency injection and being minification-proof

Closes #5209
2016-01-11 10:59:18 -08:00
Wesley Cho 176f41978b chore: bump Bootstrap to 3.3.6 2016-01-11 08:45:24 -08:00
Foxandxss 4c338eb4fc docs(timepicker): add templateUrl as config
Closes #5205
2016-01-11 06:25:36 -08:00
Foxandxss bd6de24ace docs(popover): add missing dashes 2016-01-11 10:13:02 +01:00
Phil Brown 1340812caa style(tabs): Match Bootstrap tabs / pills styles
Adds all style declarations for Bootstrap (v3.3.6) tabs and pills.

See http://getbootstrap.com/components/#nav

Closes #5202
2016-01-10 22:04:33 -08:00
Daniel Gornstein 9e9c6cf153 fix(timepicker): prevent mixture of numbers and letters
- More strictly parse the expressions for disallowing a mixture of numbers and letters

Closes #5201
Fixes #5085
2016-01-10 18:55:43 -08:00
Daniel Gornstein 4b0e381b01 feat(timepicker): add templateUrl in timepickerConfig
- Sets the default templateUrl in `uibTimepickerConfig`

Closes #5087
Closes #5200
2016-01-10 18:33:31 -08:00
Wesley Cho aa010b024e fix(datepicker): fix error message
- Change error message to reflect what is officially supported as a model value

Closes #5198
Fixes #5191
2016-01-10 09:51:41 -08:00
Wesley Cho 9d0269ea97 fix(build): add ; after script
- Add extra `;` so there is no issue when concatenating scripts

Closes #5197
Fixes #5196
2016-01-10 09:20:32 -08:00
Wesley Cho 7250ff3ad8 docs(dropdown): add note about usage with ngTouch
- Add note about an issue with the click event not bubbling up when
  using ng-click with ngTouch

Closes #5101
Closes #5189
2016-01-10 09:16:03 -08:00
Wesley Cho 63ca2f3755 chore: use template string 2016-01-10 09:01:46 -08:00
sergey makarov 36fca744d5 fix(carousel): reset active for buffered transitions
- Disable active state for slides in buffered transitions

Closes #5195
Fixes #5178
2016-01-10 08:53:13 -08:00
Wesley Cho 428beaff4c fix(datepicker): fix usage of non-standard format
- Fix display of model in input when using a non-standard format with
  the dateparser (i.e. `M!` and `d!`)

Closes #5188
Fixes #5187
2016-01-09 09:11:40 -08:00
Wesley Cho 6ad873fab4 chore: update gruntfile with ES6
- Add some ES6 usage in the gruntfile

Closes #5179
2016-01-09 09:11:03 -08:00
Adam Gordon 84bb118b35 chore(docs): fix popover and tooltip docs
* update popover and tooltip docs to indicate that the `uib-*-html` attribute
  does not get compiled
* addresses complaint in #4923

Closes #5184
2016-01-09 06:17:16 -08:00
Daniel Gornstein 71afeeb6e3 fix(timepicker): use correct disabled expression
Closes #5185
Fixes #5182
2016-01-09 05:22:53 -08:00
Foxandxss a42266c956 chore(carousel): change images on demo
Closes #5106
2016-01-08 11:27:15 -08:00
Wesley Cho 2dfa1f5c53 chore(docs): bump angular to 1.4.8 2016-01-08 09:46:41 -08:00
Wesley Cho 16c7f9fbf1 chore(release): Starting v1.0.1 2016-01-08 09:46:27 -08:00
Zach Lysobey 00c4df10c2 docs(changelog): fix typo
Closes #5176
2016-01-08 09:04:04 -08:00
Wesley Cho 162de3eaf2 chore(release): 1.0.0 2016-01-08 08:44:00 -08:00
Foxandxss ac32cbb4cf chore: update homepage footer
Closes #5176
2016-01-08 17:24:32 +01:00
Foxandxss b32003bb8c docs(buttons): add boolean badge 2016-01-08 17:00:43 +01:00
Foxandxss 859dccd711 docs(homepage): add extra note
Closes #5171
2016-01-08 16:56:10 +01:00
Foxandxss 1a3e2adf1a docs(typeahead): tune up
Closes #5170
2016-01-08 16:55:20 +01:00
Foxandxss b6031d6bf0 docs(timepicker): tune up
Closes #5166
2016-01-08 16:53:13 +01:00
Wesley Cho a9e476f0f7 feat: add npm support in main repository
- Add support for consuming the main repository via npm for releases

Closes #4739
Closes #5129
2016-01-08 06:42:44 -08:00
Wesley Cho e1e6e1bb62 fix(typeahead): use correct selector
- With the addition of the header, the selector to scroll the dropdown
  onto the correct element is incorrect - this fixes it to select all
list elements in the dropdown

Closes #5168
Fixes #5167
2016-01-07 17:21:55 -08:00
Daniel Gornstein 3e876b8fdd feat(typeahead): add event object to onSelect
- Add support for `$event` in expression with `onSelect`

Closes #5165
2016-01-07 17:19:39 -08:00
Foxandxss 3ef8992c54 docs(tabs): tune up
Closes #5163
2016-01-08 00:15:09 +01:00
Wesley Cho a5ca78ad2a feat(tooltip): change back to jqLite listeners
- Change event listeners to be handled by jqLite

Closes #4886
Closes #5157
2016-01-07 06:37:19 -08:00
Wesley Cho d320df88a3 chore(dateparser): fix docs 2016-01-06 19:57:57 -08:00
Wesley Cho f40066af9e revert(dateparser): change template literal to '
This reverts commit 9513f1007f.

Fixes #5091

BREAKING CHANGE: Reverts back to original template literal with `'` instead of `\''
2016-01-06 18:50:11 -08:00
Foxandxss e1723bf09d docs(datepicker): remove unneeded signs 2016-01-07 01:30:18 +01:00
Foxandxss 86ed171e37 docs(rating): tune up
Closes #5154
2016-01-07 00:43:39 +01:00
Foxandxss 4d37c9240b docs(progressbar): tune up
Closes #5148
2016-01-06 19:32:25 +01:00
Chenyu Zhang cab0945ac9 fix(typeahead): fix programmatic focus issue
- Fix issue where programmatic focus on typeahead input does not work

Closes #5150
Fixes #764
2016-01-06 06:36:14 -08:00
Foxandxss ff5e720690 docs(popover): tune up
Closes #5146
2016-01-05 13:54:44 +01:00
Foxandxss dbdffd4c4e docs(tooltip): fix typo 2016-01-04 20:29:47 +01:00
Foxandxss dc229ac01f docs(tooltip): there is no html unsafe version anymore 2016-01-04 20:21:24 +01:00
Foxandxss c357385207 docs(tooltip): tune up
Closes #5143
2016-01-04 14:11:39 +01:00
Foxandxss 6b5fcc385c docs(position): tune up
Closes #5138
2016-01-04 13:42:58 +01:00
Foxandxss b8ebad2dfa chore(grunt): fix typo on comment 2016-01-03 20:15:55 +01:00
William Di Luigi ed7e4600b0 revert(progressbar): remove min-width
- Remove min-width in template due to Bootstrap removing min-width

Closes #5141
2016-01-03 13:37:34 -05:00
Foxandxss 2ccaa1977f docs(pagination): update to latest version
Closes #5135
2015-12-31 10:45:04 +01:00
Foxandxss 1f3e55f6fc docs(pager): fix more typos 2015-12-30 14:24:43 +01:00
Foxandxss e98492baa2 docs(pager): fix more typos 2015-12-30 14:20:14 +01:00
Foxandxss db52961f5c docs(pager): remove unneeded characters 2015-12-30 14:14:35 +01:00
Chris Chua 72f13ef38b refactor(datepicker): optimize datepicker
- Add new class manipulation helper directive that uses 1 watcher as opposed to watchers for each element with ng-class
- Optimize disabled state
- Optimize class binding

Closes #2613
Closes #3451
Closes #3770
Closes #5065

BREAKING CHANGE: For those using custom templates, the changes result in necessary changes being made to the templates to match the new class changing syntax
2015-12-30 08:04:23 -05:00
Foxandxss f33ab7ceca docs(pager): update to latest
Closes #5133
2015-12-30 12:36:22 +01:00
Foxandxss 14037f1633 docs(dropdown): add badges
Closes #5132
2015-12-29 13:41:09 +01:00
Foxandxss ca580268eb docs(dropdown): reword extra settings 2015-12-28 19:14:12 +01:00
Foxandxss 7a8cf0e458 docs(button): reword the extra settings 2015-12-27 18:08:19 +01:00
Foxandxss 36c687a32f docs(accordion): add config as a badge
Closes #5125
2015-12-26 15:26:32 +01:00
Foxandxss fccc9691f9 docs: add explanation for the C badge
Closes #5120
2015-12-26 15:25:39 +01:00
Foxandxss 8b68fe052d docs(datepicker): docs tune up
Closes #5119
2015-12-26 15:24:05 +01:00
Foxandxss 1273156097 chore(karma): install fixed version
Closes #5126
2015-12-26 15:21:47 +01:00
Foxandxss 33b7a3760f docs(collapse): tune up docs
Closes #5110
2015-12-22 10:52:57 -05:00
Foxandxss 2cc6cbaa0d docs(carousel): tune docs
Closes #5105
2015-12-21 09:11:58 -05:00
Foxandxss 74b213ef60 docs(alert): tune up docs
Closes #5103
2015-12-20 21:20:06 -05:00
Foxandxss 277ffa998c docs(buttons): update button docs
Closes #5102
2015-12-20 00:08:05 -05:00
Foxandxss 5805b51f4d docs(accordion): add extra badges
Closes #5099
2015-12-18 22:55:16 -05:00
Foxandxss 4dba58ddbe docs: add badge explanations
Closes #5100
2015-12-18 22:54:52 -05:00
Jeffrey Hamans a5c2a5b061 fix(modal): add focus check for IE
- Check if element has focus method due to IE issues

Closes #5097
Fixes #5096
2015-12-18 13:57:02 -05:00
Wesley Cho 3b7f78a93d test(datepicker): optimize performance
- Optimize performance of tests by compiling datepicker once max per test

Closes #5094
2015-12-18 08:46:24 -05:00
Wesley Cho 1524080078 fix(datepicker): correctly set minMode/maxMode
- Correctly set `minMode` and `maxMode` for the datepicker popup

Closes #5093
Fixes #5090
2015-12-18 08:45:00 -05:00
Foxandxss 3845980bda docs(accordion): order the different settings
Closes #5098
2015-12-18 13:08:22 +01:00
Wesley Cho 6fa4cc5a4a chore: add updated compiler for Travis 2015-12-16 11:10:48 -05:00
Dave Anderson 09098f891f feat(datepicker): add timezone support
- Add timezone support with ngModelOptions

Closes #5062
2015-12-16 10:12:32 -05:00
Wesley Cho 9019298cc3 fix(datepicker): active date should be model if present
- When ng-model value is initially present, it should set the active date to be the model date as per documentation

Closes #5082
Fixes #5081
2015-12-16 09:40:37 -05:00
Wesley Cho 2635f0d65b feat(modal): add pluggable resolve support
- Adds support for pluggable resolvers, namely for supporting UI Router's resolve handling

Closes #3405
Closes #5078
2015-12-15 19:22:08 -05:00
Foxandxss fd5991311a docs(modal): update to latest version
Closes #5079
2015-12-15 18:41:48 -05:00
Wesley Cho 00a7cc393a chore: leverage es6 in gruntfile
- Add some ES6 usage in gruntfile

Closes #5076
2015-12-15 09:24:21 -05:00
Wesley Cho 5ad08fff46 fix(collapse): set initial state to avoid animation
- Ensure animation does not occur when first loaded

Closes #5075
Fixes #4848
Fixes #4885
2015-12-15 09:23:01 -05:00
Wesley Cho 000d6c309e fix(datepicker): stop propagation of esc in popup
- Stop propagation of esc key in datepicker popup, which can propagate to undesirable elements/handlers such as the modal

Closes #5074
Fixes #5013
2015-12-15 09:22:04 -05:00
Wesley Cho ccf161afba chore: bump node version 2015-12-15 01:54:27 -05:00
Wesley Cho bf1768e752 fix(dropdown): do not close on right click
- Do not close the dropdown on right click when open due to Firefox's
  behavior

Closes #5052
Fixes #5051
2015-12-14 17:10:20 -05:00
Wesley Cho 2a1aaf2d85 feat(tooltip): add appendToBody only attribute support
- Add support for using only `tooltip-append-to-body` without any attribute value to enable appending tooltip to body

Closes #4945
Closes #5071
2015-12-14 17:08:04 -05:00
Bryan Grohman a49ce8e50a test(datepicker): test that changing time updates model
- Add unit test for changing the time and verifying that the model updates

Closes #5073
2015-12-14 16:20:50 -05:00
Connor Hindley e6474f0597 docs(tooltip): fix incorrect attribute mentioned
Closes #5072
2015-12-14 15:33:25 -05:00
Dave Anderson e7f709f0a7 fix(datepicker): fix minDate/maxDate with literals
- Fixes use of min-date and max-date with literal strings

Closes #4841
Fixes #3437
2015-12-14 14:47:11 -05:00
Wesley Cho 812d47e817 chore: fix recursion error
- This fixes an error in Firefox for Linux where too much recursion happens

Closes #5061
Fixes #4977
2015-12-14 13:18:58 -05:00
Wesley Cho 6dbd3f8f06 chore: change node-markdown for marked
Closes #5066
Closes #5067
2015-12-14 10:28:09 -05:00
Dave Anderson b784422ee3 feat(datepicker): yearRange -> yearRows and yearColumns
BREAKING CHANGE: 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

Closes #3348
Closes #4970
2015-12-14 07:40:24 -05:00
Wesley Cho d84cb6536a chore(datepicker): fix formatting 2015-12-14 00:33:48 -05:00
Wesley Cho e18bdd557c chore(datepicker): fix formatting 2015-12-14 00:33:36 -05:00
Wesley Cho 8b721f425b chore(datepicker): fix formatting 2015-12-14 00:33:22 -05:00
Wesley Cho 9a32cda11c chore(datepicker): change to new format 2015-12-14 00:32:40 -05:00
Wesley Cho 174c3bda20 chore(datepicker): change to new format 2015-12-14 00:31:57 -05:00
Wesley Cho 406528eee2 chore(datepicker): change to new format 2015-12-14 00:31:07 -05:00
Foxandxss c4a3ad41ad refactor(carousel): reorganize methods
Closes #5063
2015-12-13 21:44:49 -05:00
Foxandxss be772fa5ae refactor(carousel): remove unneeded describe
Closes #5064
2015-12-13 13:44:16 -06:00
Wesley Cho 46882525f4 chore(dropdown): remove class usage 2015-12-12 23:41:06 -08:00
Foxandxss 1e24ff7bc1 chore(modal): remove empty line 2015-12-12 00:02:48 +01:00
Foxandxss 7be21c4983 test(modal): test dismissAll
Closes #5056
2015-12-11 08:21:18 -08:00
Foxandxss b31f87cef6 chore(modal): fix typo on test 2015-12-11 15:34:44 +01:00
Wesley Cho fe68977033 chore(modal): clean up code style 2015-12-10 22:40:39 -08:00
Wesley Cho b8969d1937 fix(modal): fix bindToController
- Fixes issue where `$scope` provided does not have properties present
  on controller instance due to $new resulting in the property on the
prototype of the $scope copied from, which causes it to not be
enumerable

Closes #5048
Fixes #5039
2015-12-10 09:46:31 -08:00
Jeffrey Barrus 2460e42322 feat(datepicker): add allowInvalid support
- Adds support for invalid view values via `ngModelOptions`
  allowInvalid` setting

Closes #4694
Closes #4837
2015-12-10 07:26:11 -08:00
Foxandxss 3658502c74 chore: add migration guide link to homepage
Closes #5037
2015-12-09 10:37:21 +01:00
Sergii Stotskyi a5cac90ad0 feat(tabs): add controllerAs support
Closes #5019
Closes #5020
2015-12-06 18:44:52 -08:00
Dave Anderson fd88dcb274 fix(datepicker): update with alternative format
Closes #5014
2015-12-05 12:34:21 -08:00
Foxandxss 62e0761351 chore: bump minimum angular version in homepage
Closes #5018
2015-12-05 12:32:03 -08:00
Wesley Cho 8930a7f373 chore: ensure tests are gc'd
- Ensure event listeners globally on service instantiation are garbage
  collected properly

Closes #5017
Fixes #4996
2015-12-05 12:31:12 -08:00
Wesley Cho 8a7ebbf94d chore(typeahead): change to on/off
Closes #5016
2015-12-05 12:30:07 -08:00
Foxandxss 75b8e5aa0e refactor(modal): mix both modal spec files
Closes #5011
2015-12-05 09:22:36 -08:00
Foxandxss 5e5c8b4af2 refactor(modal): migrate more animations to animateCss
Closes #5008
2015-12-05 09:22:02 -08:00
wawyed c0f10276af fix(modal): trap tabbing regardless of config
- Ensure tabbing is trapped regardless of whether `keyboard` is `false`

Closes #5010
Fixes #4990
2015-12-04 06:26:36 -08:00
Wesley Cho 384fdfc83d chore: update package.json
- Update package.json with more information
- Improve .npmignore slightly

Closes #4993
2015-12-03 18:08:07 -08:00
Foxandxss 66d290225a refactor(modal): simplify backdrop creation
Closes #5002
2015-12-03 22:39:58 +01:00
Foxandxss f125cdb6ae chore(modal): change link parameters
Closes #5002
2015-12-03 22:37:59 +01:00
Foxandxss 8c4d248afa chore(modal): remove prefix leftover
Closes #5001
2015-12-03 22:36:57 +01:00
Wesley Cho 763cfd921e fix(carousel): resolve rendering issues
- Defer selection of active slide until after transition has been reset
  to avoid selection occuring before the transition finishes, preventing
a new slide from being chosen
- Buffer slides if transition is currently going on to navigate to last
  slide selected after

Closes #4984
Fixes #4361
Fixes #4823
Fixes #4969
2015-12-01 06:46:20 -08:00
Wesley Cho a8b0d454f9 chore(carousel): clean up code style 2015-11-30 21:43:39 -08:00
Wesley Cho bd47f6c4ff feat(typeahead): add ng-model-options debounce support
- Adds support for ng-model-options `debounce` option

Closes #4982
2015-11-30 15:34:05 -08:00
Wesley Cho 6094e0725e chore(carousel): remove dead code
- Remove unnecessary $animate.enabled check

Closes #4983
2015-11-30 15:08:35 -08:00
Foxandxss c488d824bb chore(pager): fix demo
Closes #4980
2015-11-30 06:49:08 -08:00
Wesley Cho e9c4977dc4 feat(modal): add closed promise
- Add `closed` promise for when the modal animation completes on removal

Closes #4979
2015-11-30 10:06:35 +01:00
Wesley Cho 9d139a5975 refactor(typeahead): change to switch 2015-11-29 23:26:07 -08:00
Wesley Cho d9e3dd5c44 chore(carousel): combine animation check
- Combine animation check since $animate.enabled value is set in the
  $watcher

Closes #4976
2015-11-29 07:42:47 -08:00
Wesley Cho 19b7e3e699 chore(dropdown): remove class support
BREAKING CHANGE: Class support for consuming the directive has been
removed. Please use an attribute instead

Closes #4975
Resolves #4753
2015-11-28 07:17:18 -08:00
Wesley Cho 12a37e0f02 fix(carousel): fix conditions for animation
- Fix incorrect animation conditions

Closes #4974
Fixes #4972
2015-11-28 06:35:50 -08:00
Wesley Cho d8c8767c3d chore(carousel): clean up code style 2015-11-27 21:05:00 -08:00
Wesley Cho 1a822a1170 feat(timepicker): add semantic classes
- Adds semantic classes to assist with styling

Closes #4764
Closes #4971
2015-11-27 13:55:37 -08:00
Wesley Cho 1d49f054c0 chore: bump up uglify version 2015-11-27 11:35:08 -08:00
Wesley Cho f3f5430b1c chore: bump up node for travis 2015-11-27 11:34:26 -08:00
Wesley Cho f2f8c4e8d3 feat(paging): factor out common controller code
- Create paging factory for creating common controller for the
  pagination and pager components

Closes #4803
Closes #4968
2015-11-27 11:31:16 -08:00
Dave Anderson 8bfeda00d4 feat(datepicker): implements alternative format support
- Adds support for multiple input formats

Closes #4951
Closes #4952
2015-11-26 11:21:32 -08:00
Foxandxss f3d4dc2cf9 docs(datepicker): fix a few typos 2015-11-26 15:19:03 +01:00
Wesley Cho 58902485ef feat(pager): change controllerAs to pager
BREAKING CHANGE: As part of the split of the pager component from the
pagination component, this changes the controllerAs use to `pager` from
`pagination`

Closes #4961
2015-11-26 06:13:45 -08:00
Wesley Cho 891c449ad4 chore(pager): fix indentation 2015-11-26 06:05:51 -08:00
Wesley Cho 80e927e735 chore(pager): remove unnecessary code 2015-11-26 06:05:32 -08:00
Adam Gordon 9f0dba173f docs: fix append-to-body attribute
* fix `tooltip-append-to-body` doc
* fix `popover-append-to-body` doc

Closes #4948
Fixes #4945
2015-11-24 21:45:48 -08:00
Wesley Cho 9513f1007f feat(dateparser): change template literal from ' to `
- Changes from ' to ` for template literals
- Adds documentation about template literals

BREAKING CHANGE: This changes template literals from the single quote
`'` to the backtick character `` ` `` for more natural usage with certain
strings such as `o'clock`.

Closes #4880
Closes #4936
Closes #4938
2015-11-24 12:38:14 -08:00
Rob Jacobs d265113984 feat(position): implement auto positioning
Implementing the ability to auto position elements
in the position service - positionElements function.

Closes 4899
2015-11-23 13:24:36 -05:00
Wesley Cho 526e6de82a chore(pagination): clean up code style 2015-11-22 23:23:40 -08:00
Wesley Cho 2a3314df70 feat(pager): move to separate component
- Separate pager into its own component

Closes #4935
2015-11-22 12:57:48 -08:00
Chenyu Zhang 2cd7f4fe6d docs(tabs): add disabled style
Closes #4916
2015-11-22 12:55:14 -08:00
Wesley Cho 48505a3045 chore(tooltip): remove deprecated feature from docs 2015-11-22 00:12:46 -08:00
Wesley Cho dd6ddc8039 Revert "Revert "fix(debounce): fix argument slicing""
This reverts commit 1e19292b6b.
2015-11-21 14:37:36 -08:00
Brian Genisio 56f9a207de refactor: remove dot usage of reserved words
- Remove usage of `.finally` for IE9 compatibility

Closes #4913
2015-11-17 11:43:27 -08:00
Foxandxss 423ba10875 docs(dropdown): update docs
Closes #4910
2015-11-16 08:11:44 -08:00
Foxandxss 77a5158c2b chore(eslint): add semicolons rule
Closes #4909
2015-11-16 07:43:47 -08:00
Wesley Cho e209db392e chore(timepicker): clean up code style 2015-11-15 14:27:00 -08:00
Alex Knowles 726ccc367d fix(modal): retain focus if child has focus
- If a child element in the modal has focus before animation completes, do not refocus

Closes #4904
Fixes #4903
2015-11-15 13:16:05 -08:00
Foxandxss 6d5b1d9038 test(dropdown): use existing matchers
Closes #4898
2015-11-13 10:51:05 -08:00
Foxandxss 31af431d5a test(dropdown): reorganize and refactor tests
Closes #4896
2015-11-13 10:27:05 -08:00
Foxandxss 57f72b219e fix(dropdown): remove extra uib-keyboard-nav
Closes #4891

BREAKING CHANGE: `keyboard-nav` for the dropdown is not longer a directive and to use it you have to use `keyboard-nav` instead of `uib-keyboard-nav`.
2015-11-13 18:04:01 +01:00
Foxandxss 4dab96e28c refactor(dropdown): remove regex to not match 138 and 140
Closes #4892
2015-11-13 08:32:44 -08:00
Foxandxss 58205a82bb refactor(dropdown): remove unneeded
Closes #4893
2015-11-13 08:31:31 -08:00
Foxandxss 4de49f4f58 refactor(dropdown): change bind/unbind to on/off
Closes #4895
2015-11-13 08:29:51 -08:00
Foxandxss 85fdfc2024 chore(readme): fix typo 2015-11-13 00:35:22 +01:00
Wesley Cho b1c05f40cc chore(carousel): remove unnecessary tests 2015-11-11 11:58:11 -08:00
Adam Gordon 53806c2779 chore(tabs): add nested forms example
Closes #4866
2015-11-11 11:57:46 -08:00
Foxandxss c34317d13d docs(datepicker): revamp documentation
Closes #4881
2015-11-11 19:06:38 +01:00
Foxandxss 4199237da0 refactor(datepicker): simplify miscellaneous stuff
Closes #4876
2015-11-11 09:52:51 -08:00
Foxandxss c9363809d8 test(datepicker): add a few tests
Closes #4874
2015-11-11 09:33:18 -08:00
Foxandxss a255d99b0b chore(datepicker): open one popup at once in the demo
Closes #3432
Closes #4879
2015-11-11 09:32:27 -08:00
Foxandxss c61257143f chore(datepicker): fix customClass demo
Closes #4877
2015-11-11 09:30:19 -08:00
Foxandxss 9131907bb4 chore(datepicker): remove stale deprecation stuff
Closes #4875
2015-11-11 09:28:39 -08:00
jsdevel 9b80ee1b2f feat(carousel): expose next and prev on controller
- Expose `prev` and `next` functions on the carousel controller

Closes #4851
Closes #4853
2015-11-10 15:01:55 -08:00
Dave Anderson 26d31037ce feat(datepicker): pass through attrs in popup
- Passes through all datepicker config attributes from the popup to the datepicker

Closes #4863
Fixes #3338
2015-11-10 14:48:38 -08:00
Chenyu Zhang 0917623b18 fix(accordion): ensure panelOpen class is present
- Ensure panelOpen class is present on initialization of panel

Closes #4849
Closes #4870
2015-11-10 14:40:27 -08:00
Adam Gordon 44820a01b3 chore(build): update Bootstrap dependency
* Update the Bootstrap version used by the Plunker demos.

Closes #4865
2015-11-10 14:34:42 -08:00
Timothy Zorn 873730360c feat(tooltip): add outsideClick trigger
- Add `outsideClick` trigger support, which allows dismissal of the tooltip/popover on click of any element outside of the tooltip/popover

Closes #4419
Closes #4871
2015-11-10 14:32:02 -08:00
Adam Gordon 3ca8b88044 docs(tooltip): fix directive name
Closes #4864
2015-11-10 12:04:39 -07:00
Adam Gordon 1e19292b6b Revert "fix(debounce): fix argument slicing"
This reverts commit e196be855e.
2015-11-10 12:02:43 -07:00
Astashenkau e196be855e fix(debounce): fix argument slicing
Closes #4859
Closes #4860
2015-11-10 07:43:33 -08:00
damon.friendship a5bafe6439 feat(typeahead): add dynamic toggling of Editable
- Allow user to toggle value of `typeaheadEditable` dynamically

Closes #2638
Closes #4820
2015-11-10 00:07:03 -08:00
Dave Anderson 1f43cdf3da chore(build): properly prefix module dependencies
- Fixes module dependencies for `ui.bootstrap.tpls`

Closes #4842
2015-11-08 18:30:32 -08:00
Wesley Cho f68a7e0c27 chore(modal): clean up code style 2015-11-08 16:10:55 -08:00
Wesley Cho ca02088666 chore(modal): remove old comment 2015-11-08 16:10:38 -08:00
Wesley Cho e48342a3f8 chore(modal): clean up code style 2015-11-08 16:07:45 -08:00
Wesley Cho e28ccedb6c feat(modal): support requiring from parent directive
- Add support for requiring from parent directive of element being
  appended to

Closes #3765
Closes #4844
2015-11-08 16:02:46 -08:00
Wesley Cho ee7ab9f36a chore(tooltip): remove old comment 2015-11-07 14:44:19 -08:00
Wesley Cho 07c31d0731 chore: add eslint
- This adds eslint and integrates it to the build chain
- Removes jshint

Closes #4758
Closes #4840
2015-11-07 14:42:44 -08:00
Wesley Cho 742132a2c8 feat(modal): change to use $animate
- Change to use $animate and $animateCss

Closes #3418
Closes #4834
2015-11-07 12:51:17 -08:00
Wesley Cho 342c576ea4 feat: prefix virtual templates with uib/
- Change all virtual paths with built in templates to be prefixed by `uib/`

BREAKING CHANGE: 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

Closes #1205
Closes #4839
2015-11-07 12:49:59 -08:00
Wesley Cho fe6938675e feat(timepicker): add model state support
- Adds support for the timepicker model $touched and $dirty states

Closes #3527
Closes #4835
2015-11-07 12:48:53 -08:00
Wesley Cho 703432b259 chore(tabs): clean up unnecessary code 2015-11-07 10:12:00 -08:00
Wesley Cho ea388b34d0 feat(dateparser): add new format support
- Adds `ww` support
- Adds `w` support
- Adds `G`, `GG`, `GGG` support
- Adds `GGGG` support

Closes #3418
Closes #4833
2015-11-07 08:02:16 -08:00
Wesley Cho 8c3c38ded7 chore(dateparser): fix incorrect character 2015-11-07 06:46:41 -08:00
Wesley Cho 2fb812be13 feat(dateparser): add Z support
- Add support for the `Z` format, as referred to in the Angular
  documentation [here](https://docs.angularjs.org/api/ng/filter/date)

Closes #4831
2015-11-06 12:05:03 -08:00
Incell 628039bb16 chore(tooltip): fix matcher condition
Closes #4821
2015-11-05 09:03:37 -08:00
Robbert Merlier 80df0152b3 feat(modal): allow appending outside iframe
- Loosen to accept jqLite element straight up

Closes #4818
2015-11-04 07:17:25 -08:00
Foxandxss 5bf4052d69 chore(CONTRIBUTING): remove prefix note 2015-11-03 19:53:39 +01:00
Wesley Cho 434c6026a5 feat(datepicker): add disabled and ngDisabled support
- Adds support for `disabled` attribute
- Adds support for `ng-disabled`

Closes #4059
Closes #4814
2015-11-03 08:45:25 -08:00
Wesley Cho 73efc782e9 chore(debounce): create debounce helper
- Create internal debounce helper
- Move debounce logic from typeahead to use helper

Closes #3966
Closes #4813
2015-11-03 07:22:42 -08:00
Wesley Cho aff9010250 chore(datepicker): clean up code style 2015-11-03 06:23:50 -08:00
Wesley Cho 1c30baa335 chore(modal): clean up code style 2015-11-03 05:45:47 -08:00
Wesley Cho 465119141a feat(timepicker): add ngDisabled support
- Adds support for `ng-disabled` on timepicker element for disabling all controls programmatically

Closes #2219
Closes #4811
2015-11-03 05:38:31 -08:00
Wesley Cho beabb4a04d fix(datepicker): correctly display pre-100 years
- Fix display of dates in datepicker for years less than 100

Closes #4812
Fixes #4032
2015-11-03 05:37:50 -08:00
Wesley Cho fc61e178b6 chore(timepicker): clean up code style 2015-11-02 20:42:18 -08:00
Wesley Cho bd8acac329 chore(timepicker): clean up code style 2015-11-02 20:31:58 -08:00
Wesley Cho 83d1435444 fix(dateparser): enforce order of regex construction
- Change `formatCodeToRegex` into an array to avoid potential iteration bug where the order the keys are listed in the object matters in the iteration order

Closes #4810
Fixes #4808
2015-11-02 15:47:22 -08:00
Scotty Waggoner 56642ea396 feat(pagination): add force-ellipses option and boundaryLinkNumbers
- Adds force-ellipsis option for adding ellipses to pagination
- Add boundary-link-numbers option for allowance of the first and last page numbers to always be shown

Closes #2924
Closes #3064
Closes #3565
2015-11-02 15:27:19 -08:00
dstone 3f307e4c4b feat(pagination): Show ellipsis when rotating 2015-11-02 15:18:47 -08:00
Wesley Cho b1cfc5762d feat(dateparser): add M! and d! support
- Add M! and d! for optional support of leading zeroes in date string format

Closes #4805
Closes #4809
2015-11-02 15:01:35 -08:00
Wesley Cho 3f5b420a8c chore(demo): fix demo with tab change
- Fix appearance of tabs with breaking change in demo

Closes #4807
2015-11-02 13:58:07 -08:00
Foxandxss d732929d7e docs(dateparser): add demo with docs
Closes #4806
2015-11-02 11:49:59 -08:00
Yakira C. Bristol 02d2ef3c63 docs(datepicker): adds notes about validation
- Adds a note about the `dateDisabled` validation error

Closes #3440
Closes #4770
2015-11-02 06:23:55 -08:00
Wesley Cho 3aa41f053f fix(typeahead): allow parent to be required
- Change to insert content to DOM before compiling to preserve requiring parent controllers

Closes #4800
Fixes #2679
2015-11-02 06:05:49 -08:00
Wesley Cho 8637afcbac feat(typeahead): change to appendTo
- Change signature to `appendTo`, which takes a value that evaluates to a DOM node for API consistency

BREAKING CHANGE: Usage before
```html
<div id="typeahead-container"></div>
<input typeahead="state for state in states | filter: $viewValue | limitTo: 8" typeahead-append-to-element-id="typeahead-container">
```
After
```html
<div id="typeahead-container"></div>
<input typeahead="state for state in states | filter: $viewValue | limitTo: 8" typeahead-append-to="typeaheadContainer">
```
```js
$scope.typeaheadContainer = angular.element(document.querySelector('#typeaheadContainer'));
```

Closes #4797
2015-11-01 18:32:34 -08:00
Wesley Cho 08ad07701e chore(typeahead): clean up code style 2015-11-01 17:56:34 -08:00
Wesley Cho 01c2d9a5c0 chore(typeahead): clean up code style 2015-11-01 17:43:20 -08:00
Wesley Cho 8b75bc4f5f chore(typeahead): clean up code style 2015-11-01 17:43:04 -08:00
Wesley Cho d59083b65e fix(tab): fix unexpected routing
- Change anchor tag to `div` to prevent unexpected routing being triggered by the browser on generation of anchor tags with nested clickable controls

BREAKING CHANGE: This causes the cursor style to be removed from the tab - implement CSS on the `.uib-tab > div` selector, or similar, accordingly

Closes #4793
Fixes #3266
2015-10-31 11:36:12 -07:00
Wesley Cho df211bd625 fix(accordion): fix unexpected routing
- Change anchor tag to `div` to prevent anchor tag from triggering route change

BREAKING CHANGE: This causes the cursor style to be removed from the heading - implement CSS on the `accordion-toggle` class accordingly

Closes #4792
2015-10-31 11:34:46 -07:00
Wesley Cho 0495ff0917 feat(dropdown): add open class support
- Adds support for the `uib-dropdown-open` class to be toggled on the container element of a dropdown menu on dropdown toggle

Closes #4466
Closes #4794
2015-10-31 11:18:02 -07:00
Wesley Cho b77618e06f feat(buttons): add uib-uncheckable support
- Add support for `uib-uncheckable` with uib-btn-radio

Closes #3604
Closes #4791
2015-10-31 11:16:27 -07:00
Foxandxss 739b667cc5 chore(carousel): fix demo
Closes #4796
2015-10-31 15:36:41 +01:00
Tobias Gunkel 1c79888ca6 feat(dateparser): add support for literals
- Add support for string literals via single quotes

Closes #3914
Closes #4426
2015-10-30 21:58:39 -07:00
Jay Klehr 809ecdb476 feat(dropdown): add append-to support
- Adds support for appending dropdown to specified DOM node

Closes #4467
Closes #4488
2015-10-30 21:21:44 -07:00
Wesley Cho da455f6dd0 chore(buttons): clean up code style 2015-10-30 19:08:41 -07:00
Chenyu Zhang d859f42cc0 feat(typeahead): add min-length === 0 support
- Adds support for `typeahead-min-length` being equal to `0`

Closes #764
Closes #2324
Closes #4789
2015-10-30 10:58:21 -07:00
Wesley Cho 20a8701c34 chore: update devDependencies 2015-10-30 06:54:22 -07:00
Foxandxss f6f6db1681 chore(karma): add coverage
Closes #4785
2015-10-30 06:45:01 -07:00
Wesley Cho 65b47a2e0e chore(typeahead): fix mistakenly resolved template usage 2015-10-30 06:34:47 -07:00
Wesley Cho 3f6d388925 chore(typeahead): fix mistaken removal of prefix 2015-10-30 06:19:49 -07:00
dsisejkovic a1355e7687 feat(typeahead): add ability to scroll with matches
- This adds scrolling capability with matches when using keyboard
  navigation

Closes #4463
2015-10-30 06:18:57 -07:00
Chenyu Zhang ef82ad1f29 feat(typeahead): add show-hint option
- Add support for hinting on the first match in the matches list

Closes #2570
Closes #4784
2015-10-29 23:11:00 -07:00
Wesley Cho 9d93af1c81 fix(carousel): remove version checks
- Make use of `$animateCss` directly since a shell service was introduced in Angular proper

Closes #4122
Closes #4774
2015-10-29 22:50:45 -07:00
Wesley Cho 30099a0cd0 fix(pagination): retain model on initialization
- When `total-items` initializes as undefined, ignore value and do not update page information
- Remove extra watcher and call action manually

Closes #3786
Closes #4783
Fixes #2956
2015-10-29 15:59:39 -07:00
Chenyu Zhang 167cfad72a feat(typeahead): add 'is-open' support
- Adds support for checking the toggled state of the dropdown

Closes #4760
Closes #4779
2015-10-29 15:31:38 -07:00
Wesley Cho a8624e0cff chore(pagination): clean up code style 2015-10-29 13:38:25 -07:00
Wesley Cho c8df6f2700 chore(pagination): clean up code style 2015-10-29 13:25:36 -07:00
Foxandxss d60f2dfa09 test(position): add more tests
Closes #4780
2015-10-29 13:10:22 -07:00
Wesley Cho a8516369f4 fix: allow library to be loaded async
- Fixed execution of style tag addition to inside module.run

Closes #4775
Fixes #3665
2015-10-29 13:09:22 -07:00
Foxandxss 8c0b3f592f chore(position): remove unneeded break
Closes #4781
2015-10-29 12:46:46 -07:00
Kevin McCaw 09ad740434 fix(timepicker): correct meridian toggle condition
- Fix check to be against hours being checked against the maximum for hours less than 12 (for time before noon)

Closes #4435
2015-10-28 22:40:33 -07:00
Wesley Cho 468d68ac6b chore(typeahead): fix reference to non-prefixed attribute 2015-10-28 22:27:12 -07:00
Ajay kumar Guthikonda 16d854ca4c feat(modal): add appendTo support
- Add support for appending to specific element through `appendTo` option

Closes #4599
2015-10-28 14:13:56 -07:00
Franz Torghele 8ffdaeb099 feat(timepicker): added ability to handle empty model
Closes #1114
Closes #4203
Closes #4617
2015-10-28 13:25:43 -07:00
Chris Gat c7fa84529c feat(timepicker): add support for seconds
- Adds support for seconds option

Closes #4768
2015-10-28 13:15:00 -07:00
Foxandxss 21b2297aec fix(dateparser): baseDate only care about dates
Closes #4767
2015-10-28 13:12:52 -07:00
Rob Jacobs 429ddc12b6 fix(tooltip): race condition when setting position
A race condition could occur when there is an open delay that
doesn't get cancelled after the transition delay resulting in
the position logic getting called.  This will then try to set
the css of the tooltip after is has been destroyed in the
removeTooltip function.

Closes #4765
Fixes #4757
2015-10-28 12:35:02 -07:00
Foxandxss 1cfaf64418 test(dateParser): missing tests, refactorized tests
Closes #4766
2015-10-28 12:33:35 -07:00
Wesley Cho 97c4333495 feat(datepicker): add semantic classes
- Add semantic classes to template to assist in styling

Closes #4761
2015-10-28 11:06:40 -07:00
Chenyu Zhang 1d9294c8e6 fix(typeahead): clear typeahead input when editable is false
Closes #1620
Closes #4265
Closes #4752
2015-10-28 08:21:16 -07:00
Foxandxss 623e564f07 chore: add the current version of the docs
Closes #4759
2015-10-28 08:19:55 -07:00
Foxandxss a1e0686162 chore(carousel): add more options to the demo
Closes #4749
2015-10-27 19:29:09 +01:00
Wesley Cho acb54991bb chore(accordion): clean up code style 2015-10-27 07:19:58 -07:00
Wesley Cho bb7b9e3f5a chore(accordion): clean up code style 2015-10-27 07:17:40 -07:00
Wesley Cho 9e6bf021da chore(accordion): clean up code style 2015-10-27 07:10:37 -07:00
Wesley Cho dbc9cb7a77 chore(accordion): clean up code style 2015-10-27 06:57:39 -07:00
Foxandxss 38bb19a275 chore(carousel): put documentation up to date
Closes #4747
2015-10-27 06:47:39 -07:00
Foxandxss 286860a1b7 refactor(carousel): simplify one test
Closes #4745
2015-10-27 06:47:16 -07:00
Foxandxss 738b6addf0 refactor(carousel): combine destroy events
Closes #4744
2015-10-27 06:46:42 -07:00
Foxandxss d2097c1dd7 refactor(carousel): remove stale code
Closes #4743
2015-10-27 06:46:18 -07:00
Foxandxss 4eaa82f978 refactor(carousel): a bit faster for
Closes #4742
2015-10-27 06:45:52 -07:00
Foxandxss 9d886da6f9 refactor(carousel): modify slide tests a bit
Closes #4748
2015-10-27 06:45:27 -07:00
Wesley Cho e1222fbfaa chore(carousel): delete unnecessary check 2015-10-26 17:05:28 -07:00
Wesley Cho 972dee623b fix(modal): clean up animation when disabled
- When the animation is set to false, do not remove the `in` class to prevent black opaque background from showing

Closes #4740
Fixes #4672
2015-10-26 15:30:24 -07:00
Wesley Cho 38c1b14684 fix(carousel): decouple animation information from DOM
- Change to use `$animate.enabled` to determine animation state

Closes #4737
Fixes #4516
2015-10-26 13:41:40 -07:00
Foxandxss 8899fc8e85 chore(carousel): remove stale ngdocs
Closes #4736
2015-10-26 12:54:08 -07:00
Rob Jacobs 79367b82de chore(docs): downloads - promote npm
In the download modal on the demo page, changed Bower info
to suggest using npm instead.

Closes #4734
2015-10-26 10:46:25 -04:00
Foxandxss 0669b06650 feat(progressbar): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4722
2015-10-23 15:52:05 -07:00
Foxandxss 42fa28f850 feat(position): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed service

Closes #4721
2015-10-23 15:50:59 -07:00
Foxandxss 75e493a940 feat(pagination): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4720
2015-10-23 15:50:11 -07:00
Wesley Cho feb2b736d3 feat(timepicker): remove deprecated code
BREAKING CHANGE: Remove deprecated directive

Closes #4712
2015-10-23 15:49:19 -07:00
Wesley Cho 606d419e92 feat(typeahead): remove deprecated code
BREAKING CHANGE: Remove deprecated services/directives

Closes #4711
2015-10-23 15:48:50 -07:00
Foxandxss d844623a1e feat(rating): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4723
2015-10-23 15:48:16 -07:00
Wesley Cho 1b75164c4f feat(tabs): remove deprecated code
BREAKING CHANGE: Remove deprecated directives

Closes #4710
2015-10-23 15:47:20 -07:00
Wesley Cho a85d4996c2 feat(modal): remove deprecated code
BREAKING CHANGE: Remove deprecated services/directives

Closes #4709
2015-10-23 15:46:29 -07:00
Wesley Cho 2fc3f2147b feat(datepicker): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4708
2015-10-23 15:45:24 -07:00
Wesley Cho 0010aff05d feat(accordion): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4706
2015-10-23 15:44:51 -07:00
Foxandxss ca3a343e2e feat(dropdown): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives/services

Closes #4719
2015-10-23 15:44:07 -07:00
Foxandxss 2d68f4131c feat(dateparser): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed service

Closes #4718
2015-10-23 15:43:27 -07:00
Foxandxss b159b21c85 feat(carousel): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4717
2015-10-23 15:42:50 -07:00
Foxandxss b5492632a8 feat(buttons): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4716
2015-10-23 15:41:39 -07:00
Foxandxss bc004dfa3a feat(collapse): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4715
2015-10-23 15:40:56 -07:00
Foxandxss 21e852b8ec feat(alert): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Closes #4714
2015-10-23 15:40:16 -07:00
Foxandxss 187f64c006 feat(tooltip): remove deprecated code
BREAKING CHANGE: Remove deprecated non-prefixed directives

Close #4713
2015-10-23 15:38:20 -07:00
Foxandxss 80ede3797f chore(docs): fix versions-mapping url 2015-10-23 23:04:18 +02:00
Wesley Cho 0b04eefd12 chore(release): Starting v1.0.0-SNAPSHOT 2015-10-23 13:47:45 -07:00
Wesley Cho e9d6ec2a29 chore(release): v0.14.3 2015-10-23 13:47:26 -07:00
Rob Jacobs 1f94104b69 fix(tooltip): null scope check in isOpen watch
The watch for the isOpen property from the model was not
checking to see if the internal tooltip scope was still
valid (null or undefined) before comparing the value to
the tooltip scope isOpen property.

Closes #4697
Fixes #4683
2015-10-23 15:59:05 -04:00
Foxandxss 1599cfff9b chore(accordion): update docs
Closes #4700
2015-10-23 21:46:07 +02:00
Foxandxss ac62276943 chore(buttons): update docs
Fixes #3562
Closes #4701
2015-10-23 21:44:42 +02:00
Rob Jacobs 8417b2d525 chore(docs): popover close delay
The attribute for the close delay on the popover was incorrectly
documented as 'popover-close-popup-delay' and should be
'popover-popup-close-delay.

Closes #4698
2015-10-23 11:03:43 -07:00
Wesley Cho 0d64aad4dd feat(datepicker): preserve timezone with model
- Default to using the date instance for any date manipulation, allowing
  for the timezone to automatically be preserved

Closes #4676
2015-10-23 11:01:42 -07:00
Foxandxss d3056c7605 chore: add CODE_OF_CONDUCT
Closes #4653
Closes #4652
2015-10-23 12:47:50 +02:00
Patrick Sullivan 134086a6b0 fix(datepicker): datepicker-popup nest in dropdown
* Extend fix from commit c5fe8b to the deprecated
non uib-dropdown-menu.

Fixes #4197
Closes #4693
2015-10-22 14:45:14 -06:00
Foxandxss a6cb8d37dd chore(demo): use prefixed
Closes #4674
2015-10-21 13:12:45 -07:00
Rainer Eli 74f9945171 chore(docs): fix typeo in README
Closes #4677
2015-10-21 09:48:08 -06:00
Foxandxss ff9092ec84 chore: remove stale ngDocs folder
Closes #4668
2015-10-20 22:25:11 +02:00
Foxandxss de24f4647f fix(alert): allow interpolations with dismiss-on-timeout
Fixes #4665
Closes #4666
2015-10-20 20:30:05 +02:00
Foxandxss 563410c3cb chore: add link to ng-bootstrap
Closes #4663
2015-10-20 09:40:22 -07:00
Wesley Cho 312dc3e82a chore(datepicker): clean up code style 2015-10-20 04:21:39 -07:00
Adam Gordon 1cba27c1f2 chore(docs): fix uib-popover-tempate description
* clarify description for `uib-popover-template` attribute.

Fixes #4564
Closes #4660
2015-10-19 17:05:15 -06:00
crisbeto 964aa16831 chore(modal): optimize with querySelector
- Change from `querySelectorAll` to more efficient `querySelector`

Closes #4659
2015-10-19 15:48:22 -07:00
Oliver Salzburg 94fb282481 fix(typeahead): dangling event listeners
Fixes #4632
Closes #4636
2015-10-19 21:10:22 +02:00
Wesley Cho 97fd37e226 feat(modal): support $uibModalInstance
- Add support for `$uibModalInstance` as a controller local
- Deprecate `$modalInstance` support

Closes #4638
Closes #4661
2015-10-19 11:37:52 -07:00
Foxandxss 7c3c631075 fix(datepicker): fix support for literal format on popup
- Add check for `uibDatepickerPopup`

Closes #4635
Fixes #4616
2015-10-19 07:33:05 -07:00
Sylvester Keil 6d1cd0f409 fix(collapse): fix collapse animation timing
Closes #4493
2015-10-19 00:01:02 -07:00
Sylvester Keil 82cd2d41d1 Fix collapse animation
Set class 'in' at the end of the animation to mimick the
behaviour of TWBS js. This removes scrollbars which are
otherwise visible during the animation in certain
configurations (most notably when used inside navbars).
2015-10-19 00:00:03 -07:00
Wesley Cho 13be7b78c6 chore(dropdown): clean up code style 2015-10-18 21:19:15 -07:00
Foxandxss 31446331e1 fix(collapse): trigger digest after
Fixes #4647
Fixes #4628
Fixes #4561
Closes #4651
2015-10-18 18:16:07 +02:00
Foxandxss 7985a46ead chore(readme): remove link for old docs 2015-10-17 20:28:03 +02:00
Foxandxss 550ca0f9a7 chore(docs): add docs versioning
Fixes #3670
Closes #4646
2015-10-17 20:24:51 +02:00
Foxandxss c18cb16baa chore(buttons): update tests
Closes #4644
2015-10-16 11:41:57 -07:00
Wesley Cho 59f87fcc95 docs(typeahead): remove erroneous watch
- Remove erroneous documentation that property is watched

Closes #4592
Closes #4634
2015-10-15 14:06:14 -07:00
Foxandxss e8808d3a67 fix(buttons): double toggle on spacebar
Fixes #4474
Closes #4630
2015-10-15 20:01:16 +02:00
RobJacobs 02425b807e fix(tooltip): delay timeouts
The show and hide delay timeouts where not getting
cancelled correctly resulting in tooltips staying
open when both popup and popup-close delays were
in use.

Closes #4621
Fixes #4618
2015-10-14 13:31:17 -07:00
RobJacobs 6c82b2b213 fix(tooltip): scrollbar flashing
When the tooltip is rendered for positioning scroll bars
may breifly appear depending on where the linked element
is positioned. This change adds a negative top and left
style to push the tooltip element out of view while it
is being measured and positioned.

Closes #4550
Closes #4623
Fixes #4458
2015-10-14 13:28:12 -07:00
Filip Sobczak 1f65d87fc3 feat(datepicker): add templateUrl support for pickers
- Add support for custom template urls for `uibDaypicker`, `uibMonthpicker`, and `uibYearpicker`

Closes #4432
2015-10-14 11:46:57 -07:00
Wesley Cho 16dafd5f1b chore(release): Starting v0.14.3-SNAPSHOT 2015-10-13 21:29:21 -07:00
Wesley Cho 539b4723e7 chore(release): v0.14.2 2015-10-13 21:29:05 -07:00
RobJacobs 6daf871863 fix(tooltip): popup close delay not respected
Under PR #4455 the timeout for the popup close delay
was impacted by the evalAsync for setting the isOpen
value. Moved the popup close delay timeout to the
hideTooltipBind method so the hide method will now
get called after the close popup delay. This will
also ensure if the show method is called and the
close timeout is cancelled, the isOpen property
will not get toggled.

Closes #4597
Fixes #4567
2015-10-13 17:04:56 -07:00
Wesley Cho be5802a5da chore(modal): clean up code style 2015-10-13 13:32:17 -07:00
Wesley Cho 8ba3466048 chore(modal): clean up code style 2015-10-13 13:31:31 -07:00
RobJacobs ebb5e18761 fix(tooltip): clean up stackedMap on scope destroy
The tooltip was not being removed from the stackedMap
resulting in a memeory leak.  Tooltip will now be
removed from the stackedMap in scope destroy
function.

Closes #4610

Fixes #4604
2015-10-13 14:09:41 -04:00
JDeuker feb689cf8e fix(progressbar): fix percentage calculation
- Fix percentage calculation when bars are altered

Closes #4471
Closes #4588
Fixes #4452
2015-10-12 08:06:17 -07:00
Wesley Cho 0b1e206141 refactor(typeahead): move logic to controller
- Create `UibTypeaheadController` for decoupling the directive
  implementatino from the controller

Closes #4595
2015-10-12 07:53:06 -07:00
Foxandxss 5646cbe63f chore(readme): add link to the wiki for constructing old docs
Closes #4594
2015-10-12 03:24:36 -07:00
Wesley Cho 68f9530565 chore(modal): clean up code style 2015-10-11 15:46:09 -07:00
Wesley Cho 1a1cd35d80 chore(modal): fix extra character being present 2015-10-11 15:41:11 -07:00
Wesley Cho a1340d72b6 chore(release): Starting v0.14.2-SNAPSHOT 2015-10-11 14:57:29 -07:00
Wesley Cho f9a73a08bd chore(release): v0.14.1 2015-10-11 14:57:03 -07:00
Wesley Cho 4ebecbcca8 feat(timepicker): add accessibility improvements
- Add ng-disabled usage in template
- Add `timepickerTabindex` attribute support for binding tabindex to
  timepicker controls

Closes #4569
Closes #4573
2015-10-11 14:55:40 -07:00
Foxandxss 18371ab1df fix(datepicker): make deprecated controller work with 1.3.x
Closes #4586
2015-10-11 21:24:32 +02:00
Wesley Cho a09275afde docs(datepicker): fix 2009-08-24 button
- Fix button in demo for setting the date

Closes #4587
2015-10-11 12:01:03 -07:00
Wesley Cho 70be195959 docs(datepicker): switch to use uib
- Properly update datepicker configuration

Closes #4575
2015-10-11 11:58:31 -07:00
Foxandxss 1cb4f631b2 chore(readme): add migration guide
Closes #4568
2015-10-11 20:51:00 +02:00
Foxandxss ae1a87c6d2 fix(dropdown): make deprecated controller work with 1.3.x
Closes #4585
2015-10-11 11:34:35 -07:00
Foxandxss 00f60eeb27 fix(timepicker): make deprecated controller work with 1.3.x
Closes #4584
2015-10-11 11:34:08 -07:00
Foxandxss 685bd6a461 fix(tabs): make deprecated controller work with 1.3.x
Closes #4583
2015-10-11 11:33:45 -07:00
Foxandxss ce1114a4ee fix(rating): make deprecated controller work with 1.3.x
Closes #4582
2015-10-11 11:33:22 -07:00
Foxandxss 1c5e4798dd fix(progressbar): make deprecated controller work with 1.3.x
Closes #4581
2015-10-11 11:32:54 -07:00
Foxandxss d50e8d22ac fix(pagination): make deprecated controller work with 1.3.x
Closes #4580
2015-10-11 11:32:25 -07:00
Foxandxss f6c7931e85 fix(carousel): make deprecated controller work with 1.3.x
Closes #4578
2015-10-11 11:31:57 -07:00
Foxandxss 1e3cbd82ed fix(buttons): make deprecated controller work with 1.3.x
Closes #4577
2015-10-11 11:31:23 -07:00
Foxandxss e8c8ee6cd2 fix(alert): make deprecated controller work with 1.3.x
Closes #4576
2015-10-11 11:30:48 -07:00
Foxandxss c5e6042bf2 fix(accordion): make deprecated controller work with 1.3.x
Closes #4574
2015-10-11 11:30:12 -07:00
Wesley Cho 9e71da8d1a chore(docs): fix links in changelog 2015-10-09 15:51:38 -07:00
Wesley Cho d668ce14f6 chore(demo): update to angular 1.4.7 2015-10-09 09:50:53 -07:00
Wesley Cho 6bb2f550eb chore(release): Starting v0.14.1-SNAPSHOT 2015-10-08 21:23:52 -07:00
Wesley Cho c7cc9eab88 chore(release): v0.14.0 2015-10-08 21:23:25 -07:00
Adam Gordon 0ad7cb9ed1 fix(datepicker): add custom class to year picker
* add missing custom class to year picker

Closes #4558
Fixes #4546
2015-10-08 16:03:36 -07:00
Foxandxss 32729600c6 chore: add tooltip/popover classes by hand
Closes #4557
2015-10-08 15:30:32 -07:00
Foxandxss 22f1a4b6c4 chore(modal): add modal-backdrop class by hand
Closes #4556
2015-10-08 14:47:38 -07:00
RobJacobs 01b9624ef0 fix(tooltip): check for ttScope in $$postDigest
In the tooltip $$postDigest function a check is done
on ttScope.isOpen but ttScope may have been set to null
in the scope.$on('$destroy'...) function.  Added a
check to make sure ttScope is defined and not null.

Closes #4555
Fixes #4552
2015-10-08 15:52:07 -04:00
Wesley Cho c9ab5f63bf chore(demo): remove safari 6 fallback 2015-10-08 08:03:26 -07:00
Wesley Cho 7675457a06 chore(modal): remove unnecessary restrict options 2015-10-08 08:00:13 -07:00
Wesley Cho 53bb69ee62 Revert "chore(modal): change to $uibModalStack"
This reverts commit adf68ebc35.
2015-10-08 07:56:17 -07:00
Wesley Cho adf68ebc35 chore(modal): change to $uibModalStack 2015-10-08 07:55:18 -07:00
Wesley Cho f900fdd321 chore(dropdown): change to output warning after controller check 2015-10-08 07:52:40 -07:00
Wesley Cho 305dc2e1f8 chore(dropdown): fix to use uibKeyboardNav 2015-10-08 07:49:03 -07:00
Wesley Cho b1862d32dc chore(typeahead): change to uibTypeaheadPopup 2015-10-08 07:36:28 -07:00
Foxandxss 694a0116e3 chore(demo): use prefixed directives 2015-10-08 14:21:39 +02:00
Wesley Cho 44354f67e5 feat(datepicker): add uib- prefix
Closes #4509
2015-10-08 14:05:50 +02:00
bob 9e5e1a2eab feat(typeahead): add uib- prefix
Closes #4542
2015-10-07 09:45:56 -07:00
Wesley Cho 038157dd57 chore(accordion): simplify controller instantiation 2015-10-06 23:49:28 -07:00
Wesley Cho 001574e5ef chore(alert): simplify controller instantiation 2015-10-06 23:48:55 -07:00
Wesley Cho 4db0f95c95 chore(buttons): simplify controller instantiation 2015-10-06 23:48:35 -07:00
Wesley Cho dc8379a014 chore(dropdown): simplify controller instantiation 2015-10-06 23:47:58 -07:00
Wesley Cho a76fd08dc3 chore(progressbar): simplify controller instantiation 2015-10-06 23:47:19 -07:00
Wesley Cho 795b7cf736 chore(rating): simplify controller instantiation 2015-10-06 23:46:52 -07:00
Wesley Cho 18590f065f chore(tab): simplify controller instantiation 2015-10-06 23:46:23 -07:00
Wesley Cho adebde9044 chore(timepicker): simplify controller instantiation 2015-10-06 23:45:43 -07:00
Tom McGeehon 5f7051b38f feat(tooltip): allow custom closing delay
- Add support for `tooltipClosePopupDelay` for customizing close timeout

Closes #3576
2015-10-05 09:35:52 -07:00
Foxandxss d4adef7834 chore(tooltip): fix wrong deprecation message 2015-10-05 12:58:14 +02:00
Wesley Cho f8bc038db6 feat(tooltip): add uib- prefix
Closes #4515
2015-10-05 12:04:21 +02:00
bob 9aea856f11 feat(pagination): add uib- prefix
Closes #4536
2015-10-05 11:53:06 +02:00
Foxandxss 4e60e22c49 docs: add tooltip and popover workaround
Closes #4535
2015-10-05 11:43:37 +02:00
Foxandxss 8c7b9e4c78 feat(modal): add uib- prefix
Closes #4511
2015-10-05 11:42:02 +02:00
Wesley Cho 30e8aa71e2 fix(carousel): re-enable deprecated directives
- Re-implement deprecated directives
- Re-expose `CarouselController` with deprecation notice

Closes #4527
2015-10-04 17:06:09 -07:00
Patrick Sullivan 6b4267b2d3 fix(datepicker): datepicker-popup nest in dropdown
- Add `dropdown-nested` class hack to avoid problems with dropdown
  controller

Closes #4489
Fixes #4197
2015-10-03 17:25:39 -07:00
Wesley Cho 0b3d5bd38c fix(carousel): reset $currentTransition when no slides
- Reset `$currentTransition` when there are no slides

Closes #4532
Fixes #4390
2015-10-03 14:09:36 -07:00
Wesley Cho 3aa984182e fix(timepicker): re-expose TimepickerController
- Re-expose `TimepickerController` with deprecation notice

Closes #4531
2015-10-03 14:08:16 -07:00
Wesley Cho 435924f201 fix(tabs): re-expose TabsetController
- Re-expose `TabsetController` with deprecation notice

Closes #4530
2015-10-03 14:06:46 -07:00
Wesley Cho aede646189 fix(rating): re-expose RatingController
- Re-expose `RatingController` with deprecation notice

Closes #4529
2015-10-03 14:05:55 -07:00
Wesley Cho 5604e59586 fix(progressbar): re-expose ProgressController
- Re-expose `ProgressController` with deprecation notice

Closes #4528
2015-10-03 14:04:58 -07:00
Wesley Cho 92ab48ece5 fix(dropdown): ensure class is present in dropdown-menu
- Ensure `dropdown-menu` class is present when using as an attribute
  directive
- Refactor `DropdownController` to be more agnostic of directive

Closes #4523
Fixes #4442
2015-10-03 14:01:57 -07:00
Wesley Cho c0dbf793ba fix(buttons): re-expose ButtonsController
- Re-expose `ButtonsController` with deprecation message

Closes #4526
2015-10-03 14:00:10 -07:00
Wesley Cho f561aa9e95 fix(alert): re-expose AlertController
- Re-expose `AlertController` with deprecation message

Closes #4525
2015-10-03 11:13:24 -07:00
Wesley Cho 5382226a54 fix(accordion): re-expose AccordionController
- Expose `AccordionController` with deprecation message

Closes #4524
2015-10-03 11:12:06 -07:00
Wesley Cho db36c62f99 chore(carousel): clean up code style 2015-10-03 10:02:16 -07:00
Wesley Cho e7c58791af fix(dropdown): restore deprecated directives
- Adds uib- prefix to `dropdownConfig`
- Restores functionality to deprecated directives

Closes #4514
2015-10-03 09:01:29 -07:00
Wesley Cho 8fa158769d chore(buttons): update docs
Closes #4517
2015-10-03 01:39:19 -07:00
Wesley Cho 3a3b383f2f chore(progressbar): update docs
Closes #4518
2015-10-03 01:38:05 -07:00
Wesley Cho 8d19c608e0 chore(rating): update docs
Closes #4519
2015-10-03 01:37:26 -07:00
Wesley Cho d1555dcdb6 chore(timepicker): update docs
Closes #4520
2015-10-03 01:36:52 -07:00
Wesley Cho 7b7039b4d9 chore(typeahead): remove unnecessary $digest
- Removes unnecessary $digest inside $timeout

Closes #4521
2015-10-03 01:35:29 -07:00
Wesley Cho 85d7748162 chore(progressbar): clean up code style 2015-10-02 23:57:05 -07:00
Steven Pribilinskiy 2e268151e2 fix(carousel): fix reading of noTransition
- Check the correct DOM node for animation settings

Closes #4325
2015-10-02 22:53:52 -07:00
Wesley Cho 6f9f1fcf6b revert(dropdown): undo adding of open class on body
This reverts commit bf63cef0aa.
2015-10-02 22:43:31 -07:00
bob 5bc0851c08 feat(dropdown): uib- prefix
Closes #4510
2015-10-02 15:28:36 -07:00
Wesley Cho 615809169b feat(position): add uib- prefix
Closes #4507
2015-10-02 13:09:13 -07:00
Wesley Cho 504e653f6b feat(timepicker): use uib- prefix
Closes #4505
2015-10-02 13:08:04 -07:00
Wesley Cho 66819c2ad0 chore(carousel): remove whitespace 2015-10-01 23:17:36 -07:00
Chad King 2e5bfaca3b feat(carousel): use uib- prefix
Closes #4501
2015-10-01 23:16:50 -07:00
Wesley Cho 0fa851fb80 feat(dateparser): use uib- prefix
Closes #4504
2015-10-01 21:32:30 -07:00
Wesley Cho 298ec8cf20 feat(accordion): use uib- prefix
Closes #4503
2015-10-01 21:30:48 -07:00
Wesley Cho 377b4b7962 feat(rating): user uib- prefix
Closes #4502
2015-10-01 16:32:11 -07:00
keith fdf53e6461 feat(typeahead): add appendElementToId
- Add appending popup to specific id

Closes #4231
Closes #4497
2015-09-30 16:29:36 -07:00
Wesley Cho 8919b0a08e chore(typeahead): clean up code style 2015-09-30 13:35:20 -07:00
Foxandxss e432059aed chore(demo): use prefix on tabs
Closes #4480
2015-09-28 15:59:53 -07:00
Adam Gordon d25a8c245b feat(tabs): use uib- prefix
Close #4449
2015-09-26 18:49:49 +02:00
Wesley Cho 23a312d5c1 chore(carousel): change to empty hrefs 2015-09-25 15:23:09 -07:00
Evan.Duncan da711594f8 fix(carousel): improve accessibility
- Improves accessibility of carousel

Closes #4478
Closes #4479
2015-09-25 15:21:26 -07:00
Foxandxss 19118f162e refactor(buttons): match general style
Closes #4465
2015-09-24 14:46:36 -07:00
Foxandxss ec6c0bca1b style(buttons): change bind to on
Closes #4464
2015-09-24 14:46:02 -07:00
RobJacobs 81a38d7261 refactor(tooltip): rollup commit for several issues
This is a rollup commit intended to address several
issues around the positioning and parsing of
attributes.

- Fixes issue introduced under PR #4311 where setting
  height and width in tooltip position function
  messed up arrow placement.
- Fixes issue introduced under PR #4363 where setting
  visibility to hidden in tooltip position function
  caused elements in popover to lose focus.
- Fixes issue #1780 where tooltip would render if
  content was just whitespace.
- Fixes issue #3347 where tooltip isolate scope was
  being accessed after it was set to null.  Observers
  will now be created/destroyed as tooltip opens/closes
  which will also offer a performance improvement.
- Fixes issue #3557 by implementing evalAsync to set
  tooltip scope isOpen property.
- Fixes issue #4335 where if model isOpen property is
  undefined, tooltip would call show/hide toggle function.
- Closes PR #4429 where how the templated content
  was being evaluated could cause an infinite digest loop.

Closes #4400
Closes #4418
Closes #4429
Closes #4431
Closes #4455

Fixes #1780
Fixes #3347
Fixes #3557
Fixes #4321
Fixes #4335
2015-09-23 19:38:06 -04:00
Foxandxss a59caf183d chore(demo): update collapse to use prefix
Closes #4446
2015-09-23 12:04:47 +02:00
Foxandxss 5a1c2c9a27 feat(buttons): use uib- prefix
Closes #4445
2015-09-23 12:02:10 +02:00
ehtesham 4031e29cae docs(typeahead): add custom template demo
Closes #4412
2015-09-23 11:59:56 +02:00
Wesley Cho 2c0ad03f8a chore(docs): bump up angular version 2015-09-17 19:51:17 -07:00
Wesley Cho bba0e686dc chore(tooltip): clean up code style 2015-09-17 06:55:50 -07:00
Tobias Gunkel d9a521a4e5 feat(dateparser): reset parsers when $locale.id changes
- Reset parsers when $locale.id changes to take into account changed
  localization settings

Closes #4286
Closes #4425
2015-09-16 23:07:03 -07:00
Yousuf Jukaku 868c0e248d fix(datepicker): add check for contains
Closes #4423
Fixes #4411
2015-09-16 09:35:07 -07:00
Wesley Cho b74c263fd5 Revert "feat(typeahead): add customClass support for dropdown"
This reverts commit fa1cdfccd3.
2015-09-16 06:40:58 -07:00
Nadi fa1cdfccd3 feat(typeahead): add customClass support for dropdown
- Adds support for custom classes on the typeahead dropdown

Closes #4332
Closes #4410
2015-09-15 15:44:33 -07:00
Wesley Cho 7ba252787c chore(timepicker): clean up code style 2015-09-14 00:26:53 -07:00
Wesley Cho fb90152c7e chore(tooltip): clean up code style 2015-09-14 00:24:14 -07:00
Wesley Cho b10a48b5ed chore(tooltip): clean up code style 2015-09-14 00:21:47 -07:00
Wesley Cho cbf2c0d1e4 chore(dropdown): clean up code style 2015-09-14 00:18:48 -07:00
Wesley Cho fabf0161ce chore(dropdown): clean up code style 2015-09-14 00:17:55 -07:00
Martin Magana 36ecf60c23 fix(datepicker): remove focus management on date selection by keyboard
BREAKING CHANGE:

Removes focus on datepicker on selection of a date via keyboard for accessibility reasons

Closes #4409
2015-09-13 22:24:49 -07:00
Jesus Rodriguez 5e3a87a91e feat(alert): use uib- prefix
Closes #4406
2015-09-12 00:04:00 +02:00
Jesus Rodriguez a04b4ff284 refactor(alert): move dismiss-on-timeout to an attribute
Closes #4405

BREAKING CHANGE: Alert's dismiss-on-timeout is now an attribute inside uib-alert.
2015-09-11 16:20:24 +02:00
Wesley Cho d1babb64e9 docs(changelog): update with breaking change
Closes #3256
2015-09-10 22:21:48 -04:00
Jesus Rodriguez 641cdb32d8 chore(accordion): clean some stale code and comments
Closes #4394
2015-09-10 21:59:45 -04:00
Jesus Rodriguez b1fdca5da2 chore(accordion): add missing test for $destroy
Closes #4393
2015-09-10 21:57:28 -04:00
Jesus Rodriguez fcb08e9dfc chore(accordion): clean tests a bit
Closes #4392
2015-09-10 21:55:41 -04:00
Jesus Rodriguez 47076029f1 chore(accordion): test that any other keyCode wont work
Closes #4399
2015-09-10 21:54:19 -04:00
Wesley Cho 252837158b chore(changelog): fix formatting 2015-09-10 20:59:34 -04:00
Wesley Cho 9d6ab9665b docs(changelog): update with breaking change for tooltip
Closes #4364
2015-09-10 20:58:23 -04:00
Wesley Cho 65814f1e95 fix(datepicker): change to $popup 2015-09-10 20:38:59 -04:00
Jesus Rodriguez 53f5f477ef docs(collapse): update them yet again to latest design
Closes #4397
2015-09-10 15:32:16 +02:00
Jesus Rodriguez 4d01387a1b chore(accordion): update docs to match the general style
Closes #4395
2015-09-10 15:30:39 +02:00
Wesley Cho c08509a071 feat(tooltip): hide tooltip when esc is hit
- Hide tooltip when `esc` is hit for accessibility

Closes #4367
Resolves #4248
2015-09-10 07:08:20 -04:00
Wesley Cho f26998303d chore(carousel): clean up code style 2015-09-10 07:04:56 -04:00
Wesley Cho 365cdd6acb chore(carousel): clean up code style 2015-09-10 07:04:47 -04:00
Pavel R3VoLuT1OneR Zhytomirsky bd38e8f355 feat(modal): Added ability to add CSS class to top window
- Added ability to add a class to the most recently opened modal window.
  Note that even if different classes are specified, the class will
only be present if the modal is the most recently opened modal, i.e. if
modal1 was opened with a top class of `foo`, and modal2 is opened
afterwards with a top class of `bar`, modal2 will have the class `bar`
for the modal window, and modal1 will not have the class `foo`.

Closes #2524
2015-09-10 06:44:15 -04:00
Jesus Rodriguez 0328a7630a feat(accordion): use uib- prefix
Closes #4389
2015-09-10 06:31:36 -04:00
Wesley Cho eb2366fe11 fix(alert): properly pass $event as local
- Change to pass object due to how `&` binding works

Fixes #4386
Closes #4387
2015-09-09 21:13:42 -06:00
Wesley Cho d6cda93aff fix(tooltip): fix binding to multiple triggers
- Due to switch to raw `addEventListener`, changed to add and remove
  listeners to event triggers by iteration

Fixes #4371
Closes #4384
2015-09-09 21:10:07 -06:00
Wesley Cho 8ae664fa2e chore(tabs): remove disabled support
- Remove deprecated `disabled` support

Closes #4383
2015-09-09 20:58:49 -06:00
VitalyVoroshilov ff52f52a8d fix(tooltip): properly gc popupTimeout
- Make sure to cancel timeout before setting to `null`

Closes #2786
2015-09-09 10:51:50 -04:00
RobJacobs 5f68280ad0 fix(tooltip): isOpen to work with expressions
The is-open attribute should work with expressions
as well as model values

Closes #4380
Fixes #4362
2015-09-09 10:19:56 -04:00
Wesley Cho c064748536 chore(accordion): change to !! 2015-09-09 05:08:55 -04:00
Sylvester Keil b864aa9c81 fix(accordion): coerce to boolean
- Coerce `toggleClass` argument to boolean due to jQuery ignoring
  `undefined`

Closes #4385
2015-09-09 05:07:18 -04:00
Wesley Cho cf92eae985 chore(carousel): clean up code style 2015-09-09 04:39:39 -04:00
Wesley Cho e6f3b874cb feat(progressbar): add aria-labelledby support
- Add `aria-labelledby` support for accessibility

Closes #4350
Resolves #4347
2015-09-09 03:55:11 -04:00
Jesus Rodriguez 9bdb32ed8f feat(collapse): use uib- prefix
Closes #4370
2015-09-08 16:36:28 -04:00
Wesley Cho 79e38cbce7 chore(tooltip): clean up code style 2015-09-08 16:33:34 -04:00
RobJacobs b413a226a4 fix(tooltip): add display block to style
- Adds style override to fix `display: none` being set by Bootstrap's
  CSS

Closes #4363
Closes #4379
2015-09-08 16:30:09 -04:00
Jesus Rodriguez 9d80066321 docs(collapse): update docs to latest version
Closes #4377
2015-09-08 16:29:17 -04:00
Jesus Rodriguez c4b7e04b7c chore(contributing): add note about prefixes work
Closes #4376
2015-09-08 16:28:15 -04:00
Wesley Cho d11c3d0ef0 chore(bindHtml): remove unused module
Closes #4374
Closes #4375
2015-09-08 16:26:45 -04:00
Jesus Rodriguez ddfca61360 chore(typeahead): update demo to use ngBindHtml
Closes #4378
2015-09-08 16:26:15 -04:00
Damien Abos 8fee75d517 fix(tooltip): correct flash of reposition
- Avoid position computation when tooltip is empty
- Force visibility to none when resetting style

Closes #4363
Fixes #4195
2015-09-07 19:18:02 -04:00
Wesley Cho 72de2d80e7 feat(rating): add aria-valuetext attribute
- Add `aria-valuetext` attribute on each star element for accessibility

Closes #4349
Resolves #4347
2015-09-07 19:16:28 -04:00
Wesley Cho af2d1ef4e5 docs(rating): add aria-labelledby
- Add usage of `aria-labelledby` to aid in demonstrating accessibility

Closes #4246
Closes #4348
2015-09-07 19:15:16 -04:00
Jesus Rodriguez 50ebfc3db0 chore(progressbar): switch deprecation warnings
Closes #4366
2015-09-07 19:14:40 -04:00
Jon Iñiguez de Heredia 508acebe8e fix(modal): fix for conflicts with ngTouch module on mobile devices
- Merge pull request #3044 from jiniguez/fix2280
Conflicts:
	src/modal/modal.js
	template/modal/window.html

Fixes #2280
Closes #4357
2015-09-07 11:48:22 -07:00
Jesus Rodriguez 745c57d41b docs(progressbar): fix the prefix 2015-09-07 17:55:14 +02:00
btrauma8 1e039e86b6 fix(tooltip): do nothing if $scope doesn't exist
- Do nothing on hide when `$scope` is already removed

Closes #4346
Fixes #3347
2015-09-04 13:43:09 -07:00
Di Huang f7cb8bc014 fix(tooltip): set visibility: hidden to avoid flicker
- Set `visibility: hidden` and then to `visible` to avoid flicker from positional movement

Closes #4342
2015-09-04 13:08:42 -07:00
Adam Gordon 5482db2edd docs(accordion): fix accordion demo
* fix accordion demo for last panel
* last panel was previously the markup example so moving just the close toggle
  was not sufficient and moving the markup as well would have rendered that
  specific accordion example obsolete.  so this restores the markup accordion
  back to original and moves to the last accordion example.

Closes #4344
2015-09-04 11:25:09 -07:00
Adam Gordon 31e04a85a9 docs(accordion): fix accordion demo
* fix toggle last panel

Closes #4341
2015-09-04 10:21:07 -07:00
Jesus Rodriguez 1583dde5e2 chore(collapse): clean some stale test headers
Closes #4340
2015-09-04 10:20:17 -07:00
Wesley Cho 533a9f03c6 feat(collapse): convert to use $animateCss
- Change to use `$animateCss` when available

Closes #4257
2015-09-04 12:04:48 +02:00
Adam Gordon 0a69580432 docs(changelog): fix breaking changes
* fix breaking changes section for 0.13.4 release.

Closes #4337
2015-09-03 23:46:30 -07:00
Jesus Rodriguez b6635e68e3 chore(collapse): fix test
Closes #4304
Closes #4336
2015-09-03 12:48:32 -07:00
Wesley Cho da6924eba2 chore(tooltip): remove deprecated code
BREAKING CHANGE:
Remove the unsafe html support from the tooltip

Closes #4334
2015-09-03 10:13:49 -07:00
Wesley Cho 8b809b2831 chore(changelog): generate changelog 2015-09-03 08:00:19 -07:00
Chris Chua dfa4c97cb6 chore(transition): remove transition module
BREAKING CHANGE:
The `transition` module along with its `$transition` service are no longer
available. We're now using `$animate` service for animations and would
encourage users to do the same.

Closes #4359
2015-09-03 07:29:36 -07:00
Wesley Cho 833e7ad765 chore(demo): bump up version of angular in docs 2015-09-03 07:22:06 -07:00
Wesley Cho 20739e4a2e chore(release): Starting v0.14.0-SNAPSHOT 2015-09-03 07:10:21 -07:00
Wesley Cho eec160855f chore(release): v0.13.4 2015-09-03 07:10:20 -07:00
Wesley Cho 86e35a7740 chore(build): fix changelog task reference 2015-09-03 07:09:37 -07:00
Adam Gordon defcbbb1b6 fix(dropdown): fix up arrow nav support
* add support for when user opens dropdown and then presses the up arrow key.

Closes #4330
Fixes #4327
2015-09-02 16:11:38 -07:00
unknown c7d669fd38 refactor(tooltip): optimize positioning routine
Wrapped position logic in a timeout to ensure the
digest cycle always completes before positioning
the popup.  Also optimized when the calls to
position the popup occur.

Closes #4328
2015-09-02 09:29:53 -07:00
Wesley Cho 7556beda48 fix(tooltip): switch to use raw DOM event bindings
- Switch to use `addEventListener` and `removeEventListener` to prevent
  jqLite/jQuery bug where the events are swallowed on disabled elements

Closes #4322
Fixes #4060
2015-09-01 13:39:01 -07:00
Wesley Cho d891c8da3f chore(tooltip): clean up code style 2015-09-01 13:04:25 -07:00
Wesley Cho ae6583d54c chore(collapse): clean up code style 2015-09-01 11:40:28 -07:00
Wesley Cho 4b026481c9 feat(typeahead): add custom popup template support
- Add support for custom popup templates

Closes #4320
Resolves #3774
2015-09-01 06:31:43 -07:00
Wesley Cho aa5a991ea5 feat(accordion): support spacebar to toggle group
- Allow spacebar to toggle the accordion group

Closes #4319
Resolves #4249
2015-09-01 06:30:32 -07:00
Wesley Cho 9b2f7ac315 fix(datepicker): ensure the original target is not in popup
- Ensure that the original event target is not a child of the popup element to avoid edge case where the datepicker closes on any click

Closes #4316
Fixes #4314
2015-09-01 06:29:32 -07:00
Wesley Cho 3b35349320 chore(accordion): clean up code style 2015-08-31 23:00:54 -07:00
Wesley Cho 44fd16cd13 chore(accordion): clean up code style 2015-08-31 23:00:39 -07:00
Wesley Cho ccaa6272eb fix(typeahead): add support for ngModelOptions getterSetter
- Add support for getterSetter with ngModelOptions

Closes #3865
Fixes #3823
2015-08-31 14:21:52 -07:00
Wesley Cho 56bdb1c104 chore(datepicker): fix typo 2015-08-31 09:04:33 -07:00
Damien Abos 457f10c92b fix(tooltip): correctly position tooltip
- Use a style reset so the DOM recalculates values before correctly positioning the tooltip

Closes #4311
Fixes #4195
2015-08-31 09:00:30 -07:00
Wesley Cho b1e98b1f79 fix(modal): fix allowing promises to be resolved
- Wrap values otherwise and push to resolve handler

Closes #4310
Fixes #4309
2015-08-30 23:42:07 -07:00
Wesley Cho bf63cef0aa fix(dropdown): fix display when using with append-to-body
- Change to add `dropdown` class and open class to the `<body>` element

BREAKING CHANGE: This differs from the existing behavior in that it no longer will toggle based on the existing `dropdown` directive element, but on the `body` element instead

Closes #4305
Fixes #4240
2015-08-30 15:20:16 -07:00
Wesley Cho 49a0858a80 chore(dropdown): fix code style 2015-08-28 16:32:05 -07:00
Wesley Cho 0be8778b67 chore(dropdown): fix code style 2015-08-28 16:31:39 -07:00
yoann-antoviaque 695db9d53e fix(typeahead): release references on destruction
- Release reference to manually managed scopes, which prevent proper garbage collection

Closes #4299
Fixes #4298
2015-08-28 16:13:18 -07:00
Nathan Williams 1bba8b4bf5 feat(modal): complete modal open resolution in order
- Ensure modals resolve in order they were opened

Closes #2443
Closes #4302
Resolves #2404
2015-08-28 16:00:42 -07:00
wawyed 937a1f3f78 fix(modal): Wait for animation before focus.
- focus modal only after animation completes

Closes #4300
Fixes #4274
2015-08-28 15:54:02 -07:00
Jesus Rodriguez 5a44eb2f38 chore(tests): bump to 1.4.5
Closes #4303
2015-08-28 15:51:13 -07:00
Wesley Cho 9b094a0d31 chore(npm): remove ngAnimate 2015-08-28 14:43:18 -07:00
Wesley Cho ad760434e8 chore(tests): fix several issues 2015-08-28 14:41:01 -07:00
Wesley Cho 1914955a10 chore(npm): re-add angular-animate 2015-08-28 14:34:41 -07:00
Matthew Davies 5229c204df chore(datepicker): fixed typo in docs
Closes #4301
2015-08-28 14:26:13 -07:00
Wesley Cho a06afe6bc1 feat(buttons): hide nested inputs
- Hide nested input elements

Closes #4282
2015-08-28 14:24:59 -07:00
Adam Gordon ef668f67f3 docs(changelog): fix breaking changes
* update breaking changes section to include #3419

Closes #4295
2015-08-28 14:24:10 -07:00
Adam Gordon 639d5117b7 feat(timepicker): add templateUrl and controllerAs support
* Add support for overriding the `templateUrl` on an instance by instance basis
* Expose controller via `controllerAs`

Fixes #4275
Closes #4284
2015-08-28 10:53:39 -06:00
Adam Gordon 53c94be934 docs(readme): add clarity on angular requirement
* add note strongly recommending the use of Angular 1.3.18 or higher for UI
  Bootstrap 0.13.3 and higher due to animation fixes.

Closes #4277
Closes #4278
2015-08-28 09:52:11 -06:00
Jesus Rodriguez afa8cdda5d chore(alert): remove restrict
Closes #4280
2015-08-26 20:14:45 +02:00
Jesus Rodriguez 1b76695c46 docs(accordion): markdown cleanup
Also rephrased the template part a bit.

Closes #4281
2015-08-26 20:12:20 +02:00
Jesus Rodriguez c31a7cce97 docs(alert): revamp to match the general style
Closes #4279
2015-08-26 20:11:00 +02:00
Adam Gordon f50a4d6138 docs(alert): specify dismiss-on-timeout requirements
* update alert docs to specify that the use of `dismiss-on-timeout` requires
  the use of the `close` attribute.

fixes #4268
Closes #4269
2015-08-26 18:11:21 +02:00
Jesus Rodriguez 5ee6f0e39e docs(accordion): update demo and docs to match latest version
Closes #4267
2015-08-25 20:26:07 +02:00
Wesley Cho 6af48e18d5 chore(typeahead): fix code style 2015-08-24 17:07:50 -07:00
Wesley Cho d0653c81b2 chore(tooltip): clean up code style 2015-08-24 00:45:12 -07:00
Wesley Cho bdfb28916e feat(buttons): allow toggling via spacebar when focused
- Allow the spacebar to toggle the button state when focused

Closes #4252
Closes #4259
2015-08-23 06:42:21 -07:00
Adam Gordon 5ee23a4c26 feat(accordion): allow custom panel class
- add support for custom panel class

Closes #4242
Fixes #3968
2015-08-21 09:14:20 -07:00
Wesley Cho 07a938d124 fix(progress): rename to avoid conflict
- Rename to `ui-progress` and `ui-bar`

Closes #4255
2015-08-21 08:33:44 -07:00
Casey Garland 7d3ba1e10e fix(tabs): ensure tab selection only occurs once
- Fix issue where select callback is fired twice due to compilation order when using dynamic tabs mixed with static tabs

Closes #3060
Closes #4230
Fixes #2883
2015-08-18 16:22:27 -07:00
Wesley Cho 790d6b97f1 chore(tabs): fix code style 2015-08-18 12:36:48 -07:00
Wesley Cho 3492c26259 chore(modal): clean up code style 2015-08-18 09:35:44 -07:00
Wesley Cho dac087eb89 feat(carousel): add model binding support to slide
- Add support for binding slide model to slide

Closes #4202
Resolves #4201
2015-08-18 09:33:34 -07:00
Wesley Cho 3d01c597b9 feat(modal): support multiple open classes
- Support multiple modal open classes when multiple modals are open

Closes #4226
Fixes #4184
2015-08-18 09:23:02 -07:00
Jonathan Gawrych 550fe20d65 feat(dateparser): add support for the h format
- Adds support for the `h` format

Closes #4220
2015-08-17 14:46:27 -07:00
Jonathan Gawrych 734bd6a566 test(datepicker): fix incorrect format used in hh test
Closes #4221
2015-08-17 14:43:23 -07:00
Wesley Cho ba734b4e63 feat(pagination): add ngDisabled support for the pager
- Add `ngDisabled` support to the pager component

Closes #4217
Resolves #2856
2015-08-17 12:54:36 -07:00
Wesley Cho 0b03a01faf chore(datepicker): fix model for max date in demo 2015-08-17 12:54:16 -07:00
Wesley Cho 432b4eb93e chore(build): change to updated changelog task 2015-08-17 07:44:28 -07:00
FernandoSendMail bb9fa1a2a5 fix(typeahead): use ng-bind-html
- Switches to use `ng-bind-html` from `bind-html-unsafe`

BREAKING CHANGE: This modifies the typeahead to use the the `$sce` service instead when `ngSanitize` is present

Closes #3463
Resolves #4073
2015-08-17 07:14:24 -07:00
Wesley Cho aaec2f4d84 chore(typeahead): clean up code style 2015-08-16 13:08:03 -07:00
Wesley Cho 42dab29a3e chore(datepicker): clean up code style 2015-08-16 13:02:40 -07:00
Wesley Cho 86a91da916 chore(progressbar): use reduce instead of forEach 2015-08-16 12:32:11 -07:00
Wesley Cho 30dd34f9dc chore(progressbar): clean up code style 2015-08-16 12:29:41 -07:00
Wesley Cho aaf65bbda6 chore(accordion): clean up code style 2015-08-16 12:29:02 -07:00
Wesley Cho 773af482c2 chore(modal): fix garbage collection in test 2015-08-16 12:08:14 -07:00
Wesley Cho 16ff411b81 chore(datepicker): fix garbage collection in test 2015-08-16 12:07:33 -07:00
Jesus Rodriguez b5ecda30c3 feat(typeahead): add typeaheadFocusOnSelect
Closes #4212
Closes #4211
Fixes #4206
2015-08-16 19:25:12 +02:00
Wesley Cho f8eab5594b fix(tooltip): properly gc timeout on toggle of disabled
- When `disabled` attribute changes, properly garbage collect the timeout

Closes #4210
Fixes #4204
2015-08-15 11:59:58 -07:00
Wesley Cho 71e0b8a981 feat(datepicker): disable today button if invalid
- Disable today button if current date is before `min-date` or after
  `max-date`

Closes #4199
Resolves #3988
2015-08-14 12:21:19 -07:00
Jesus Rodriguez 8e84567555 chore(modal): fix tests for Angular 1.4.4
Closes #4207
2015-08-14 07:48:52 -07:00
Wesley Cho cd4822dcf0 docs(pagination): fix display 2015-08-14 04:14:21 -07:00
Dave Anderson 575eb8593a fix(accordion): add custom open class support
- Add support for using custom class when accordion is opened

Closes #4198
2015-08-13 10:56:55 -07:00
Wesley Cho dccd619755 chore(timepicker): fix code style 2015-08-12 23:38:41 -07:00
Wesley Cho f36b61d7a2 chore(timepicker): fix code style 2015-08-12 22:31:25 -07:00
Wesley Cho a366648c38 chore(timepicker): code style fix 2015-08-12 22:05:27 -07:00
Wesley Cho 07f51356f4 Revert "chore(timepicker): code style fix"
This reverts commit bb460c380d.
2015-08-12 22:04:29 -07:00
Wesley Cho bb460c380d chore(timepicker): code style fix 2015-08-12 22:04:05 -07:00
Wesley Cho 401c2d127c chore(timepicker): code style cleanup 2015-08-12 21:42:03 -07:00
Wesley Cho 0e32664ca0 chore(timepicker): clean up code style 2015-08-12 21:30:38 -07:00
Wesley Cho fba7bfb5ef chore(datepicker): fix code style 2015-08-11 22:57:27 -07:00
Wesley Cho 5b0c10922b chore(datepicker): minor code style fixes 2015-08-11 11:13:12 -07:00
Wesley Cho f9b761d0eb chore(datepicker): minor code style fixes 2015-08-11 09:05:15 -07:00
Wesley Cho da8821fc58 chore(datepicker): minor code style fixes 2015-08-11 09:02:18 -07:00
Wesley Cho 8213e7b5aa chore(npm): update dependencies 2015-08-11 08:50:44 -07:00
Wesley Cho 17cc39f4b7 fix(tooltip): fix jshint error 2015-08-11 08:48:47 -07:00
Wesley Cho 581161d577 chore(typeahead): unify code style 2015-08-11 07:35:09 -07:00
Wesley Cho f3b68b3810 chore(tooltip): unify code style 2015-08-11 07:21:34 -07:00
Wesley Cho 20f525ba0e chore(timepicker): unify code style 2015-08-10 16:46:09 -07:00
Wesley Cho 94acfda024 chore(tabs): unify code style 2015-08-10 16:29:33 -07:00
Wesley Cho ed236b318c chore(rating): unify code style 2015-08-10 14:33:33 -07:00
Wesley Cho e7761b4485 chore(progressbar): unify code style 2015-08-10 14:30:26 -07:00
Wesley Cho 0d6b897e91 chore(position): unify code style 2015-08-10 14:27:41 -07:00
Wesley Cho 71360800a3 chore(popover): unify code style 2015-08-10 14:24:18 -07:00
Wesley Cho 467292ad6c chore(modal): unify code style 2015-08-10 13:34:47 -07:00
RobJacobs 99b87cc07b feat(tooltip): expose isOpen property
Add support for toggling the isOpen
property of the tooltip.

Closes #4179
Closes #2148
Fixes #590
2015-08-10 12:12:27 -07:00
Wesley Cho dbd6f737cd chore(pagination): unify code style
- Fix up the code style for consistency

Closes #4176
2015-08-10 09:10:24 -07:00
Wesley Cho ba2ce243b0 fix(modal): correctly remove custom class
- Fix removal of custom class on closing/dismissing of modal

Closes #4175
Fixes #4171
2015-08-10 09:09:47 -07:00
Wesley Cho ace4ae19e2 chore(dropdown): unify code style
- Update code style to be more consistent

Closes #4167
2015-08-10 09:08:54 -07:00
Wesley Cho 1abfd057ee feat(tabs): add support for x-tab-heading
- Add support for `x-tab-heading` attribute and element

Closes #4166
Fixes #1893
2015-08-10 09:07:59 -07:00
Wesley Cho 84cc5f0656 chore(datepicker): unify code style
- Clean up code style to be more consistent

Closes #4165
2015-08-10 09:07:20 -07:00
Wesley Cho 32f002dbfc chore(dateparser): unify code style
- Clean up code style for consistency

Closes #4164
2015-08-10 09:06:27 -07:00
Wesley Cho 311c97f868 chore(collapse): unify code style
- Minor code style changes to be more consistent

Closes #4163
2015-08-10 09:05:38 -07:00
Wesley Cho 818f7e53ca fix(timepicker): leave view alone if either input is invalid
- Change to not auto-update inputs if either input is invalid

Closes #4160
Fixes #3825
2015-08-10 09:03:59 -07:00
Wesley Cho 11ecfd5d62 docs(datepicker): fix templateUrl reference 2015-08-10 09:02:05 -07:00
Wesley Cho a75d5e6b34 docs(datepicker): fix markdown 2015-08-10 06:41:47 -07:00
Wesley Cho 64b52896fc feat(pagination): add templateUrl support
- Add support for overriding the `templateUrl` on an instance by instance basis
- Expose controller via `controllerAs`

Closes #4162
2015-08-09 21:45:55 -07:00
Wesley Cho 3c06832d76 docs(contributing): add link to commit conventions
- Add commit convention link to document

Closes #4161
Resolves #3602
2015-08-09 21:44:39 -07:00
Wesley Cho 215abd01c2 chore(buttons): tighten up code style
- Tighten up code style for increased consistency

Closes #4155
2015-08-09 21:40:30 -07:00
Wesley Cho 876b9769e7 chore(alert): tighten up code style
- Tighten up the code style for increased consistency

Closes #4154
2015-08-09 21:39:48 -07:00
Wesley Cho 0ba4184d02 chore(accordion): tighten up code style
- Make the code style uniform for consistency

Closes #4153
2015-08-09 21:38:57 -07:00
Wesley Cho 739b1d19f5 chore(release): Rolling back to 0.13.4 snapshot start 2015-08-09 09:36:08 -07:00
Wesley Cho 3a036de799 chore(release): Starting v0.14.0-SNAPSHOT 2015-08-09 09:30:04 -07:00
Wesley Cho 4a69d00815 chore(release): v0.13.3 2015-08-09 09:30:03 -07:00
Wesley Cho 54f4d735c3 chore(datepicker): clean up bad indentation 2015-08-08 12:55:26 -07:00
Wesley Cho e04b06d765 feat(datepicker): allow custom templates
- Allow custom templates for datepicker and popup
- Expose controller to template

Closes #4157
Resolves #1913
2015-08-08 12:38:42 -07:00
Wesley Cho 68afc4c63e feat(datepicker): add onOpenFocus support
- Add `onOpenFocus` attribute for optional disabling of focus of popup
  after datepicker popup is opened

Closes #2303
Closes #2546
Closes #4146
2015-08-08 12:22:44 -07:00
Wesley Cho 991c91d404 docs(datepicker): change from primitive
- Change to use an object to better align with best practices

Closes #3922
Closes #4148
2015-08-08 09:41:40 -07:00
Wesley Cho 901a7c6656 feat(tooltip): remove unnecessary $digest
- Remove unnecessary call to `$digest`

Closes #4151
2015-08-08 09:39:42 -07:00
Adam Gordon ead15e37f6 fix(accordion): add open class when expanded
- add `open` class to `.panel-collapse` when open.
- fix missing closing `<` on test.

Closes #4152
Fixes #3419
2015-08-08 09:37:26 -07:00
Wesley Cho 22b16f01be fix(tooltip): add safety to $apply
- Change to use `$rootScope.$digest()` only as necessary for safety

Closes #3943
Closes #4150
Fixes #516
2015-08-08 09:18:12 -07:00
RobJacobs 895a228107 fix(tooltip): tooltip w/ template position
When using a template with the tooltip/popover
the position funciton needs to be called at the
end of the $digest cycle to ensure correct
positioning in case the template content size
has changed

Closes: #4144
Fixes: #4090
2015-08-07 13:05:39 -07:00
Wesley Cho b21c9abdf9 feat(pagination): add classes to assist with styling
- Add classes to allow the user to target the styles of component with more specificity

Closes #4130
Closes #4142
2015-08-07 10:39:16 -07:00
Wesley Cho a29c8f2070 feat(carousel): add templateUrl support
- Add support for `templateUrl` attribute for `carousel` and `slide`
  directives for instance by instance overriding of default templates

Closes #4141
2015-08-07 10:24:13 -07:00
Wesley Cho 02872dc1fe feat(buttons): add controllerAs support
- Expose controller to the view for `btnCheckbox` and `btnRadio`
  directives

Closes #4140
2015-08-07 10:23:12 -07:00
Wesley Cho 88a885ca73 feat(alert): add templateUrl support
- Adds support for `templateUrl` to override template on an instance by
  instance basis
- Exposes controller to the view via `controllerAs`

Closes #4139
2015-08-07 10:22:31 -07:00
Wesley Cho 9865ee8e1c feat(accordion): add controllerAs support
- Expose the controller to the view via `controllerAs`

Closes #4138
2015-08-07 10:21:24 -07:00
Wesley Cho a0e1c91cb1 feat(pagination): add templateUrl support
- Add support for overriding the template url on an instance by instance
  basis
- Expose the controller to the view via `controllerAs`

Closes #4137
2015-08-07 10:20:25 -07:00
Wesley Cho 5a28ff76ff feat(modal): add ability to change class on body
- Add support for `openedClass` to allow overriding the default modal class added & removed on the `body` element (`modal-open`)

Closes #2633
Closes #4132
2015-08-07 10:19:10 -07:00
Wesley Cho f081fabe1a chore(datepicker): fix code style 2015-08-07 08:46:03 -07:00
Wesley Cho bfec07e45e feat(carousel): expose carousel controller via controllerAs
- Expose the carousel controller in the component via `controllerAs`

Closes #4131
2015-08-07 06:46:33 -07:00
Wesley Cho 893688565f feat(modal): allow users to resolve with strings
- Allows users to specify a string reference to a service for injection

Closes #2676
Closes #4124
2015-08-07 06:44:48 -07:00
Wesley Cho 3c58a7323c docs(docs): explain the difference between -tpls and not
- Add documentation on the difference between `-tpls` and the regular
  built scripts

Closes #420
Closes #4125
2015-08-07 11:13:03 +02:00
Wesley Cho feee292de0 docs(buttons): add documentation on uncheckable
- Add documentation on the `uncheckable` attribute

Closes #4102
Closes #4123
2015-08-07 10:58:56 +02:00
Slimmmo f3d263e1b9 feat(datepicker): add support for dynamic min-mode and max-mode
- This adds support for dynamic `min-mode` and `max-mode`

Closes #3843
Fixes #2618
2015-08-06 23:02:08 -07:00
Basil Siddiqui abfd26c025 chore(typeahead): add comment on typeahead-min-length
- Add comment on `typeahead-min-length` about valid values

Closes #4129
2015-08-06 22:27:38 -07:00
Blackbaud-PatrickOFriel bab1d3754a feat(datepicker): allow suppression of log error
- Add `$datepickerSuppressError` injectable to allow suppressing of error message

Closes #3836
Closes #4115
2015-08-06 22:25:19 -07:00
Wesley Cho 87fc242d80 feat(timepicker): add documentation for max/min
- Add documentation on new max/min attributes
- Fix code style
2015-08-06 21:49:11 -07:00
Michael Knoll 6c0010be41 feat(timepicker): Added min/max attributes for timepicker.
- Add support for min & max attributes

Closes #4019
2015-08-06 21:36:47 -07:00
tomasz stryjewski a05b9c1ac5 fix(modal): skipping ESC handling for form inputs
BREAKING CHANGE: Allow the user to hit `esc` inside an element in a modal and not exit the modal if the event has been `defaultPrevented`

Closes #3551
Fixes #2544
2015-08-06 08:00:39 -07:00
Kai Johnson 1ecd82ced1 fix(dateparser): Support 12-hour format and AM/PM
- Adds support for the flags `hh` and `a`

Closes #4117
2015-08-06 07:46:23 -07:00
Wesley Cho e633ca80f4 chore(carousel): refactor to remove try-catch 2015-08-06 07:45:56 -07:00
Wesley Cho c7f19d5834 fix(modal): add $animateCss support
- Add support for `$animateCss`

Closes #4121
Fixes #4119
2015-08-05 21:28:10 -07:00
Martin Brennan 265d429b67 feat(docs): add explanation of eye icon
- Add explanation of the eye icon to documentation

Closes #4120
2015-08-05 18:39:51 -07:00
Wesley Cho e60c3ff6e2 fix(modal): fix test 2015-08-04 22:29:53 -07:00
Wesley Cho 8853bd8325 chore(modal): change to $uibUnscheduledDestruction
- Change to `$uibUnscheduledDestruction` as per comment in #4097
2015-08-04 22:27:56 -07:00
Adam Gordon 0b37f088f1 fix(dropdown): handle keyboard-nav correctly
- fix bug in directive whereby list item selector is not being initiated on
  correct DOM element.
- fix bug in directive whereby invalid `keyCode` property of jQuery Event
  object is being referenced instead of `which`.
- update functional test to trigger keydown event on correct DOM element
  because otherwise the keydown handler in the directive is not getting
  executed.
- remove invalid functional test because it is not possible to trigger a
  keydown event on a hidden DOM element through normal UI interaction.

Closes #4110
Fixes #4091
2015-08-04 17:05:34 -07:00
Wesley Cho 12c527afb3 fix(tooltip): prevent opening when tooltipPopupDelay is present
- Cancel the timeout when `tooltipPopupDelay` is present and the element with the tooltip directive becomes disabled

Closes #4098
Fixes #3611
2015-08-04 14:35:33 -07:00
Wesley Cho 8359d73fd3 fix(carousel): fix animation direction
- Properly fix the animation direction of the slides

Closes #4092
Fixes #4087
2015-08-04 14:15:26 -07:00
Wesley Cho 3584061f19 fix(modal): dismiss modal on unschedule destruction
- Dismiss modal via `modalInstance.dismiss` if the `$scope` undergoes an unscheduled destruction

Closes #4097
Fixes #3694
2015-08-04 11:40:03 -07:00
Wesley Cho 5ae5be6625 chore(tooltip): add note on wrapping in a tag
- Add documentation to tooltip and popover about usage of `*-template` and the template needing to be wrapped in a tag

Closes #3555
Closes #4101
2015-08-04 09:59:42 -07:00
Wesley Cho 3b5b3bd24b chore(pagination): preventDefault on click
- Add `event.preventDefault` call in order to avoid potential router bugs

Closes #4096
2015-08-04 09:58:11 -07:00
Wesley Cho 328146db6e chore(accordion): add note about type in docs 2015-08-04 09:57:09 -07:00
Wesley Cho f777c320cc feat(accordion): add templateUrl support
- Add ability to override the template of the `accordion` and `accordion-group` directives on an instance by instance basis

Closes #4084
2015-08-04 09:56:15 -07:00
Wesley Cho b18dc8f9bc fix(accordion): revert to empty href
- Revert to empty href to avoid user triggered routing problems

Fixes #4104
2015-08-04 08:12:42 -07:00
Wesley Cho 394fcc2576 chore(npm): bump up dependency versions 2015-08-03 23:57:12 -07:00
Wesley Cho fbba5d3853 chore(grunt): add convenience for testing 2015-08-03 22:27:52 -07:00
Wesley Cho c9b0d0b05f fix(buttons): change to use attrs.disabled
- Change to use `attrs.disabled`

Fixes #4088
2015-08-03 21:48:14 -07:00
Wesley Cho 707fbf55c0 fix(buttons): allow selection of undisabled button
- When a button has been toggled between disabled and not, fix allowing selection of the button to occur

Fixes #4088
2015-08-03 14:52:01 -07:00
Adam Gordon 758860dbca chore(buttons): add missing unit test for btn-radio
- added missing unit test to test for string literal values on btn-radio directive

Closes #4083
2015-08-02 23:28:11 +02:00
Wesley Cho 74a8be4c5a fix(datepicker): commit safe apply on destruction
- Ensure we are not in a $digest before executing an $apply on scope destruction to avoid potential error

Closes #4079
Fixes #4076
2015-08-02 11:25:26 -07:00
Wesley Cho ca9196fa8f feat(tooltip): add multiple trigger support
- Adds support for multiple triggers

Closes #3987
Closes #4077
2015-08-02 11:21:48 -07:00
Wesley Cho 8dc13be924 fix(progressbar): fix min-width for Bootstrap 3.2
- Fix styling of progressbar for Bootstrap 3.2

Closes #4081
Fixes #2511
2015-08-02 11:20:19 -07:00
Wesley Cho 5245ccad3c fix(datepicker): change to dateDisabled
BREAKING CHANGE: Change validation key to `dateDisabled` to align better with Angular's convention

Closes #2773
Closes #4080
2015-08-02 11:18:13 -07:00
Wesley Cho c7d3a66095 fix(typeahead): return null if empty
- Return `null` instead to unify falsy values

Closes #4078
Fixes #3176
2015-08-02 11:14:16 -07:00
Wesley Cho cf65a6357c chore(docs): fix bootlint warnings
- Fix bootlint warnings

Closes #3597
Closes #4075
2015-08-02 11:10:25 -07:00
Wesley Cho a8a22cff06 feat(docs): add ngAnimate Plunker support
- Adds support to autogenerated Plunkers to use ngAnimate out the gate

Closes #3648
Closes #4072
2015-08-02 11:09:25 -07:00
Wesley Cho 8056368e03 fix(carousel): fix sorting of indicators
- Change the `orderBy` usage to `indexOfSlide` to properly order indicators

Closes #4071
Fixes #3764
2015-08-02 11:05:14 -07:00
Wesley Cho ff37fb68ba chore(release): Starting v0.13.3-SNAPSHOT 2015-08-02 00:42:08 -07:00
Wesley Cho 76b21f5973 Revert "chore(release): Starting v0.14.0-SNAPSHOT"
This reverts commit 95d22cbb6f.
2015-08-02 00:41:38 -07:00
Wesley Cho 95d22cbb6f chore(release): Starting v0.14.0-SNAPSHOT 2015-08-02 00:41:11 -07:00
Wesley Cho 5e372c021b chore(release): v0.13.2 2015-08-02 00:41:09 -07:00
Chad von Nau 13df1c9305 fix(tooltip): update tooltip placement dynamically
Closes #3980
Fixes #3978
2015-08-02 00:34:56 -07:00
Chad von Nau 632aa8204b fix(tooltip): prevent 1px shift in Webkit/Blink
- Only update tooltip position when content changes, instead of every $digest

Fixes #3964
2015-08-02 00:30:30 -07:00
Wesley Cho 1e8297be43 fix(modal): properly garbage collect DOM node
- Garbage collect using `$animate` so that `$animate` releases reference to DOM node

Fixes #2875
2015-08-02 00:19:22 -07:00
Jeff Treuting 647cdd931c feat(typeahead): add noResults indicator binding
- Add ability to configure no results message

Closes #2016
Closes #2792
Closes #4068
2015-08-01 12:06:10 -07:00
Wesley Cho 9f73d240ab fix(datepicker): change to contains
- Change check to contains due to improper check

Closes #4066
Fixes #3076
2015-08-01 09:17:48 -07:00
Wesley Cho 6b90e9edf2 chore(buttons): add demonstration of multiple checkbox
- Add demonstration of how to store model when working with multiple checkboxes

Closes #3087
Closes #4065
2015-08-01 09:17:02 -07:00
Wesley Cho 25704838d2 fix(typeahead): reset matches if enter is hit
- If no match is selected and enter is hit, reset matches

Closes #4063
Fixes #3545
2015-08-01 09:16:09 -07:00
Wesley Cho 7af9cdf804 chore(build): remove ngdocs
- Remove ngdocs since it is not functional

Closes #4064
Closes #3457
2015-08-01 09:10:01 -07:00
Maarten Winkels 97e077e115 fix(typeahead): only reset matches if matches are present
- Resets matches only when matches are present to avoid extra $digest

Closes #3119
2015-08-01 07:41:28 -07:00
Wesley Cho ab4580fd81 fix(datepicker): *BREAKING CHANGE* remove new Date fallback
- Remove `new Date` fallback due to buggy behavior

Closes #2513
Closes #3294
Closes #3344
Closes #3682
Closes #4092
Fixes #1289
Fixes #2446
Fixes #3037
Fixes #3104
Fixes #3196
Fixes #3206
Fixes #3342
Fixes #3617
Fixes #3644
2015-08-01 07:32:12 -07:00
Wesley Cho 20047577b0 chore(tab): change to linking function
- Change to use linking function as the use of `transclude` on the compile has been deprecated by Angular

Closes #4061
2015-08-01 07:30:33 -07:00
Jamie Czerwinski a9d3d253eb feat(popover): add custom template support
- Adds custom template support for popovers

Closes #4056
Closes #4057
2015-08-01 07:24:56 -07:00
Wesley Cho 4f1e03f114 fix(dateparser): add type and validity check
- Add type and validity check to ensure proper date object is created
- Make code style uniform in scripts
- Add warning if the string is not a valid date

Closes #3701
Closes #3759
Closes #3933
Fixes #3609
Fixes #3713
Fixes #3736
Fixes #3875
Fixes #3937
Fixes #3976
2015-07-31 09:10:40 -07:00
lepit31 713c8487cb feat(rating): add title support for stars
- Add support for adding titles to stars

Closes #3621
2015-07-31 08:50:31 -07:00
Wesley Cho a69f66f127 docs(datepicker): add is-open documentation
- Add documentation for `is-open` binding for the datepicker

Closes #4055
Fixes #3939
2015-07-31 07:45:23 -07:00
rvanbaalen 0643fd3e6c fix(accordion): apply disabled style to accordion-header
- Disable the header if `is-disabled` is true

Closes #3599
Fixes #3233
2015-07-31 07:27:00 -07:00
Erik Giron 577b2a2ace fix(datepicker): ensure initDate is on an object
- Check if `options` is an object to avoid error at `initDate` check

Closes #3625
2015-07-31 07:11:55 -07:00
Wesley Cho 811bf96eb1 fix(modal): fix bindToController implementation
- Correct the implementation of `bindToController` to match Angular with properties on `$scope` being bound on the controller

Closes #4054
Fixes #4051
2015-07-31 07:02:34 -07:00
Jason Schindler 277b30ca8b feat(typeahead): add typeaheadSelectOnExact support
- Add support for `typeahead-select-on-exact` for exact matches

Closes #3365
Fixes #3310
2015-07-30 13:22:56 -07:00
Wesley Cho d0bdd2ade6 chore(build): improve travis speed 2015-07-30 11:12:19 -07:00
Maximiliano Korp 27f7ca26d2 feat(build): add support for npm publishing
- Build in support for npm consumption for users
- Improve efficiency of travis tasks

Closes #3108
2015-07-30 11:09:11 -07:00
Iurii Kucherov 797804cacc chore(docs): update library size
Closes #3842
2015-07-30 09:44:58 -07:00
Wesley Cho f45b4a4cdf fix(carousel): fix animations with 1.4
- Change to use `$animateCss` in angular 1.4 and fallback to existing behavior for angular 1.3

Closes #3946
Closes #4041
Fixes #3811
2015-07-30 08:36:05 -07:00
Wesley Cho 42e1af5c60 fix(buttons): respect disabled attribute
- Ensure disabled attribute is respected due to a change in Bootstrap 3.3.5 CSS

Closes #4026
Fixes #4013
2015-07-30 08:33:53 -07:00
Wesley Cho 1b04599b15 chore(build): update dependencies
- Change the angular version to 1.4.3 for docs

Closes #4043
2015-07-30 08:32:31 -07:00
Wesley Cho 32e73280a6 fix(datepicker): change to higher max date
- Change to higher max date so there are valid dates to choose from in the demo

Closes #4042
2015-07-30 14:33:27 +02:00
Wesley Cho c55ee4f527 fix(modal): animate backdrop concurrently with window
- Start animation of backdrop at the same time as the window

Closes #4039
Closes #4036
2015-07-30 14:31:37 +02:00
Wesley Cho 1afc5d1d7c fix(progressbar): use more visible color
- Due to the fixed color of the bar, switch to use white text for readability

Closes #4044
2015-07-30 14:05:05 +02:00
RobJacobs 9f593baf0c refactor(datepicker): move popup document click bind
Moved the datepicker popup document click bind to
a timeout so having preventDefault and stopPropagation
on the element click event triggering the
popup to be open is no longer necessary.

Closes #3972
Fixes #3705
2015-07-28 22:54:06 -07:00
Nive Jayasekar fe0d954a54 fix(datepicker): fix validation with ngRequired
- Fix how validation is handled using `ngRequired`

Closes #4002
Fixes #3862
2015-07-28 22:14:31 -07:00
Steffan Long 2e9177e5f6 fix(progressbar): allow max width of 100%
- When stacking bars, ensure that the max width possible is 100%

Closes #4027
Fixes #4018
2015-07-28 11:48:37 -07:00
Paulo Pacheco a028d2aa16 feat(modal): trap focus in modal for tabbing
- Trap focus inside modal when tabbing while modal is in focus

Closes #3689
Closes #4004
Fixes #738
2015-07-28 07:37:06 -07:00
Pål Sletner 60e431608f fix(dropdown): add safety check for setIsOpen
- Ensure `setIsOpen` is a function, due to it optionally being falsy

Closes #4030
2015-07-28 07:28:54 -07:00
Loïc D 0c78026b6c fix(carousel): clear currentSlide when there are no slides
- Clear `currentSlide` when slides have been emptied

Closes #4021
2015-07-27 21:18:12 -07:00
Sai Chaitanya a65a5fa196 fix(datepicker): set to null if not present
Closes #4014
2015-07-24 10:31:57 -07:00
Jonathan Haines c727da815b docs(typeahead): fix select-on-blur typo
Closes #4008
2015-07-24 00:27:15 -07:00
Jesus Rodriguez feb8a8642c chore(tests): bump to 1.4.3 2015-07-23 20:42:31 +02:00
Wesley Cho 7bf3a2bed0 chore(release): Starting v0.13.2 2015-07-23 07:50:29 -07:00
Wesley Cho 4a29947a5a chore(release): v0.13.1 2015-07-23 07:47:31 -07:00
Wesley Cho fbc655614c Revert "chore(release): 0.13.1"
This reverts commit ece8a36cba.
2015-07-23 07:41:02 -07:00
Wesley Cho 960b5e29d4 Revert "chore(release): update changelog"
This reverts commit a722395bec.
2015-07-23 07:40:43 -07:00
Wesley Cho a722395bec chore(release): update changelog 2015-07-23 07:39:00 -07:00
Wesley Cho ece8a36cba chore(release): 0.13.1 2015-07-23 07:30:32 -07:00
Wesley Cho 5b37bb8b4e fix(typeahead): select match on tab for iOS webview
- Select match on blur if only it has not been selected upon keydown

Closes #3762
Fixes #3699
2015-07-22 14:59:12 -07:00
Wesley Cho 7d1c46009f fix(typeahead): don't close popup on right click
- Ensure typeahead popup does not dismiss on right click in Firefox

Closes #3975
Fixes #3973
2015-07-22 14:26:00 -07:00
Wesley Cho 8ae1a76dc1 chore(bindHtml): add deprecation notice
- Add deprecation notice for bindHtmlUnsafe

Closes #3974
Closes #3574
2015-07-22 14:24:07 -07:00
Wesley Cho cc66a06872 fix(dropdown): do not autoclose with outsideClick and append to body
- Do not auto-close the dropdown menu when it is set to `outsideClick` and dropdown-append-to-body is used

Closes #3792
Fixes #3645
2015-07-22 14:20:38 -07:00
Wesley Cho 6173664ff7 docs(modal): add note about $modalProvider
- Add note about setting global defaults via `$modalProvider.options`

Closes #3797
Resolves #1759
2015-07-22 14:19:12 -07:00
Wesley Cho 091f0f609d chore(pagination): improve performance
- Use bind once for non-watched text blocks
- Add bind once to boundaryLinks and directionLinks

Closes #3807
2015-07-22 14:17:17 -07:00
Wesley Cho 8adfc833f7 feat(modal): add support for bindToController
- Add `bindToController` support in modal options

Closes #3965
Resolves #3404
2015-07-22 14:14:15 -07:00
Wesley Cho a861a2c6b0 chore(timepicker): add bind once to template
- Add bind once to appropriate values not being watched in template

Closes #3809
2015-07-22 14:12:12 -07:00
Adam Tentis 5567c43251 fix(datepicker): change to min width cells
- Change to use `min-width` due to issue in Firefox

Closes #4000
Fixes #3941
2015-07-22 13:16:39 -07:00
Jesus Rodriguez aef8957307 chore(readme): Add NPM installation instructions
Closes #3991
2015-07-22 06:25:46 -07:00
Wesley Cho 41ebd9846a fix(dropdown): avoid matching 138 & 140 2015-07-22 05:39:08 -07:00
Brian 4af83ade14 feat(dropdown): add dropdown classes dynamically
- Add `dropdown` and `dropdown-toggle` classes dynamically for template simplification

Closes #3984
Closes #3986
2015-07-21 12:40:00 -07:00
Schmulik Raskin 2332f14d66 fix(dropdown): align when using dropdown-menu-body
- Fixes the right alignment when using the `dropdown-menu-body` class in
  conjunction with the dropdown component

Closes #3913
Fixes #3820
2015-07-20 05:01:51 -07:00
Paulo Pacheco 14689e058c feat(dropdown): add accessibility attributes
- Add accessibility attributes in documentation examples

Closes #3951
2015-07-19 11:37:44 -07:00
Wesley Cho 9c2a8db9f2 chore(timepicker): add bind-once 2015-07-19 10:52:48 -07:00
Daniel Zimmermann 493510d059 fix(typeahead): close dropdown on tab with no selection
- When no item is selected and tab is hit, close the dropdown

Closes #3340
2015-07-19 10:49:48 -07:00
Andrey Yakovlev f14120149b fix(datepicker): fix OS dependent time zone issue
- Fixes an issue with dates involving different OSes and timezones

Fixes #3079
2015-07-19 10:07:58 -07:00
Manuel Siggen 68cac59ac0 feat(typeahead): add 'select on blur' option.
- Add `select-on-blur` option

Closes #3445
2015-07-19 10:01:14 -07:00
Sneha Jain 054341b715 fix(dropdown): call toggle after animation
- Change to call toggle after animation completes

Closes #3513
Closes #3655
Fixes #3511
2015-07-19 09:50:36 -07:00
RobJacobs b72efed56f refactor(datepicker): implement ng-if on datepicker-popup
Implementing ng-if on the datepicker-popup directive
for performance.

Closes #1915
Closes #3666
2015-07-19 09:35:24 -07:00
Markku Roponen dbceec76d0 fix(rating): Set rating to 0 when same value is selected
- When same rating value is selected, change rating value to 0

Closes #3963
Fixes #3246
2015-07-19 09:30:57 -07:00
david.rus 86bfec1919 feat(typeahead): popup position
- Position the dropdown appropriately when appended to the body and window is resized or scrolled

Closes #3874
2015-07-19 09:25:25 -07:00
DarkAvanger f6edfa5ddf feat(pagination): add support for ng-disabled
- Add support for ng-disabled

Closes #3956
2015-07-19 09:19:36 -07:00
Wesley Cho 2b27dcbf99 fix(tabs): fix empty href
- Add agreed upon fix for empty href due to CSP and the new Angular router

Fixes #3799
2015-07-19 02:08:11 -07:00
Ricardo Faria 92551342cc feat(collapse): add accessibility support
- Add addition of appropriate `aria-` attributes for representation of states for the collapse component

Closes #3920
2015-07-17 12:14:55 -07:00
mseancole ede9ea4606 fix(collapse): fix occasional flickering
- Fixes occasional flickering that can happen

Closes #3804
Fixes #3801
2015-07-17 08:36:10 -07:00
Roy Musa fb302c6086 fix(accordion): add CSP compliance for accordion & typeahead
Closes #3909
Fixes #3904
2015-07-07 15:16:28 -07:00
Chris Chua 158d267659 fix(modal): backdrop animation on AngularJS 1.4
Fixes #3896
2015-07-06 00:21:56 -07:00
Wesley Cho 13a0354f66 fix(alert): adjust check for close attribute
- Adjust check due to change in Angular 1.4 where the presence of attribute gives key value of `undefined`, causing variable to contain incorrect truthiness

Closes #3864
Closes #3890
Fixes #3848
2015-07-04 21:17:18 -07:00
Chris Chua 0286828be3 fix(modal): closing breaks on missing scope, 1.4
- supports Angular 1.4

Fixes #3787
Fixes #3806
Fixes #3873
Closes #3888
2015-07-04 16:45:23 -07:00
jvanbouchaute dd4f3cc872 fix(modal): remove illegal character
- Remove bad character masquerading as a space

Closes #3893
Fixes #3892
2015-07-03 23:22:28 -07:00
lgaudez 3316d3e1ca chore(docs): add blurb about ngAnimate
Closes #3887
2015-07-02 09:01:54 -07:00
Mihir Patel 7fb3840f2f feat(carousel): add noWrap option to prevent re-cycling of slides
- Adds `noWrap` option on carousel element for breaking the wrapping of the carousel

Closes #3462
Resolves #3397
2015-06-29 20:26:35 -07:00
sonofbjorn eb3b32ecd6 fix(datepicker): Apply custom class to month
Closes #3863
2015-06-26 11:26:52 -07:00
Avi Cherry 44e0642562 feat(alert): pass $event to close()
Add ability to hook into `$event` in close callback

Closes #3828
Fixes #3827
2015-06-26 09:13:18 -07:00
Geno Roupsky 36e0f0ea36 fix(progressbar): use max value on stacked progress bar
Closes #3830
Fixes #3618
2015-06-26 09:11:27 -07:00
bleggett 62359370e9 feat(dropdown): add keynav support to dropdown
Add `keyboard-nav` option for dropdowns for navigating the dropdown menu with the keyboard

Closes #3685
Closes #3212
Fixes #1228
2015-06-26 09:06:50 -07:00
Wesley Cho 49e73a89f3 chore(typeahead): change to one-way binding for position
- Change position to one-way binding to reduce an unnecessary $watch

chore(typeahead): add bind once to id attr
2015-06-11 23:10:36 -07:00
Wesley Cho ca07ad7c72 fix(carousel): change to avoid references to debug info
- Change usage of `.scope()` and `.isolateScope()` to grab metadata from elements

Closes #3795
Fixes #3794
2015-06-11 23:08:47 -07:00
Joe Ibershoff a5a25141fc feat(typeahead): handles min-length of 0
Closes #3600
2015-06-11 13:35:59 -07:00
Thomas Haukland 988336ccff fix(modal): focus on body if element disappears
- Change to focus on `document.body` instead if element is not present

Closes #3653
Fixes #3639
2015-06-11 10:07:33 -07:00
Wesley Cho 0d96221fa3 fix(typeahead): do not execute unnecessary $digest
- If in a $digest, do not execute `scope.$digest`

Fixes #2652
Closes #3791
2015-06-11 08:24:02 -07:00
Wesley Cho 115d490a25 fix(carousel): ensure there are slides present
- Ensure there are slides present before calling `$scope.next` in timer

Fixes #3755
2015-06-11 08:22:40 -07:00
Robin van Baalen f02a24d232 chore(readme): make main title fit on one line 2015-06-07 22:33:31 -04:00
Wesley Cho ef45ecf894 fix(carousel): disable transition until animation completes
- Force the carousel indicator to not select the slide if the animation has not completed
- Factor out `goNext` function to not redefine on each execution of `select`

chore(carousel): move `$currentTransition` check to `select` method

Fixes #3729
Closes #3757
2015-06-07 11:21:52 -07:00
Andrei Alecu 83c4266cd8 feat(dropdown): support optional templates for dropdown menus
Optionally support specifying a custom template for a dropdown menu.

Allows generating multiple dropdown menus with custom templates.
2015-06-04 14:39:14 -07:00
Armin Cifuentes 1f760eb35f feat(timepicker): add showSpinner flag
- Add optional `showSpinner` flag support
2015-06-04 13:16:53 -07:00
Rob Jacobs d631af5a05 fix(alert): rename alert-dismissable to alert-dismissible
The use of alert-dismissable is now deprecated in correspondence with https://github.com/twbs/bootstrap/pull/13845
2015-06-04 13:54:17 -04:00
Robin van Baalen 8297244aba docs(modal): fix markup 2015-06-04 13:49:52 -04:00
Robin van Baalen 10c67e7b5d chore(license): update copyright year range 2015-06-04 13:41:05 -04:00
marwy c946509bda docs(alert): document dismiss-on-timeout attribute 2015-06-04 11:15:59 -04:00
Scotty Waggoner 195e520ec4 fix(typeahead): add href to show cursor as pointer
When hovering over typeahead matches, the cursor is now shown as a pointer.

Fixes #3649
2015-06-04 11:08:51 -04:00
CloudNiner e5a1e88fd7 fix(dropdown): do not close on $locationChangeSuccess
Behaviour only triggers when `auto-close=disabled`

Closes #3683, #3704
2015-06-03 13:52:35 -04:00
Robin van Baalen 9247f15b30 docs(tooltip): add notice about deprecated feature
Added a note that `tooltip-html-unsafe` is deprecated in favour of `tooltip-html`

Closes #3634
2015-06-03 12:11:59 -04:00
Robin van Baalen a469fc36f2 docs(typeahead): remove hardcoded http protocol
This prevents protocol mismatch errors

Closes #3723
2015-05-28 13:05:46 -04:00
Robin van Baalen 13b2f9b17a docs(carousel): inject protocol independent images
This prevents protocol mismatch errors

Closes #3723
2015-05-28 13:04:06 -04:00
Robin van Baalen ed10899d6b fix(datepicker): check if getter.assign is function
Closes #3155, #3345, #3719
2015-05-28 12:54:47 -04:00
Rob Jacobs 4683996246 chore(build): updating angular dependency
Setting the angular dependency to be 1.3.x or less
2015-05-28 10:59:33 -04:00
RobJacobs 2a2e5de7d8 refactor(datepicker): implement one time bindings
Reducing the number of watches created for the
datepicker by implementing one time binding
on the datepicker templates. Removing aria-disabled
attribute as the ngAria module will add that
to the button with ng-disabled.

Closes #3443
2015-05-13 13:39:10 -04:00
RobJacobs 21b2002461 test(datepicker): initialize $sniffer variable
The uninitialized $sniffer variable causes the
changeInputValueTo function to fail in Chrome.
Also fixed issue where an ng-change test was failing
as the date selected was the same as the initialized
scope date (today's date).

Closes #3630
2015-05-13 12:13:09 -04:00
RobJacobs ce3ef4c74d Revert "test(datepicker): initialize $sniffer variable"
This reverts commit 8824532f26.
2015-05-13 10:54:31 -04:00
RobJacobs 8824532f26 test(datepicker): initialize $sniffer variable
The uninitialized $sniffer variable causes the
changeInputValueTo function to fail.

Closes #3630
2015-05-13 08:25:30 -04:00
Chris Chua e9b9eb00b0 chore(release): Starting v0.13.1-SNAPSHOT 2015-05-02 11:43:56 -07:00
Chris Chua 4c6e0b3b2e chore(release): v0.13.0 2015-05-02 10:31:20 -07:00
Chris Chua fcbc07c689 chore(demo): update AngularJS version requirement 2015-05-02 09:59:26 -07:00
Chris Chua 88a41dce86 feat(popover): respect popover-class option
This functionality now works the same between tooltips and popovers.

Closes #3569
2015-04-30 09:19:45 -04:00
Chris Chua 6af627a8ed fix(tooltip): template type should respect popup class
- Test each option for each tooltip type
- Tooltip popup now uses tooltip-classes directive

Closes #3569
2015-04-30 09:08:35 -04:00
Chris Chua 34044a7707 fix(tooltip): tooltip-html should not open if empty
Closes #3563
2015-04-29 15:26:21 -04:00
Chris Chua 422c823460 feat(popover): use expression to fix usage with $sce
Allows for trusted resource URLs through Strict Contextual Escaping ($sce).
If an interpolated expression is used instead, then the benefits of SCE is
lost.

Fixes #3558
2015-04-29 15:26:10 -04:00
Chris Chua d867f8302d feat(tooltip): use expression to fix usage with $sce
Allows for trusted resource URLs through Strict Contextual Escaping ($sce).
If an interpolated expression is used instead, then the benefits of SCE is
lost.

Fixes #3558
2015-04-29 15:24:41 -04:00
Chris Chua aef8953c79 feat(datepicker): support HTML5 month input type
Closes #3499
2015-04-29 14:38:04 -04:00
Chris Chua 1a9e88fe9e feat(datepicker): support HTML5 date input type
Closes #3499
2015-04-29 14:37:00 -04:00
Rouven Weßling e909b922a2 refactor(modal,typeahead) Use $templateRequest 2015-04-29 13:31:43 -04:00
Olivier Gonzalez f02c1bbbf7 fix(changelog): add comment on breaking change
- Adds comment on breaking change for opening on focus

Closes #2675
2015-04-26 23:04:52 -07:00
ayu48 f0cadb1f1a fix(grunt): fix typo in gruntfile
Closes #3589
2015-04-26 22:50:34 -07:00
Chris Chua 0de8c866ad style(datepicker): improve readability of week loop
- Remove extra beforeEach in test
2015-04-26 16:15:18 +08:00
Andreas Kemkes 39e5fd3e49 fix(datepicker): week count issues
- add missing semicolon
- no need for exact days match in test
- describe in spec file

Fixes #2506
Fixes #3120
Closes #2306
2015-04-26 16:15:11 +08:00
Chris Chua 82cb637dd1 feat(dateparser): add support for milliseconds
Closes #3537
2015-04-14 13:06:53 -07:00
Wesley Cho ec0f3db314 revert(dateparser): "add support for milliseconds"
This reverts commit 9f5d389c30.
2015-04-14 13:06:22 -07:00
Wesley Cho 3264cd0904 Revert "Revert "feat(dateparser): add support for milliseconds""
This reverts commit c1ff923e43c8d8638cbf361b4378e7c3cd007ad1.
2015-04-14 12:33:54 -07:00
Wesley Cho 8bbc463b78 Revert "feat(dateparser): add support for milliseconds"
This reverts commit 8facf60071728662881a6e1779b2df3bf305ebb5.
2015-04-14 12:33:54 -07:00
Chris Chua 9f5d389c30 feat(dateparser): add support for milliseconds
Closes #3537
2015-04-14 12:33:36 -07:00
Wesley Cho 6324486d70 feat(timepicker): always pad minutes
- Always pad minutes as a UX improvement

- Make suggested fix as per CR

Fixes #1598
Relates to #2639
Closes #3533
2015-04-13 23:05:17 -07:00
Leyan Lo 31a68021f5 test(dropdown): use openClass constant
Changing the value of dropdownConfig.openClass should not break the unit tests

Closes #3529
2015-04-12 22:49:37 -07:00
Dan Caddigan 09cf058498 docs(bower): update bower installation instructions
Closes #3521
Fixes #2622
2015-04-11 16:11:30 -07:00
Robin van Baalen da4208acbb chore(docs): fix quicklinks in README
Fixes #3525
2015-04-10 11:15:12 -04:00
Chris Chua 4b7c21be6d refactor(tooltip): make tooltip-class more robust
- Add tooltip-class support to tooltip-template
- Remove observer for tooltip-class, it’s evaluated once on tooltip
  preparation instead
- Remove interpolation on class attribute
  Interpolation on the class attribute can have undesirable mangling
  effects when use with a directive that has `replace: true`. It also
  doesn’t work properly with ngAnimate.

Relates to #3126
Closes #3510
2015-04-10 07:50:09 -07:00
Chris Chua c8156c7e21 fix(popover): prevent wrong positioning from title
If the title is blank, ngAnimate attempts to animate ngShow so positionTooltip
gets called when the title box is still visible, about to be animated to
hidden. Hence, the positionTooltip receives a taller height. Avoid this by
using ngIf instead.

Closes #3518
2015-04-10 07:46:03 -07:00
fluentthinker 22a21448cb fix(modal): fix minor grammar error
Closes #3519
2015-04-10 07:27:19 -07:00
Chris Chua c2ace47225 fix(popover): animations with ngAnimate
- Animations didn't work because the class attribute was mangled during
  compilation due to the way class attributes are merged on directives with
  `replace: true`

- Rename attribute to popup-class

- Refactor to rename variables named "class" as it's a keyword
  and also looks weird in editors

Closes #3509
Fixes #3375
Fixes #3506
2015-04-08 04:11:42 -07:00
Chris Chua e31fcf0fcb feat(tooltip): add tooltip-html directive
This directive replaces tooltip-html-unsafe use cases. It requires
safe HTML content from $sce.

Closes #3496
2015-04-07 06:54:58 -07:00
Chris Chua 9ca9d7f526 fix(tooltip): use correct prefix for -template
Closes #3498
Fixes #3473
2015-04-07 06:51:36 -07:00
Leonard Seymore 4bfae2238d fix(tab): change to disable attribute
- Switch support to `disable` attribute
- Deprecate support for `disabled`

Closes #2677
2015-04-07 06:42:31 -07:00
Chris Chua 461087b5ff fix(popover): make it work with ngAnimate
Closes #3482
Fixes #3375
2015-04-06 08:21:19 -07:00
Chris Chua 8a55244374 feat(transition): deprecate transition module
Closes #3497
2015-04-06 06:14:46 -07:00
ankit d0cc72841b fix(datepicker): make 'show-weeks' work on datepickerPopup
Fixes #3143
Closes #3149
2015-04-05 21:39:03 -07:00
Chris Chua d024dd77ed fix(datepicker): datepicker-popup compatibility with ngModelOptions
- Separate validation from parsing so that validation still runs on model
  change
- Remove direct calls to $render
- Remove extra call to $render during intialization (only run when format is
  changed)
- Save last date value in formatter
- Remove use of ngModel.$modelValue as users may add parsers to convert
  $modelValue to other formats

Relates to #2069

Fixes #3349
2015-04-05 21:10:24 -07:00
Wesley Cho 971a1b5739 feat(dateParser): Add support for HH, H, mm, m, ss, s formats
- Add support for `HH`, `H`, `mm`, `m`, `ss`, `s` formats from Angular's
  `dateFilter`
- Add support for `:` character in format expression

- Fix typos

- Add regexp escaping of special characters

Fixes #2509
Fixes #3159
Closes #3417
2015-04-05 17:32:27 -07:00
Wesley Cho b4bbc01982 fix(timepicker): move render logic to formatter
- Moves render logic converting model values into date or null object into a formatter, which allows the render function to more correctly render using the viewValue

- remove parentheses as per CR

Relates to #2069

Fixes #3160
Closes #3427
2015-04-05 16:29:16 -07:00
Ben Hanna 33269bb6b4 fix(pagination): remove focus from prior clicked elements
Closes #3488
Fixes #3486
2015-04-05 09:40:24 -07:00
Jerome Botineau e6b105ae39 fix(modal): Fix focus when the dialog is close or cancelled
- Return focus to element with focus before modal opened

Closes #2888
2015-04-05 08:10:51 -07:00
Paul Schuegraf 26b40903ab fix(pagination): fixes issue when init called after watch triggered
Ensure `$watch expressions are bound after init is called

Closes #2257
Fixes #2227
2015-04-05 08:04:01 -07:00
Jesus Rodriguez 7de7a8ea28 chore(tests): update to jasmine 2.x
Closes #3469
Implements #3458
2015-04-02 09:57:34 -07:00
Ryan Silva dfe9854be3 feat(dropdown): Dropdown append-to-body
Closes #3411
Fixes #1030
2015-04-02 07:17:22 -07:00
Chris Chua a643f96d67 demo(popover): fix typo in template url 2015-04-01 23:24:51 -07:00
rvanbaalen 6355d8adc7 chore(docs): update README.md
Restructured README, added references to new Wiki pages and updated
content

Closes #3453
2015-03-31 16:32:31 -04:00
Chris Chua 5536e9660e chore(tests): use angular installed via npm
- Avoid maintaining / copying AngularJS source code on our repo.
- Ensures that Travis checks out the latest Angular version and tests
  against it.
2015-03-31 09:44:18 -07:00
Jesus Rodriguez a1e50d37a5 chore(travis): use latest node
Closes #3470
2015-03-31 09:42:20 -07:00
onjiro 0ad208d6a0 feat(modal): pass reason when opened promise rejected
Closes #2978
2015-03-30 22:45:42 -07:00
hsubu 489961e1a0 fix(progressbar): limit max width to 100%
Closes #3005
2015-03-30 22:42:34 -07:00
Wesley Cho ac6a0f4e6d Merge pull request #3065 from sashless/fix/xhtml-compatibility
make it useable in xhtml documents
2015-03-30 22:36:09 -07:00
Mario Casciaro a50f11201e feat(dropdown): Make Auto-Close Dropdowns optional.
Fixes #2218
Closes #3045
2015-03-30 22:04:06 -07:00
Chris Chua dcdce69fc6 docs(modal): remove typo
Typo was made in 5e661d4
2015-03-30 01:01:03 -07:00
Chris Chua 5e661d47d6 feat(modal): add option to disable animations
Note: Move backdropClass logic into compile function because otherwise
modifying classes in the compile function is broken when using an interpolated
class attribute.

Fixes #1007
Closes #2725
2015-03-30 00:59:00 -07:00
Max Fierke 4a06adbac6 fix(dropdown): Fix $digest:inprog on dropdown dismissal
Make $apply first check if $rootScope is in $digest cycle before executing

Closes #3274
2015-03-29 17:54:38 -07:00
imagentleman 31c2694007 chore(rating): remove redundant validation and add unit tests
Closes #3464
2015-03-29 13:20:56 -07:00
Wesley Cho 2c1a4cc09c Merge pull request #3456 from chrisirhc/feature/update-dependencies
chore(build): upgrade devDependencies
2015-03-28 19:46:02 -07:00
Chris Chua a1695114a2 feat(tooltip): add tooltip-template directive
Fixes #220
2015-03-28 13:41:02 -07:00
Chris Chua 7e3179ab9f feat(popover): add popover-template directive 2015-03-28 13:40:05 -07:00
Chris Chua bf4b5ec985 refactor(carousel): make use of one function
Resolve this TODO since we're requiring 1.3 where the fix for `.one` has been
merged.
2015-03-28 13:09:54 -07:00
Chris Chua f908c2b1aa refactor(carousel): remove unused dependency 2015-03-28 12:57:25 -07:00
Chris Chua dcc340f7f4 refactor(collapse): remove unused dependency 2015-03-28 12:52:51 -07:00
Chris Chua dcb44b10c9 chore(build): add missing karma-coverage dependency
Useful for retrieving test coverage statistics.
2015-03-28 12:21:09 -07:00
Chris Chua fa8e52c406 chore(build): upgrade to Karma 0.12
Upgrade configuration file. However, still use an old version of karma-jasmine
because upgrading to Jasmine 2.x requires a number of test code changes.

Note that firefox-launcher is used for travis CI builds.
2015-03-28 12:21:09 -07:00
Chris Chua 8821d12eb2 chore(build): upgrade devDependencies
Upgrade dependencies that are safe to upgrade with no changes needed
in any configuration.
2015-03-28 12:21:09 -07:00
Raanan Weber 7ccff028ff feat(progressbar): allow dynamic update to max
- Adds ability to dynamically change max value
2015-03-28 05:10:46 -07:00
Robin van Baalen f13ed0fb84 chore(docs): remove deprecated roadmap file 2015-03-27 12:53:02 -04:00
Chris Chua 853fa4578a feat(tooltip): update position dynamically
Reposition on each digest, this ensures that the tooltip is always positioned
correctly no matter how its content changes.

Fixes #96
Fixes #1109
Closes #2816
Closes #3435
2015-03-26 21:24:35 -07:00
RobJacobs a726b7cd47 fix(timepicker): remove ng-mousewheel binding
The timepicker template has an ng-mousewheel
binding on the hours input element and the
TimepickerController also binds the elemeent
to mouse wheel events.  Removed ng-mousewheel
binding from the template.

Closes #3442
2015-03-25 13:50:28 -04:00
Wesley Cho 7c1c75b46c docs(modal): update documentation on size 2015-03-25 07:13:30 -07:00
Wesley Cho df5bda6574 revert(timepicker): implement ng-disabled support timepicker
This reverts commit 8cf810baee.
2015-03-25 06:46:39 -07:00
gediminasgu 8cf810baee feat(timepicker): implement ng-disabled support timepicker
Add support for ng-disabled for timepicker
2015-03-25 06:42:54 -07:00
Wesley Cho 5cb2f78f78 revert(timepicker): ng-disabled attribute implemented for timepicker"
This reverts commit f7b44286aa.

Conflicts:
	template/timepicker/timepicker.html
2015-03-25 06:39:53 -07:00
Chris Chua 58e74af071 test(modal): add test for custom modal sizes
Related to #3429
2015-03-25 00:41:06 -07:00
RevanProdigalKnight 85eeb95428 fix(modal): allow for custom user modal sizes
Remove restriction to Bootstrap-native `modal-sm` and `modal-lg` size classes.

Fixes #3429
Closes #3431
2015-03-25 00:39:03 -07:00
cookfront 9468d7239d fix(buttons): add unit tests for buttons
Adds unit tests to buttons, helping bring test coverage to 100%

Closes #3030
2015-03-24 23:19:14 -07:00
Kevin Locke 35b8512ac7 fix(datepicker): disable title button when in max mode
When the calendar is in the maximum configured mode, clicking the title
button has no effect.  To convey this to users, make the non-functional
button non-clickable, and take the button out of focus order, disable
the button when in the maximum mode.

Closes #3012
2015-03-24 23:11:27 -07:00
Mike Fisher 8e89440ba8 fix(timepicker): fix widths of inputs when inside form-inline
Set timpicker widths on input elements to fix display in inline forms
2015-03-24 23:07:27 -07:00
Wesley Cho 13bd516cfc fix(datepicker): add shortcutPropagation to datepickerPopup 2015-03-24 08:02:54 -07:00
Olivier Leduc 89ab4580cd fix(datepicker): fixed shortcut event kill by adding option
Added optional `shortcut-propagation` attribute for optionally allowing the keydown event to propagate upwards
2015-03-24 08:00:20 -07:00
Kenneth Baltrinic 98e2bdfc8b fix(datepicker): fix initDate implementation in datepicker
Fixes use of initDate across datepickerConfig, datepickerOptions, and
the initDate attribute
2015-03-24 07:10:26 -07:00
Sylwester Grabowski c19b8879e9 fix(dateparser): add extra validation constraint to days
day equal to 0 is not allowed
2015-03-24 06:07:44 -07:00
Jonas b5e534b893 docs(CHANGELOG): Added dropdown breaking change
After I upgraded from 0.10.0 to 0.11.0 I needed to add the dropdown directive to my button dropdowns. This is not documented in the breakting changes.

The bootstrap documentation only mentions the dropdown class only in the [dropdowns section](http://getbootstrap.com/components/#dropdowns), but not in the [btn-dropdowns section](http://getbootstrap.com/components/#btn-dropdowns).
2015-03-24 06:02:50 -07:00
hitautodestruct df0bc00522 docs(pagination): add information about ng-change
Add details that ng-change can be used alongside ng-model
2015-03-24 05:32:30 -07:00
hitautodestruct 570f2e1f2a Added missing ng-change
This documentation was missing ng-change event.
2015-03-24 05:32:18 -07:00
Chris Chua bed788eb58 revert(modal): remove an unnecessary $digest
This reverts commit 7940fd05f0.

Breaks a test.
2015-03-23 23:45:09 -07:00
strille 7940fd05f0 feat(modal): remove an unnecessary $digest
Optimized opening of modals by causing one digest loop less: The modalBackdrop directive now schedules switching its animate flag using a $timeout which does not cause a digest loop. If we assume modalBackdrop is always followed by a modalWindow directive, then we are guaranteed a digest loop by modalWindow's $timeout, which will happen after modalBackdrop's $timeout.
2015-03-23 23:19:05 -07:00
Brian Lewis b076483caa feat(rating): add rounding logic to rating value
- Moved rounding logic into a formatter
- Checking for number instead of checking if undefined
- Using angular.isNumber for rounding logic
- Using bitwise instead of modulo to check for decimel

Fixes #3413
Closes #3415
2015-03-23 23:05:09 -07:00
Daniel Zimmermann c0a9c70790 fix(typeahead): reset 'parse' validation key
When typeahead-editable="false" and we select a perfect
match from the results list, the $parsers aren't called,
which results in the 'parse' error key not being reset.

As with the 'editable' key, we should reset this once
an item is selected because we know we have a valid
model matching the view value.

Closes #3166
2015-03-23 16:40:49 -07:00
Alexandre David 405dab65f7 fix(timepicker): Stringify pad return when value >= 10
In some cases, the increment function becomes invalid because the
minutes are invalid. This change ensures that the value returned is a
string
2015-03-23 14:36:24 -07:00
gediminasgu f7b44286aa feat(timepicker): ng-disabled attribute implemented for timepicker
Add support for ng-disabled for timepicker
2015-03-23 14:15:21 -07:00
Ara Hacobian 950c22cdab fix(typeahead): resolve property length of undefined error
- resolves property length of undefined error by checking value first #2999

Fixes #2999
Closes #3178
2015-03-23 11:15:19 -07:00
Chris Chua 36e6363765 refactor(collapse): use ngAnimate
- Animations are now opt-in, include ngAnimate to see collapse
  animations

- ngAnimate handles initial state and doesn't animate if first
  reflow hasn't occurred.
  angular/angular.js@cc58460

- Tests may need more work. Right now they test for 'in' class.

Fixes #1774
Fixes #2821
Fixes #2836
Closes #1274
Closes #1444
2015-03-23 10:47:52 -07:00
Winckell Thomas c5b63ded0a fix(datepicker): Fix init-date not applying on datepicker-popup
Fix of the init-date attribute for the datepicker-popup. The init-date attribute, when set in a datepicker-popup element, is now added to the datepicker element and in the datepicker-popup scope, so the datepicker element can retrieve the attribute value.
2015-03-23 08:30:45 -07:00
Josh Friend 22961157ad feat(timepicker): have up/down arrow keys control time selection
Add ability to use arrow keys to control time selection
2015-03-23 08:04:52 -07:00
Chris Chua 0d8820b9aa refactor(modal): use ngAnimate for animation
- Fix scope.$apply call not working previously because scope was already
  destroyed. Use $rootScope instead.
- Move $destroy call nearer to the dom removal.
- Remove fallback timer (emulateTime param)

Fixes #2585
Fixes #2674
Fixes #2536
Fixes #2790
Fixes #3182
Closes #2724
2015-03-22 19:03:08 -07:00
Uri Goldshtein 0bcd30c4a6 feat(datepicker): Add custom class to specific days via outside logic 2015-03-22 18:42:39 -07:00
André Gaul b004443371 fix(typeahead): set validity if model is set manually
With this commit, the validity of a typeahead model is set to true if
the model is set manually and the typehead directive is set to be
non-editable.

add test for setting model manually

Fixes #3318
2015-03-22 18:14:56 -07:00
Christoph Herbst 03446c5633 fix(typeahead): $compile match template after adding to DOM 2015-03-22 18:00:48 -07:00
Diego Domingues e5f5f75b37 fix(modal): Autofocus corrects the second time that the modal is open
element with autofocus attribute when the modal is reopened

Fixes #2802
2015-03-22 17:40:59 -07:00
hamfastgamgee 2c2dba6d14 fix(datepicker): Make datepicker respect dateFormat inside ng-if
Makes the datepicker respect dateFormat inside ng-if.
2015-03-22 17:22:44 -07:00
Andrey Yakovlev b5f220fa84 fix(carousel): respect the order of the slides
index parameter is added to the slide directive. It is used to order the
slides.

Fixes #488
2015-03-22 14:55:56 -07:00
Khashayar Hajian d253208bd7 fix(datepicker): ng-model value can be a timestamp
Accept a number of milliseconds since 01.01.1970 as a valid value
for `ng-model`:
- change parseDate() to handle timestamp values
- add the test to `datepicker.spec.js`

Closes #2345
2015-03-22 14:36:04 -07:00
Stepan Riha d784354a53 feat(tooltip): Support for tooltip-class configuration
Closes #3126.
2015-03-22 14:20:53 -07:00
Dennis Stevense 0ecf7faad3 fix(datepicker): Parse date from $viewValue instead of $modelValue
Allow use in conjunction with an ngModelController that has custom formatters and parsers to translate between $modelValue and $viewValue
2015-03-22 14:14:37 -07:00
Chris Chua f9a9b979c5 refactor(accordion): use ngAnimate for animations
- Deprecate collapse module
  Consider removing it after transition module is deprecated as well.

Fixes #2871
Fixes #3141
Closes #1675
2015-03-21 15:21:47 -07:00
Matt Evanoff 20a01cefcc docs(accordion): add is-open
Closes #3230
2015-03-21 14:35:14 -07:00
Chris Chua 431b9c76b0 refactor(carousel): use ngAnimate for animation
Fixes #1350
Fixes #1513
Fixes #1185
Fixes #2062
Fixes #2235
Closes #2067
2015-03-19 00:35:42 -07:00
Chris Chua d03543ea61 chore(build): add handling for css files 2015-03-19 00:35:42 -07:00
Chris Chua 8e4860f8f0 chore(demo): update demo to include animations 2015-03-19 00:35:42 -07:00
Bruno Lellis 9a26b36803 demo(tooltip): add tooltip-enable description, example
- Simple description about tooltip-enable.

- Add section demonstrating tooltip-enable

Closes #3372
2015-03-17 23:49:48 -07:00
fassetar f74b9583e6 chore(demo): add favicon.ico
Closes #3398
2015-03-17 23:36:06 -07:00
Chris Chua 907c55ff3e docs(CHANGELOG): fix commit links
Commit URLs were manged because I used a newer version of
grunt-conventional-changelog without a proper repository URL.

Closes #3332
2015-03-17 02:22:03 -07:00
Chris Chua 8c584cd057 chore(build): upgrade to grunt-contentional-changelog 1.1
See #3332
2015-03-17 02:21:54 -07:00
Chris Chua 30a34196d7 demo(all): remove unused variable 2015-03-16 23:39:20 -07:00
Chris Chua 8dc3cffa6c demo(all): make it work with AngularJS 1.3
AngularJS 1.3 seems stricter with controller registration. Previously,
the controller were registered with undefined values but AngularJS 1.2
found them as they were window globals.

Looks like aa0b639 was incomplete. This should fix the rest of the demo app.

Fixes #3394
2015-03-16 23:38:15 -07:00
Karol Fabjańczuk 91b5fb62ee feat(tabs): it should not select first not active tab as selected 2015-03-15 21:22:36 -07:00
Nathan Williams a5a82d9be7 feat(Modal): Add a vetoable modal.closing event
Add tests

Includes tests, refinements to the documentation and a fix for an
inconsistent variable name.

Fix test bug
2015-03-15 21:08:38 -07:00
onjiro ab919f9f89 fix(modal): fix messages on modal test failed
- Change to use resolved & rejected values instead of promises in message
2015-03-15 17:48:35 -07:00
Owais Zahid 99af5f8a36 fix(Modal): Use attribute observe and add a render promise. 2015-03-15 17:29:35 -07:00
Peter af Geijerstam b5a80c08f2 fix(Typeahead): Fix for memory-leak in typeahead
Remove template element in order to prevent memory leak when directive is instantiated/destroyed

Move element removal to $destroy block to be safe
2015-03-15 17:17:49 -07:00
Antoine Pairet 87a3607632 fix(tooltip): Fix for issue #3167 2015-03-15 16:39:50 -07:00
Rouven Weßling aa0b6392db fix(demo): Modify the demo app to play nice with Angular 1.3
Fixes #3098
2015-03-15 16:30:08 -07:00
Bart Verkoeijen 9ca4ec399b fix(accordion): noop for href in header to prevent page refresh with nested buttons canceling events
When nesting buttons in the header, and calling `$event.stopPropagation()` in their click handlers would cause a page refresh, because the default empty URL would be executed. By changing this into a noop, the page refresh is prevented. #3299
2015-03-15 16:19:24 -07:00
Henri Hietala 6abad509cd fix(Accordion): Made accordion heading tab-able for IE9-10
- Add tabindex to anchor tag
2015-03-15 15:00:27 -07:00
Robin van Baalen db570e36df Merge pull request #3368 from jodytate/patch-2
fix(docs): 'typehead' to 'typeahead'
2015-03-09 21:39:23 -04:00
jody tate c505546abb typo: fix 'typehead' to 'typeahead' 2015-03-09 12:31:53 -07:00
MikeMatusz c2e5b284a3 fix(datepicker): don't stop ESC propagation unless dropdown is open
In reference to issue #3096
If the escape key should have other functionality in the context of a form (for
example, if datepicker is on a modal) it makes sense to prevent this from
happening if escape is used to close the dropdown.  If the dropdown is closed,
however, the event should be allowed to propagate.

Fixes #3096
Closes #3179
2015-03-08 23:21:16 -07:00
Christian Asmussen 2724b46282 docs(datepicker): fix a double negative
no model value is ~~not~~ specified
2015-03-08 22:43:05 -07:00
jgleason cb41538eea refactor(accordion): Use angular.noop instead
Closes #3224
2015-03-08 22:35:32 -07:00
Martijn Verburg 001c9effa4 Merge pull request #3336 from ramdog/patch-1
Update README.md
2015-02-25 16:16:01 +00:00
Ramin Taleghani 692268185d Update README.md 2015-02-25 08:10:50 -08:00
Martijn Verburg f1dd46a07a Merge pull request #3330 from karianna/master
Update README.md with progress of 0.12.1 release
2015-02-24 07:43:50 +00:00
Martijn Verburg 868798ed2e fix(doc): Update progress in README 2015-02-24 07:40:54 +00:00
Martijn Verburg f38ad2ba5e Merge branch 'master' of github.com:angular-ui/bootstrap 2015-02-24 07:38:10 +00:00
Dave Martin 23936f9f6e fix(datepicker): date formatting when using angular 1.3 fixes #2659
Closes #3293
Closes #3279
Closes #2440
Closes #2932
Closes #3074
Closes #2943
Closes #2733

Fixes #3047
Fixes #2659
Fixes #2681
2015-02-21 14:31:45 +01:00
Dave Martin 5f9afe5a86 fix(datepicker): date formatting when using angular 1.3 fixes #2659 2015-02-20 21:25:47 +01:00
Antoine Pairet ed5013b331 chore(angular): upgrade angular to version 1.3.13 2015-02-20 21:25:47 +01:00
Chris Chua fe33ca9848 chore(release): Starting v0.13.0-SNAPSHOT 2015-02-20 12:17:25 -08:00
Chris Chua b7e68347ad chore(release): 0.12.1 2015-02-20 11:47:50 -08:00
Chris Chua 5726e3efae fix(tooltip): incorrect position when text wraps
The $digest that was removed in 32c470 is actually necessary to get the
tooltip contents rendered. The rendered content is important when the
tooltip is on the right edge. See Plunker in #2995:
http://plnkr.co/edit/8GZ5F5zj3Xe6IinXQz74?p=preview

Reverts change in 32c470 (#2995) but fixes it in another way.

Fixes #2995
Fixes #2992
Fixes #2951
Closes #2996
2015-02-20 11:40:06 -08:00
Chris Chua da31a4fcda Revert "Merge pull request #3044 from jiniguez/fix2280"
This reverts commit f671e02e97, reversing
changes made to eec68d81f4.
2015-02-20 11:35:59 -08:00
Chris Chua 821c1ab0b1 Revert "Merge pull request #3169 from Hypercubed/master"
This reverts commit 0938d3fec3, reversing
changes made to f671e02e97.
2015-02-20 11:34:59 -08:00
Martijn Verburg b8bfd364fe Merge pull request #3301 from swolfand/master
Fixed a typo in CONTRIBUTING.md
2015-02-16 16:57:13 +00:00
wkh176 5dc30504a8 Fixed a typo in CONTRIBUTING.md 2015-02-16 11:40:49 -05:00
Martijn Verburg ee829af310 Merge pull request #3275 from jodytate/patch-1
"it" to "it's"
2015-02-10 14:51:24 +00:00
jody tate a89fc720be "it" to "it's" 2015-02-09 14:44:12 -08:00
Rob Jacobs 18c6acf7ad Revert "feat(popover): support templates (WIP) #1848"
This reverts commit b7beaae53a.
2015-02-04 18:39:01 -05:00
Rob Jacobs b7beaae53a feat(popover): support templates (WIP) #1848 2015-02-04 15:30:51 -05:00
Martijn Verburg 60aec2e88d Merge pull request #3226 from jClarity/master
Update README with 2015 plans and move Support up higher
2015-01-27 11:32:51 +00:00
Martijn Verburg c237757c9a Merge pull request #1 from karianna/master
Update README for 2015 Plans and move support higher
2015-01-27 11:22:08 +00:00
Martijn Verburg ea4460434c Move Support Higher 2015-01-27 11:20:14 +00:00
Martijn Verburg 384bf6061c Update README.md to convey plans for 2015 2015-01-27 11:18:49 +00:00
Martijn Verburg 2e62733c7a Update README.md to convey plans for 2015 2015-01-27 11:17:00 +00:00
Martijn Verburg ec5d73ee48 Update README.md to convey plans for 2015 2015-01-27 11:15:32 +00:00
Martijn Verburg 721e288a91 Update README.md to convey plans for 2015 2015-01-27 11:14:50 +00:00
Martijn Verburg 905db179f4 Update README.md to convey plans for 2015 2015-01-27 11:11:14 +00:00
Martijn Verburg 9935e6c7a2 Merge pull request #3198 from gitter-badger/gitter-badge-1
Add a Gitter chat badge to README.md
2015-01-27 10:55:04 +00:00
The Gitter Badger 4ed94b566b Added Gitter badge 2015-01-16 12:12:50 +00:00
Martijn Verburg 0938d3fec3 Merge pull request #3169 from Hypercubed/master
fix(tooltip): Fix for issue #3167
2015-01-08 08:46:19 +00:00
Martijn Verburg f671e02e97 Merge pull request #3044 from jiniguez/fix2280
fix(modal): fix for conflicts with ngTouch module on mobile devices
2015-01-08 08:41:10 +00:00
Jayson Harshbarger 1ac964600a fix(tooltip): Tooltip on button doesn't hide if button is disabled on click
Fix for issue #3167
2015-01-08 11:13:57 +09:00
sashless a6b9d5390d make it useable in xhtml documents 2014-12-08 14:41:37 +01:00
Jon Iñiguez de Heredia 722036c77c Moved click event from template to directive code 2014-12-02 23:41:17 +01:00
Alexander Artemenko eec68d81f4 docs(CHANGELOG): fix 0.12.0 header's level
Closes #2975
2014-11-17 01:26:03 -08:00
Chris Chua ac68c046f6 chore(release): Starting v0.13.0-SNAPSHOT 2014-11-16 13:36:32 -08:00
Chris Chua 1cebcbc387 chore(release): 0.12.0 2014-11-16 13:04:54 -08:00
Chris Chua 390f2bf6b0 fix(build): make custom builds on demo site work
Use approach from Twitter Bootstrap. Most of the code is from their customizer.

- use modules in mappings file
- generate concatenated JS
- generate tpl and non-tpl file with banner
- generate zip file for custom builds
- add browser compatibility message
- speed up page by deferring loading of files
- only load the files when needed. Cache them after they're loaded.

Fixes #2960
Fixes #2847
Fixes #2625
Fixes #2489
Fixes #2357
Fixes #2176
Closes #2892
2014-11-14 01:46:12 -08:00
Chris Chua 32c4704b74 fix(tooltip): remove extra digest causing incompatibility
In Angular 1.3.1, when using tooltips with ngAnimate, this extra $digest
call seems to break ngClass. This is an extra call to ngAnimate and it
shouldn’t be called since the tooltip hasn’t been added to the DOM.

I was unable to create a test case to test compatibility with ngAnimate.

Fixes #2951
Fixes #2959
2014-11-14 00:05:33 -08:00
Chris Chua b4832c4b55 fix(tooltip): show correct tooltip on ngRepeat
Thanks to @red-0ne for the test case.

This commit reverts a1b1ec4fe0f4ddaad343b16edb8434ff1614300c
(#2825) .

Fixes #2935
2014-11-10 23:59:35 -08:00
Warren Konkel 35d0cc1d57 feat(typeahead): add focus-first option
Add typeahead-focus-first option to prevent first match from being
focused.

Currently, the first result is automatically focused as you type. Now, set
`typeahead-focus-first="false"` and the first result is *not*
automatically focused as you type.

Closes #908
Closes #2916
2014-11-09 14:18:32 -08:00
blah238 992b23297c fix(accordion): make header links keyboard accessible
Closes #2869
2014-11-09 14:02:26 -08:00
Chris Chua a5e114da73 demo(carousel): mention 0 in interval option
Now an interval of 0 will also stop the carousel.
2014-11-09 13:57:23 -08:00
Joaquín Omar Tumas 392c0ad13c fix(carousel): replaced $timeout with $interval when it was wrong
I had a to tweak a bit two tests since $interval never throws an exception after flushing, hope I did it OK.

Ammend: addresses @chrisirhc critics

Fixes #1308
Fixes #2454
Closes #2776
2014-11-09 13:57:12 -08:00
Chris Chua faf38d20a4 fix(tooltip): memory leak on show/hide
Create a new child scope and retain a reference to it so that it can
be destroyed when the tooltip DOM is removed.

Fixes #2709
Closes #2919
2014-11-05 01:30:33 -08:00
Chris Chua 8204c80881 fix(tooltip): remove child scope requirement
tt_ scope variables are now in the ttScope which is specific to each
tooltip directive (multiple tooltip directives can now run on the same
element).

This allows tooltips to be used alongside any directive that may or
may not require different scope types.

Closes #1269
Fixes #2320
Fixes #2203
2014-11-05 01:25:38 -08:00
Chris Chua e10d561f92 fix(tooltip): evaluate appendToBody on init
This wasn't working properly with the location change code
(lines 305-314) because the observe call happens asynchronously after
the linking function has completed.

Hence, the locationChangeSuccess wasn't being set up unless the global
tooltip option's appendToBody option was set to true.

Closes #2921
2014-11-05 01:13:09 -08:00
blah238 5df524b771 fix(tabs): make tab links keyboard accessible
Fixes #2226
Fixes #2290
Closes #2870
Closes #2304
2014-11-03 02:21:07 -08:00
Chris Chua a65bea9533 refactor(tooltip): remove observer for triggers
This change fixes the usage of the tooltip directive with AngularJS
1.3.1 when no trigger attribute is used.

BREAKING CHANGE: tooltip/popover trigger is no longer a watched
attribute.
This affects both popovers and tooltips. The triggers are now set up
once and can no longer be changed after initialization.
2014-11-01 22:15:14 -07:00
Chris Chua 13b5cd95a7 refactor(tooltip): lazily evaluate placement, delay
There's no need for an observer here because these values are only used
on initialization of the tooltip.
2014-11-01 22:14:09 -07:00
Kyle eab6daf64b fix(demo): initial load of fragment URLs
Closes #2762
2014-10-27 00:02:43 -07:00
Chris Chua 3232b4e8bf refactor(demo): resolve JSHint warnings
- Use $log instead of console as it's safer and always defined
- JSHint thinks usage of alert is possibly development code, so use
  $window.alert instead
2014-10-20 02:46:27 -07:00
Chris Chua 34273ff010 fix(tests): usage of undefined variables 2014-10-20 02:46:27 -07:00
Chris Chua 42011f0665 chore(jshint): make JSHint configuration stricter
- Check for usage of undefined variables
- Add basic Jasmine globals so that spec files pass JSHint
- Ensure that angular variable can't be re-defined (set to false)

Closes #2861
2014-10-20 02:46:19 -07:00
Pawel Kozlowski ca6fad675b feat(alert): allow alerts to be closed from a controller
Closes #2399
Closes #2854
2014-10-19 21:44:50 +02:00
Richard Littauer c9baf00762 style(modal): change to dot notation
Closes #2634
2014-10-19 20:38:22 +02:00
Vitaly Aminev 1f6c3c92af fix(typeahead): don't leak DOM nodes
when `appendToBody` option is set to true and then scope is destroyed,
DOM is still polluted with popup.
This fix removes `$popup` from DOM, thus cleaning it
2014-10-19 20:30:54 +02:00
Guillaume Balaine 689c4d017d fix(tooltip): don't use an empty transclusion fn
Closes #2825
2014-10-19 20:20:13 +02:00
Dimitri Walters 6df92c0618 docs(alert): use monospace format for code references
Closes #2850
2014-10-19 12:07:24 +02:00
Marco 460fbec776 fix(datepicker): correct button alignment when using bootstrap v3.2.0
Closes #2728
2014-10-18 12:35:59 +02:00
Pawel Kozlowski 1706757587 demo(carousel): fix a link to first cat image
Fixes #2841
2014-10-17 17:18:16 +02:00
Pawel Kozlowski b9db670ede docs: add links to FAQ 2014-10-15 19:45:33 +02:00
Smith 5cb8d38ad1 docs(modal): typo in comment: loose > lose
Closes #2817
2014-10-14 19:34:27 +02:00
Chris Rebert b94bdbb8f8 docs(CONTRIBUTING): fix markdown link syntax
Closes #2819
2014-10-14 19:09:40 +02:00
Chris Chua 03b7c69ed7 docs(CHANGELOG): fix commit SHA link 2014-10-02 02:14:35 -07:00
Richard Littauer 4fc68b88e7 docs(README): Removed unnecessary string replacements
If `.html` is removed from the end only to be added to the end, there's no reason to touch it. Also, `template` + `/` is the same as `template/`.

I haven't tested this, but I see absolutely no reason why this code isn't the same functionally.

Closes #2635
2014-10-01 00:43:06 -07:00
Chris Chua ef09517061 fix(dropdown): compatibility with $location url rewriting
Fixes #2343
2014-10-01 00:37:28 -07:00
Coridyn Fitzgerald-Hood f15bfcfa27 test(tabs): don't select tabs when being destroyed
Closes #2763
2014-09-30 23:12:10 -07:00
Tom France 9939867aba fix(tabs): don't select tabs on destroy
Fixes #2155

Closes #2596
2014-09-30 23:01:41 -07:00
Tasos Bekos 192768e109 fix(dropdown): remove C restrictions to avoid conflicts
Fixes #2156

Closes #2170

BREAKING CHANGE: Both `dropdown` and `dropdown-toggle` are only attribute directives

Before:
  ```html
  <button class="dropdown-toggle" ...>
  ```
  After:
  ```html
  <button class="dropdown-toggle" dropdown-toggle ...>
  ```
2014-09-26 09:12:39 -07:00
Chris Chua 758edbb4d7 chore(release): Starting v0.12.0-SNAPSHOT 2014-09-26 09:11:32 -07:00
Chris Chua 88cd454549 chore(release): 0.11.2 2014-09-26 09:03:10 -07:00
Chris Chua 1a998c4686 revert(dropdown): remove C restrictions to avoid conflicts"
Breaking change shouldn't go into patch release.

This reverts commit 7512b93fec.

Fixes #2757

Fixes #2756
2014-09-26 09:03:05 -07:00
Chris Chua b44215df6f chore(release): Starting v0.11.2-SNAPSHOT
To fix a breaking change.
2014-09-26 09:02:31 -07:00
Chris Chua bc23d1c2bd chore(release): 0.11.1 2014-09-26 00:35:21 -07:00
Ankit Kumar 08c150e127 fix(datepicker): memory leak fix for datepicker
Fixes #2658
Closes #2684
2014-09-15 00:18:59 -07:00
Peter Dave Hello b75f7afb9e docs(README): use svg instead of png to get better image quality
Closes #2629
2014-08-26 08:22:06 +02:00
Alexander Harding 7b7cdf8422 fix(modal): controllerAs not checked
This causes the controller to be added to the scope as a property "undefined"!

Closes #2564
2014-08-15 18:04:05 +02:00
chapplez a0be450ddb fix(typeahead): replace ng-if with ng-show in matches popup
Fixes #2474
Fixes #2541
Fixes #2293
Closes #2535
Closes #2557
2014-08-15 17:54:02 +02:00
Petr Kotek e793c37b09 docs(contributing): fix typos
Closes #2566
2014-08-15 17:51:46 +02:00
Pawel Kozlowski 9030d2c971 docs(CONTRIBUTING.md): clarify GitHub issues handling policy 2014-07-27 09:27:49 +02:00
Tasos Bekos 7512b93fec fix(dropdown): remove C restrictions to avoid conflicts
Fixes #2156

BREAKING CHANGES: Both `dropdown` and `dropdown-toggle` are only attribute directives

Before:
  ```html
  <btutton class="dropdown-toggle" ...>
  ```
  After:
  ```html
  <btutton class="dropdown-toggle" dropdown-toggle ...>
  ```

Closes #2170
2014-07-22 21:28:33 +02:00
Michael Lilli e62ab94a63 fix(modal): respect autofocus on child elements
Auto-focusing of a freshly-opened modal element causes any child
elements with the autofocus attribute to loose 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.

Fixes #1696
Closes #1892
Closes #2273
2014-07-08 10:00:19 -07:00
Tasos Bekos 63ae06c9e1 fix(datepicker): correct datepicker-mode binding for popup
Fixes #2180
Closes #2184
2014-06-11 19:32:43 +02:00
Caitlin Potter 5cd6f4af47 chore(Gruntfile): add grunt-ddescribe-iit task to CI checks
This should prevent `ddescribe` and `iit` blocks in tests from being checked into the tree, as they
were in #2311.
2014-06-09 23:02:39 +02:00
Mohammed Buttu aa8c6541e6 test(modal): Remove ddescribe in the $modal tests
The `ddescribe` is only executing the $modal tests. Removing it will allow
all other unit tests to run.

Fixes #2311.
2014-06-09 22:53:38 +02:00
Pawel Kozlowski 990015fb89 feat(modal): allow templateUrl to be a function
Fixes #2296
2014-06-05 20:32:28 +02:00
Pawel Kozlowski 6e83dc647a docs(README): fix code samples formatting 2014-05-29 12:49:37 +02:00
Pawel Kozlowski 79105368b3 fix(modal): allow in-lined controller-as controllers 2014-05-27 19:26:12 +02:00
Pawel Kozlowski 8d7c2a263f feat(modal): support alternative controllerAs syntax
Fixes #2242
2014-05-22 21:30:31 +02:00
Pawel Kozlowski b519b63268 docs(typeahead): use array.map to shorten async example 2014-05-22 20:30:36 +02:00
Aaron Mendez e420204fa2 docs(CHANGELOG): fix code snippets
A few snippets were not wrapped in code blocks.

Closes #2245
2014-05-22 20:15:12 +02:00
Pawel Kozlowski cdbfac46d2 docs(README): remove reference to bitdeli analytics
see: http://blog.bitdeli.com/post/77717727361/on-githubs-image-proxy
2014-05-16 18:31:47 +02:00
Pawel Kozlowski e8e8fb67b4 chore(build): switch to node 0.10.x on TravisCI 2014-05-16 18:27:40 +02:00
JeremyWeir a708fe6de5 fix(tabs): remove leading newline from a template
This messes up jquery's parsing of the template

Closes #2200
Fixes #2106
2014-05-15 19:58:12 +02:00
Tasos Bekos 42cc3f269b fix(dateparser): do not parse if no format specified
Fixes #2159
Fixes #2137
Closes #2162
2014-05-08 17:26:23 +02:00
Domenico Matteo c7db0df400 fix(typeahead): allow multiple line expression
introduce [\s\S]+ to include both whitespace and non whitespace
characters

Fixes #1687
Closes #1850
2014-05-06 19:23:10 +02:00
Chris Chua aa188aec02 fix(alert): correct binding of alert type class
Regression from #1745 as there's a double interpolation expected but
ngClass doesn't support that.

The attribute value of ngClass is only interpolated once and the
interpolated expression is watched.

Fixes #2145
Closes #2146
2014-05-05 19:23:18 +02:00
Chris Chua 44e7d77d3a chore(all): clean up trailing whitespace
jshint is failing.

Closes #2147
2014-05-05 19:15:58 +02:00
Pawel Kozlowski 0b31e8658e fix(modal): add a work-around for transclusion scope
Fixes #2110
Closes #2134
Closes #2143
2014-05-05 19:14:59 +02:00
Pawel Kozlowski d7c314e21c test(datepicker): DOM elements cleanup 2014-05-04 18:20:26 +02:00
Pawel Kozlowski 98af6f9102 test(tooltip): DOM elements cleanup 2014-05-04 18:20:01 +02:00
Pawel Kozlowski d51c189004 test(collapse): DOM elements cleanup 2014-05-04 18:19:41 +02:00
James Sanders 353e612717 feat(modal): add backdropClass option, similar to windowClass option
Really, identical to windowClass, but for backdrop.

Fixes #1179
Closes #1862
2014-05-04 16:48:37 +02:00
Pawel Kozlowski ef62364595 chore(build): improve Karma reporting 2014-05-04 13:09:23 +02:00
Pawel Kozlowski afdefcf99c refactor(modal): remove unused variables 2014-05-04 12:55:09 +02:00
venuatu 1590920cdc fix(modal): allow modal.{dismiss,close} to be called again
$modalStack.openWindows.get(modalInstance) is undefined after the first dismiss and throws:
-   TypeError: Cannot read property 'value' of undefined

Closes #1972
2014-05-04 12:30:07 +02:00
Tasos Bekos 3ac3b48746 fix(dropdown): close after selecting an item
Fixes #2130
Closes #2140
2014-05-04 12:23:17 +02:00
Jesus Rodriguez 5b41e47144 refactor(demos): use angular modules
Closes #1912
2014-05-04 12:16:32 +02:00
Pawel Kozlowski a316e3ee07 chore(ngVersion): bump up AngularJS version to 1.2.16 2014-05-03 19:27:07 +02:00
Michal Wesolowski 5dc57927e8 fix(typeahead): timeout cancellation when deleting characters
Closes #2074
2014-05-02 19:05:37 +02:00
Pawel Kozlowski 941a382858 chore(release): Starting v0.12.0-SNAPSHOT 2014-05-01 18:33:12 +02:00
Pawel Kozlowski a81d6f986a chore(release): 0.11.0 2014-05-01 17:53:35 +02:00
Chris Chua 2b429f5de5 fix(tooltip): animation causes tooltip to hide on show
Add logic to handle cases where hide/show can be called multiple times
even before their timeouts complete.

This is more ugly logic to handle degenerate cases. Hopefully switching
over to ngAnimate and cleaning up the logic of tooltips will be better.

Fixes #1847

Closes #1940
2014-05-01 17:19:55 +02:00
Pawel Kozlowski 60cee9dcb5 feat(modal): improve accessibility - add role='dialog' 2014-05-01 17:17:09 +02:00
Jose Martinez 06ad3bd5db fix(dropdown): ensure on-toggle works when is-open is not used
This fixes an issue where on-toggle doesn't get called on the first
click if the is-open attribute is not used.

Closes #2121
2014-05-01 17:02:04 +02:00
W. Trevor King cc07cdda20 docs(modal): fix Markdown markup for augmented methods
Without leading and trailing blank lines, the source is not marked up
as a list.

Closes #2107
2014-04-30 20:56:41 +02:00
Gias Kay Lee 7899b120f8 test(modal): add test for controllerAs syntax
Closes #2091
2014-04-21 19:01:11 +02:00
Gareth Oakley 976f6083e8 feat(modal): support modal window sizes
Allows use of the size modifier classes shipped with Bootstrap 3.1
onwards. Specify either 'sm' or 'lg' to get a small/large modal dialog.
Defaults to normal size dialog if not specified.

Closes #2084
2014-04-20 14:53:02 +02:00
Tasos Bekos da95122222 fix(modal): prevent default event when closing via escape key
Fixes #1692
Closes #2087
2014-04-19 21:50:03 +02:00
Tasos Bekos 96def3d6e3 feat(modal): support custom template for modal window
Closes #2057
2014-04-19 18:41:07 +02:00
Tasos Bekos 00829b6058 refactor(modal): add class to element instead of template expression 2014-04-19 18:41:07 +02:00
Pawel Kozlowski ded352c5c1 demo(all): use protocol-less URLs
Fixes #2070
Closes #2068
2014-04-19 18:10:53 +02:00
Tasos Bekos e0eb1bce37 fix(datepicker): parse input using dateParser
Fixes #1289
Closes #2085
2014-04-19 12:48:56 +03:00
Tasos Bekos bd2ae0ee02 feat(dateParser): add dateParser service
Closes #1874
2014-04-19 11:53:16 +03:00
Tasos Bekos 73c2dea548 refactor(dropdown): do not stop event propagation
Fixes #1986
Closes #2076
2014-04-18 12:52:56 +03:00
Tasos Bekos 97b0747777 refactor(timepicker): change variable usage 2014-04-18 12:21:48 +03:00
Jesus Rodriguez b0b1434389 feat(datepicker): full six-week calendar 2014-04-16 19:05:14 +03:00
Tasos Bekos 2423f6d4c0 feat(datepicker): make widget accessible
* keyboard navigation
 * WAI-ARIA roles
 * popup will close on escape on input or calendar
 * handle focus when closing popup

Closes #1922

BREAKING CHANGES: popup calendar does not open on input focus
2014-04-13 20:20:17 +03:00
Tasos Bekos de5a25e6de docs(typeahead): add typeahead-on-select callback parameters
Closes #2047
2014-04-13 00:14:34 +03:00
Tanguy Krotoff cb31b875f9 fix(modal): give a reason of rejection when escape key pressed
Fixes #1956
Closes #1991
2014-04-12 23:09:03 +03:00
Tasos Bekos 004dd1de25 fix(dropdown): do not call on-toggle initially
Closes #2021
2014-04-11 15:02:50 +03:00
Tasos Bekos 4c76a858de feat(typeahead): add aria-owns & aria-activedescendant roles 2014-04-11 14:55:34 +03:00
Duncan Beevers 82df4fb1c4 feat(button): allow uncheckable radio button
Acts as a hybrid checkbox/radio-button, selecting exclusively among the button set, but also allowing the selected item to be unselected, leaving the button set without a selected item.

Closes #1760
2014-04-09 21:30:30 +03:00
Philipp Denzler f48e4339e9 chore(dropdown): remove unused var
Closes #2023
2014-04-06 19:40:05 +02:00
tomchentw 3b6ab25b5c fix(carousel): correct glyphicon
Fixes #2006
Closes #2014
2014-04-02 02:22:53 -07:00
MacTEC 4b811b7adc chore(typeahead): fix typo in comment
Closes #1925
2014-03-21 13:13:55 +01:00
Shayan Elhami d0024931de fix(typeahead): incompatibility with ng-focus
Used timeout to avoid $rootScope:inprog error

Fixes #1773
Closes #1793
2014-03-17 00:25:29 -07:00
Jesus Rodriguez f9aa4590e9 fix(karma): exclude demo files
Closes #1889
2014-03-08 22:14:12 +01:00
Tasos Bekos f9b6c49623 fix(timepicker): evaluate correctly the readonly-input attribute
Closes #1911
2014-03-08 21:08:34 +01:00
Tasos Bekos f715d05225 feat(dropdown): focus toggle element when opening or closing with Esc`
* Improve accessibility.

Closes #1908.
2014-03-08 19:55:56 +01:00
Jesus Rodriguez d89bbd1008 test(pagination): clean some injections
Closes #1895
2014-03-08 19:47:10 +01:00
Michal Charemza 6a830116f2 fix(typeahead): loading callback updates after blur
Fixes #1822
Closes #1904
2014-03-08 18:18:23 +01:00
Pawel Kozlowski c6c0e2d9ef chore(ci): switch off IE testing on TravisCI 2014-03-08 18:09:52 +01:00
Tasos Bekos 341b5b5886 demo(datepicker): add type attribute to buttons
Closes #1890
Closes #1894
2014-03-05 16:27:50 +01:00
Tasos Bekos 890e2d37c1 fix(dropdown): unbind toggle element event on scope destroy
Also, change the way disabled dropdownToggle is read from `attrs` instead of element property.

Closes #1867
Closes #1870
2014-02-27 23:02:00 +01:00
Rafael Garcia 93da30d559 fix(datepicker): rename dateFormat to datepickerPopup in datepickerPopupConfig
Closes #1810
2014-02-27 22:43:51 +01:00
Ricki Runge 467dd159b3 fix(datepicker): mark input field as invalid if the date is invalid
Closes #1845
2014-02-27 22:28:24 +01:00
Tasos Bekos 0d4c2e21c3 refactor(carousel): use track by in template
Closes #1723
2014-02-22 11:36:22 +01:00
stonelee 3e938bd60a refactor(accordion): transclude function in compile is deprecated.
Closes #1789
2014-02-22 11:31:43 +01:00
Tasos Bekos 5ca23e9746 feat(typeahead): add WAI-ARIA markup
Closes #1814
2014-02-22 11:29:32 +01:00
Tasos Bekos d19b4c0e85 refactor(dropdown): remove isolated scope
Closes #1818
2014-02-22 11:25:59 +01:00
Tasos Bekos 378a933797 fix(progressbar): number filter in bar template and only for percent
Closes #1807
2014-02-20 09:51:07 +01:00
Tasos Bekos e1993491f2 fix(datepicker): Today button should not set time
Fixes #1726
Closes #1808
2014-02-15 21:24:32 +01:00
Tasos Bekos dea67b08b5 chore(demo): fix fork button width
Closes #1805
2014-02-15 21:20:14 +01:00
Tasos Bekos 9a2638bfb0 feat(alert): add WAI-ARIA markup
Closes #1806
2014-02-15 21:18:15 +01:00
Tasos Bekos bce250540a refactor(pagination): move boundary & directions to the template
Closes #795
Closes #1770
2014-02-13 22:29:21 +01:00
Tasos Bekos c01d25511a refactor(datepicker): track buttons by date instead of $index 2014-02-13 22:24:07 +01:00
Pawel Kozlowski c5862b0bf3 demo(typeahead): correct demo for asyn results
Fixes #1740
2014-02-11 19:16:41 +01:00
Tasos Bekos 31115017d5 refactor(typeahead): use ng-if and track by in template
Closes #1722
2014-02-10 22:16:17 +01:00
Pawel Kozlowski 09678b1260 fix(typeahead): correctly higlight numeric matches
Fixes #1777
2014-02-10 22:05:37 +01:00
Tasos Bekos cde6a4509f refactor(pagination): remove unused watch
Closes #1769
2014-02-09 22:04:34 +01:00
Tasos Bekos a88b115e7a refactor(rating): evaluate attributes inside init function
Closes #1590
Closes #1768
2014-02-09 22:01:22 +01:00
Tasos Bekos 7f4b40eb8b feat(datepicker): add datepicker-mode, init-date & today hint
* Add two-way binded `datepicker-mode`.
 * Add optional `init-date` when no model value is specified.
 * Add hint for current date.
 * Use isolated scope for popup directive.
 * Use optional binding for `isOpen`.
 * Split each mode into it's own directive.

Closes #1599

BREAKING CHANGE:
`show-weeks` is no longer a watched attribute
`*-format` attributes have been renamed to `format-*`
`min` attribute has been renamed to `min-date`
`max` attribute has been renamed to `max-date`
2014-02-08 23:40:58 +01:00
Valentyn Shybanov e8d5fefcff fix(dropdown): use $animate for adding and removing classes
Closes #1644
2014-02-08 21:18:25 +01:00
Travis Grathwell 0daa7a7470 fix(progressbar): allow fractional values for bar width
* Fractions are limited to two decimals, and are not included in aria values.

Closes #1761
2014-02-08 20:46:45 +01:00
Tasos Bekos 101c43ac3e refactor(pagination): add href and track by in templates
Closes #1725
2014-02-08 20:36:35 +01:00
Tasos Bekos 68e5644024 refactor(rating): use track by in template
Closes #1724
2014-02-08 20:32:41 +01:00
Pawel Kozlowski a294c87f23 fix(pagination): take maxSize defaults into account
Fixes #1728
Closes #1738
2014-02-08 15:00:18 +01:00
Jesus Rodriguez b7eb69edfc demo(timepicker): update to angular 1.2.x
Closes #1755
2014-02-08 13:25:44 +01:00
Tasos Bekos 22ebd2300e feat(dropdown): add WAI-ARIA attributes
* Add `aria-haspopup` and `and aria-expanded` attributes to dropdown toggle.
 * Dynamically change `aria-expanded` when the dropdown closes or opens.

Closes #1733
2014-02-07 19:28:27 +01:00
Tasos Bekos 794954afe5 fix(alert): add alert-dismissable class
Closes #1745
2014-02-07 19:24:21 +01:00
Travis Grathwell 42d6d436c1 docs(readme): fix typos in readme and contributing guidelines
Closes #1762
2014-02-06 23:30:56 +01:00
nnpp a6a1049041 fix(readme) fix typos
Closes #1757
2014-02-06 16:18:59 +01:00
Jesús Rodríguez Rodríguez c336351be0 Merge pull request #1731 from gdi2290/patch-1
style(license): update copyright year range
2014-02-04 02:19:53 -08:00
PatrickJS 9de864e9e3 style(License): update copyright year range 2014-02-03 23:02:55 -08:00
Tasos Bekos 9dfe31572a feat(progressbar): make widget accessible
* Add WAI-ARIA markup.

Closes #1717
2014-02-01 16:20:10 +01:00
Tasos Bekos 1946833135 fix(tabs): remove tabbable class required for left/right tabs
Closes #1708
2014-01-31 19:17:02 +01:00
Tasos Bekos ab0387c041 refactor(tabs): use optional binding for active
Closes #1713
2014-01-31 19:10:29 +01:00
Tasos Bekos 4f56e60e60 feat(rating): make widget accessible
* Support keyboard navigation.
 * Add WAI-ARIA markup.
 * Text representation for screen readers.

Source: http://mindtrove.info/creating-an-accessible-internationalized-dojo-rating-widget/

Closes #1707
2014-01-31 19:09:06 +01:00
marcellino 4a9dbbef04 fix(demo): Scroll to element on initialization 2014-01-30 22:47:16 +01:00
Pawel Kozlowski 3704db9ab0 feat(tooltip): support more positioning options
Closes #1676
2014-01-30 19:13:02 +01:00
marcellino 1ba07c1b5c fix(position): remove deprecated body scrollTop and scrollLeft
Fixes #1658
Closes #1677
2014-01-30 19:06:19 +01:00
marcellino 85140f84ab feat(carousel): Support swipe for touchscreen devices
use ng-swipe-* directives. If ngTouch is included, it will be used.

Closes #1686
2014-01-29 11:53:51 -05:00
Pawel Kozlowski 66cb03bc62 chore(dependencies): update dev dependencies
Update dev dependencies for which we can simply
bump up a varsion to the latest
2014-01-27 21:36:02 +01:00
Pawel Kozlowski f452969f5d chore(build): use minified version for the demo site
Closes #1682
2014-01-27 20:46:50 +01:00
Pawel Kozlowski 6bc6634cf5 chore(ngVersion): update to 1.2.10 2014-01-25 13:16:10 +01:00
Pawel Kozlowski ab054c96f8 demo(all): fix demo scrolling issues
Fixes #1674
2014-01-25 12:52:07 +01:00
Pawel Kozlowski 1078573678 fix(typeahead): correctly handle append to body attribute
Closes #1656
2014-01-24 19:16:18 +01:00
Tak Tran c188416cab docs(typeahead): docs for typeahead-append-to-body
Closes #1663
2014-01-24 18:40:41 +01:00
Chris Chua 94a7f5934a fix(modal): backdrop z-index when stacking modals
Previously, backdrop wouldn't go over the previous open modal when a
modal is open on top of another.

Fixes #1653
Closes #1654
2014-01-23 20:40:54 +01:00
Jesus Rodriguez 8c89ccb163 chore(readme): add support section
Closes #1655
2014-01-23 19:05:42 +01:00
Pawel Kozlowski 4d641ca718 fix(moadl): toggle 'modal-open' class after animation
Fixes #1629
2014-01-22 21:37:47 +01:00
Pawel Kozlowski dfc36fd94b fix(modal): destroy modal scope after animation end
Fixes #1643
2014-01-22 21:01:14 +01:00
Jesus Rodriguez 6fb6a7657f refactor(typeahead): remove unused code
Closes #1651
2014-01-22 20:09:09 +01:00
Jesus Rodriguez 594a64bfd2 test(tooltip): remove more unused code
Closes #1650
2014-01-22 19:57:34 +01:00
Jesus Rodriguez d9ee743be6 test(tooltip): remove unused injection
Closes #1649
2014-01-22 19:48:04 +01:00
Jesus Rodriguez 3d6443476a test(datepicker): remove unused variable
Closes #1648
2014-01-22 19:47:27 +01:00
Jesus Rodriguez 2a1b80ebf3 test(alert): remove unused controller parameter
Closes #1647
2014-01-22 19:41:09 +01:00
Jesus Rodriguez e204be61ee test(accordion): remove unused variable
Closes #1646
2014-01-22 19:36:23 +01:00
marcellino 0314cd40b7 refactor(collapse): removed unused di parameter
Closes #1633
2014-01-22 19:28:38 +01:00
Pawel Kozlowski 8fb39ce0e1 demo(dropdown): remove unneded data-* attributes 2014-01-22 19:03:19 +01:00
Tasos Bekos f8c858ad52 refactor(rating): use optional binding for readonly
Closes #1641
2014-01-22 18:50:54 +01:00
Tasos Bekos 22fc117704 refactor(progressbar): remove $transition dependency
* Remove the need to find out the old value.
 * Reorganize code.

Closes #1564
2014-01-22 10:13:58 +01:00
Tasos Bekos 25de67dcdc refactor(dropdownToggle): rename module to dropdown 2014-01-21 23:21:40 +01:00
Tasos Bekos 1417c54833 feat(dropdownToggle): add support for escape key
Closes #1558
2014-01-21 23:21:39 +01:00
Tasos Bekos ae31079c01 feat(dropdownToggle): support programmatic trigger & toggle callback
Closes #270
Closes #284
Closes #1447
2014-01-21 23:21:39 +01:00
Tasos Bekos 745246ebf0 refactor(timepicker): move logic to controller 2014-01-21 23:15:18 +01:00
Tasos Bekos 83ceb78a8b fix(tabs): use interpolation for type attribute
Closes #1409

BREAKING CHANGE: Use interpolation for type attribute.

  Before:

  <tabset type="'pills'" ...></tabset >
  or
  <tabset type="navtype" ...></tabset>

  After:

  <tabset type="pills" ...></tabset>
  or
  <tabset type="{{navtype}}" ...></tabset>
2014-01-21 15:42:47 -05:00
Tasos Bekos 772734177f demo(buttons): use labels instead of buttons for groups
* Align with BS3 markup.

Closes #1323. Closes #1482
2014-01-21 15:42:31 -05:00
Andy Joslin 05490d6501 chore(carousel): update, simplify doc comment example 2014-01-21 15:42:12 -05:00
Tasos Bekos f0a129ada4 fix(alert): use interpolation for type attribute
Closes #1460

BREAKING CHANGE: Use interpolation for type attribute.

  Before:

  ```html
  <alert type="'info'" ...></alert >
  ```
  or
  ```html
  <alert type="alert.type" ...></alert >
  ```

  After:

  ```html
  <alert type="info" ...></alert >
  ```
  or
  ```html
  <alert type="{{alert.type}}" ...></alert >
  ```
2014-01-21 19:16:11 +01:00
Jesus Rodriguez 2947a2d22c test(modal): remove unneeded injection
Closes #1632
2014-01-21 19:13:32 +01:00
Jesus Rodriguez 16b4c9a362 test(dropdownToggle): add test for disabled element 2014-01-20 17:17:42 +01:00
Jesus Rodriguez 3fb39d29c4 test(datepicker): minor cleanup
Closes #1570
2014-01-20 15:18:10 +01:00
Tasos Bekos 23b7baaa76 style(all): enforce no trailing white space 2014-01-20 15:04:14 +01:00
Andy Joslin bb85213bab chore(docs): add roadmap 2014-01-20 15:02:10 +01:00
Johan Roxendal 7474c47b1a fix(tabs): fire deselect before select callback
Closes #1557
Closes #1566
2014-01-19 13:36:28 +01:00
marcellino a33bac957e chore(jshint): move JSHint configuration to a .jshintrc file
Closes #1613
2014-01-18 21:24:36 +01:00
Jesus Rodriguez 06bd92d4ce style(all): enforce single quotes
Closes #1608
2014-01-18 20:47:48 +01:00
Tasos Bekos 9c43ae7c0a feat(accordion): support is-disabled state
Closes #1126
2014-01-18 20:28:19 +01:00
marcellino f88546da0f chore(conventions): EditorConfig for consistent coding styles
Closes #1609
2014-01-18 20:09:19 +01:00
Pawel Kozlowski a61112de05 demo(all): indicate that we depend on AngularJS 1.2.x 2014-01-18 14:21:47 +01:00
Tasos Bekos 35c93076df refactor(dropdownToggle): listen to $locationChangeSuccess
* Listen to  event instead of adding an extra `$watch` to the `$digest` cycle.
 * Remove `$location` DI, that sometimes caused weird issues.

Closes #1585
2014-01-18 13:37:34 +01:00
Pawel Kozlowski 34dfff4bbf refactor(tooltip): remove work-arround for AngularJS 1.0.x bug 2014-01-18 13:23:45 +01:00
Pawel Kozlowski 4a2809290b refactor(carousel): remove unneded dependency 2014-01-18 13:09:29 +01:00
marcellino 9d5bc0aec7 refactor(carousel): use optional binding for 'active' attr in slides
Closes #1602
2014-01-18 12:57:21 +01:00
Tasos Bekos 0702403d1f refactor(accordion): use optional binding for isOpen
Closes #1596
2014-01-18 12:53:42 +01:00
Bitdeli Chef a1edfe9ef3 docs(README): add a Bitdeli badge
Closes #1605
2014-01-18 12:49:25 +01:00
Jesus Rodriguez 68cb2e5aaf fix(datepicker): remove unneeded date creation
Closes #1595
2014-01-18 12:47:03 +01:00
Chris Chua 1b90a72b11 demo(build): make build modal download consistent
Closes #1579
2014-01-17 13:32:59 +01:00
Tasos Bekos 566ae7323e demo(download): fix download process
Closes #1572
Closes #1576
2014-01-14 00:54:36 -08:00
Pawel Kozlowski 70b1a63b3a docs(rating): cleanup after merge 2014-01-13 22:51:14 +01:00
Tasos Bekos 47e227f6f4 feat(rating): plug into ngModel controller
Closes #1546

BREAKING CHANGE: `rating` is now integrated with `ngModelController`.
 * `value` is replaced from `ng-model`.

  Before:

  <rating value="rate" ...></rating>

  After:

  <rating ng-model="rate" ...></rating>
2014-01-13 21:44:19 +01:00
Tasos Bekos d65901cff8 feat(pagination): plug into ngModel controller
Closes #1545

BREAKING CHANGE: Both `pagination` and `pager` are now integrated with `ngModelController`.
 * `page` is replaced from `ng-model`.
 * `on-select-page` is removed since `ng-change` can now be used.

  Before:

  <pagination page="current" on-select-page="changed(page)" ...></pagination>

  After:

  <pagination ng-model="current" ng-change="changed()" ...></pagination>
2014-01-13 21:41:04 +01:00
Pawel Kozlowski 27a642f528 chore(release): Starting v0.11.0-SNAPSHOT 2014-01-13 21:35:52 +01:00
Pawel Kozlowski 45f568da08 chore(release): v0.10.0 2014-01-13 20:59:39 +01:00
Pawel Kozlowski f0d8d99b98 chore(ngversion): update to AngularJS 1.2.8 2014-01-13 20:56:21 +01:00
Tasos Bekos 92c1715fe3 fix(datepicker): evaluate show-weeks from datepicker-options
Closes #1532
Closes #1563
2014-01-11 20:34:23 +01:00
Pawel Kozlowski bc8d21c151 feat(modal): expose dismissAll on $modalStack
Closes #1334
Closes #1552
2014-01-11 17:48:53 +01:00
Tasos Bekos 42a029f611 chore(demo): fix eye icon for watched attributes
Closes #1556
2014-01-11 12:17:50 +01:00
Chris Rebert 912770fdcc docs(all): reflect Bootstrap's org change
also reflect the fact that the Typeahead was removed in Bootstrap v3
also fix some "typehead" (sic) typos

Closes #1559
2014-01-10 23:55:02 +01:00
Pawel Kozlowski 6eb9c2a19b docs(modal): clarify that $modal and $modalInstance are not the same
Closes #1528
2014-01-09 18:59:15 +01:00
Pawel Kozlowski b87959ac29 chore(all): switch to AngularJS 1.2 version 2014-01-08 22:19:01 +01:00
Pawel Kozlowski 85cf5b4a6b chore(tests): move test helpers to one place 2014-01-08 22:15:11 +01:00
Chris Chua 40c850bcd8 chore(tabs): Fix tests for AngularJS 1.2
- Use ngBindHtml with $sce as ngBindHtmlUnsafe has been removed

See https://github.com/angular/angular.js/commit/dae694739b9581bea5dbc53522ec00d87b26ae55
2014-01-08 22:04:58 +01:00
Chris Chua ccf5086c01 chore(tooltip): Fix tests for AngularJS 1.2
AngularJS 1.2 introduces separate isolate scopes for directives that
require isolate scopes.

See https://github.com/angular/angular.js/commit/909cabd36d779598763cc358979ecd85bb40d4d7
and https://github.com/angular/angular.js/commit/27e9340b3c25b512e45213b39811098d07e12e3b
2014-01-08 22:04:57 +01:00
Chris Chua 1c20f8fc20 chore(datepicker): Fix tests for Angular 1.2 2014-01-08 22:04:57 +01:00
Chris Chua 19f3c9c257 chore(timepicker): Fix tests for Angular 1.2 2014-01-08 22:04:57 +01:00
Chris Chua b940b068cb chore(alert): Fix test for Angular 1.2
- Since Angular 1.2 is now using the ng-hide class to hide the element,
  it needs to be added into the DOM for styles to be computed.
2014-01-08 22:04:57 +01:00
Chris Chua 7a4f06c4dc chore(tests): Update to AngularJS 1.2 for testing
- Use unminified version for easier debugging
2014-01-08 22:04:57 +01:00
Chris Chua 049cf4a210 chore(modal): fix tests for IE9
Check if transitions are available before attempting to wait for them.

Closes #1537
Closes #1540
2014-01-08 18:52:40 +01:00
Tasos Bekos bcf39efeaf fix(timepicker): add correct type for meridian button
Closes #1541
2014-01-08 18:51:00 +01:00
Chris Chua 1933488ca6 fix(modal): support close animation
Tests now have to wait for animation before checking for open modals.
Tests should actually check for the 'in' class.

Setting up both the transition end handler and a timeout ensures that
the modal is always closed even if there was an issue with the
transition. This was the implementation used by Twitter Bootstrap modal
JS code.

Note that unbinding the transition end event within the event
handler isn't necessary, and, worse is currently buggy in jqLite (see
https://github.com/angular/angular.js/pull/5109 ).

Note that the scope is already destroyed when the dom is removed so the
$destroy call isn't needed.

Closes #1341
2014-01-07 20:26:56 +01:00
Tasos Bekos f75f85af3c chore(demo): fix extra character typo 2014-01-07 17:51:27 +01:00
Pawel Kozlowski e1c9dc0d68 docs(index): clarify Bootstrap CSS compatibility
Closes #1519
2014-01-05 19:40:22 +01:00
Pawel Kozlowski 99267e6028 docs(typeahead): correct gramatical errors 2014-01-04 22:58:41 +01:00
Pawel Kozlowski 090da1941b chore(tests): run tests on IE11 2014-01-04 22:22:23 +01:00
Pawel Kozlowski a8e60e4b16 chore(tests): run tests on IE10 2014-01-03 19:37:08 +01:00
Tasos Bekos da1cf74d53 demo(all): add bower link to download modal
Closes #1515
2014-01-03 19:04:41 +01:00
Jesus Rodriguez 96f474d154 test(carousel): removing stale code
Closes #1502
2014-01-02 19:26:00 +01:00
Chris Chua 51fd006016 demo(tooltip): correct usage of anchor element
Tooltips were nested in anchor elements to get the hyperlink styling
from Bootstrap. This seems like an odd use of anchor elements and we
shouldn't encourage this. Instead, use anchors like actual links that
point to nowhere (#).

Closes #1507
Closes #1509
2014-01-02 19:22:18 +01:00
Chris Chua 278f6963f2 demo(all): add HTML5 doctype
This prevents browsers from following legacy specifications such as what
was discovered on #1507.

Closes #1510
2014-01-02 19:07:26 +01:00
Tasos Bekos ab92f5a721 demo(all): use modal for download process
Closes #1494
2013-12-31 18:12:09 +01:00
Chris Chua 0754ad7b5c fix(modal): leaking watchers due to scope re-use
Previously, the backdropScope was being re-used and each time it was
linked, it would attach more watchers to the scope.

Closes #1491
Closes #1498
2013-12-31 17:59:16 +01:00
Tasos Bekos e986485a6e chore(build): add banner into build files
Closes #1493
2013-12-31 16:34:17 +01:00
Chris Chua 5f8e3e8382 refactor(datepickerSpec): speed up tests
Tests were compiling the element multiple times unnecessarily as it's
done in the root describe's beforeEach.

Introduce describe blocks with no name to encapsulate tests that need
the element to be compiled and separate them from tests that have their
own compilation.

Closes #1499
2013-12-31 16:25:19 +01:00
Chris Chua c0df320151 fix(tooltip): performance and scope fixes
Isolate scope contents should be the same after hiding and showing the
tooltip. The isolate scope's parent should also always be set to the
directive's scope correctly.

fix(tooltip): link on demand

- Calling $digest is enough as we only need to digest the watchers in
  this scope and its children. No need to call $apply.

- Set invokeApply to false on $timeout for popUpDelay

- No need to test for cached reference when tooltip isn't visible as
  the tooltip has no scope.

Closes #1450
Closes #1191
Closes #1455
2013-12-31 16:10:54 +01:00
Jesus Rodriguez c4d0e2a78e test(alert): add more coverage and other changes
Closes #1489
2013-12-30 19:27:49 +01:00
Tasos Bekos ba79abe837 docs(tabs): remove deprecated direction & add missing deselect 2013-12-30 19:13:02 +01:00
Tasos Bekos d9e0f483ae refactor(rating): increase test coverage 2013-12-29 23:01:13 +01:00
Tasos Bekos f56a396dd7 test(pagination): add test for full coverage 2013-12-29 20:45:57 +01:00
Foxandxss 32f0f63872 style(collapse): typo in a comment
s/relaizes/realizes
2013-12-29 19:01:04 +01:00
Chris Chua 96985290b2 chore(tests): add coverage as an option
Knowing what exactly isn't being covered by the tests is more
important than knowing the statistics.

By default, this outputs full HTML reports with indicators of which
lines or branches haven't aren't covered.
2013-12-29 18:58:11 +01:00
Tasos Bekos 20d4efb38b refactor(popover): remove unused dependency injections 2013-12-29 18:13:52 +01:00
Chris Chua 28c85de2ec chore(tests): fix test output on CI
Use reporters in karma.conf.js to avoid confusion in the future.
2013-12-29 18:03:58 +01:00
Chris Chua afd9f36642 test(tabs): typo in basics test 2013-12-29 17:57:19 +01:00
Tasos Bekos c61e6974b2 demo(all): fix bootstrap cdn for plunker 2013-12-28 22:33:53 +01:00
Tasos Bekos aee5cc8aec demo(accordion): pointer cursor for accordion 2013-12-28 22:31:27 +01:00
Foxandxss 0d0375d41a test(accordion): don't attatch accordion to body
As far as I understand, to test sizes like widths or height you need to append your element to the real document. But that `describe` is not running any test with that. My guess is that there was some in the past and that line was forgotten there.
2013-12-28 22:26:46 +01:00
Pawel Kozlowski 6b1ca32e04 chore(release): Starting v0.10.0-SNAPSHOT 2013-12-28 22:23:39 +01:00
Pawel Kozlowski 15e255d7a9 chore(release): v0.9.0 2013-12-28 21:36:26 +01:00
Pawel Kozlowski dc02ad1d03 fix(collapse): fixes after rebase 2013-12-28 21:31:45 +01:00
Thien Pham e0426b90de chore(demo): update demo page for bootstrap3
Adds new header, mobile menu, fastclick, smooth scrolling, and more.

Closes #1243
Closes #1469
2013-12-28 21:27:06 +01:00
Pawel Kozlowski 5d0ca36d34 test(typeahead): clean-up after tests 2013-12-28 21:27:06 +01:00
Justin Hall 444c488d62 feat(modal): added bootstrap3 support 2013-12-28 21:27:06 +01:00
Tasos Bekos 428f147cc9 demo(all): various fixes 2013-12-28 21:27:06 +01:00
Pedro A. Melendez 9613b61bdd fix(timepicker): fix look with bootstrap3
Closes #1285
2013-12-28 21:27:06 +01:00
Justin Hall 6724a7212e feat(timepicker): restyled for bootstrap 3 2013-12-28 21:27:06 +01:00
Kury Kruitbosch a99b3608be fix(tooltip): re-position tooltip after draw
Closes #944
2013-12-28 21:27:06 +01:00
Tasos Bekos 37684330e4 feat(datepicker): update to Bootstrap 3 2013-12-28 21:27:06 +01:00
Pawel Kozlowski eadf934ab6 feat(typeahead): update to Bootstrap 3 2013-12-28 21:27:06 +01:00
Tasos Bekos 5bcff62323 feat(progressbar): update to bootstrap3 2013-12-28 21:27:06 +01:00
Pawel Kozlowski dfc3b0bd58 fix(alert): update template to Bootstrap 3 2013-12-28 21:27:06 +01:00
Tasos Bekos 76b485c261 demo(rating): replace badge with label
Badges in BS3 don't have contextual styles anymore.
2013-12-28 21:27:06 +01:00
Pawel Kozlowski 7e60284e8d feat(rating): update rating to bootstrap3
Closes #1242
2013-12-28 21:27:05 +01:00
Bernd Helzer d221d51748 fix(rating): user glyhicon classes 2013-12-28 21:27:05 +01:00
Justin Hall 458a9bd375 feat(accordion): convert to bootstrap3 panel styling 2013-12-28 21:27:05 +01:00
Chris Chua b0032d688e fix(collapse): Prevent consecutive transitions & tidy up code
Previously, there would be a case where the two transitions would run
as the cancel would asynchronously invoke the reject handler of the
transition which would set the currTransition to undefined even when
the currTransition has been replaced with a new transition.
2013-12-28 21:27:05 +01:00
Pawel Kozlowski 517dff6e45 feat(collapse): make collapse work with bootstrap3
Closes #1240

If starting out collapsed, the expand animation would jump since the `initialAnimSkip` was still `true`.
2013-12-28 21:25:48 +01:00
Tasos Bekos 3db699d79c feat(pagination): support bootstrap3 2013-12-28 21:17:23 +01:00
Justin Hall c409fdcc95 demo(carousel): center images and increase size to full frame 2013-12-28 21:17:23 +01:00
Pawel Kozlowski 1f632b65c0 feat(carousel): some changes for Bootstrap3 2013-12-28 21:17:23 +01:00
Justin Hall dbae55a98b demo(alert): add btn-default class to button 2013-12-28 21:17:23 +01:00
Justin Hall cdc268f56b demo(tooltip): change demo to support bootstrap3 2013-12-28 21:17:23 +01:00
Justin Hall aac3e97f75 demo(popover): fixed button styling for bootstrap 3 2013-12-28 21:17:23 +01:00
William Randol 3199dd8856 feat(tabs): add nav-justified
adds functionality for justifed tabs
http://getbootstrap.com/components/#nav-justified
2013-12-28 21:17:23 +01:00
Justin Hall c141daceb1 demo(tabs): update demo to Bootstrap3 2013-12-28 21:17:23 +01:00
Justin Hall f70081b749 demo(all): style demo for bootstrap3 2013-12-28 21:17:22 +01:00
Jon Jaques a74efa7bc4 demo(all): upgrade project to bs3.0.0-rc2 and get docs looking spiffy 2013-12-28 21:17:22 +01:00
Pawel Kozlowski 3ffe7188a7 chore(release): Starting v0.9.0-SNAPSHOT 2013-12-28 21:15:00 +01:00
Pawel Kozlowski 9205a57874 chore(release): v0.8.0 2013-12-28 20:02:30 +01:00
Chris Chua 54e614a8c7 fix(tooltip): respect animate attribute
Previously, it was only possible to set animation to false with an empty
string and options.

Closes #1418
2013-12-28 14:29:38 +01:00
Pawel Kozlowski 81e014a80e fix(collapse): dont animate height changes from 0 to 0
Closes #1424
2013-12-28 14:08:15 +01:00
Chris Chua 70af344759 chore(test): add test coverage task
Run `grunt test:coverage` to see a the test coverage in the terminal.
2013-12-25 15:35:14 +01:00
Chris Chua 161a99621b test(typeahead): increase coverage of tests 2013-12-24 14:23:51 +01:00
Chris Chua 7515df45b9 fix(carousel): cancel goNext on scope destruction
Discovered after #1451
2013-12-24 11:36:39 +01:00
Chris Chua 0b3999421b refactor(carousel): remove duplicate code
Move go function out of restartTimer as it doesn't need to be re-created
during each interval.
2013-12-23 15:06:53 +01:00
Chris Chua 5b9d929c37 fix(carousel): cancel timer on scope destruction
Closes #1414
2013-12-23 15:06:20 +01:00
Chris Chua c9acebbea2 fix(tabs): make nested tabs work
This reverts commit 220e7b6012.

Revert the capability to set the tab direction. This is no longer a
feature in Bootstrap 3 and breaks nested tabs.

Closes #783
Relates to #659
2013-12-23 12:14:38 +01:00
Chris Chua d6bf79b461 chore(tabs): Add tests for nested tabs
Relates to #783
2013-12-23 12:14:38 +01:00
Pawel Kozlowski db73cb3334 refactor(tabs): remove unused tabs directive 2013-12-23 10:19:50 +01:00
Chris Chua 7a5b42f91c test(tabs): get test coverage to 100%
- Add one removal of a non-last tab to test one last branch
- This excludes the deprecation message for the tabs directive.
2013-12-23 10:13:38 +01:00
plainkeyman 672a557ab2 fix(modal): properly animate backdrops on each modal opening
Closes #1267
2013-12-21 20:32:06 +01:00
Mathieu d168589a92 docs(typeahead): show custom template implementation
Closes #1441
2013-12-21 19:40:28 +01:00
matiboy d7bf5c119d docs(typeahead): add async version of the demo 2013-12-21 12:44:02 +01:00
Pawel Kozlowski e76512fabb feat(modal): add modal-open class to body on modal open
Closes #1254
2013-12-21 11:03:25 +01:00
Pawel Kozlowski 709e679c5b fix(modal): focus freshly opened modal
Closes #1187
2013-12-20 17:30:40 +01:00
Pawel Kozlowski ea053b1991 revert(typeahead): prevent accidental form submission on ENTER
Closes #1298
This reverts commit 253c49ff26.
2013-12-20 16:40:56 +01:00
Brian McKinney dd415a9800 fix(modal): Grab reference to body when it is needed in lieu of when the factory is created 2013-12-20 16:04:41 +01:00
Tasos Bekos 2db1ba56bc refactor(buttons): remove some code duplication 2013-12-20 09:36:36 +01:00
Ainur dd8eac2289 feat(typeahead): add typeahead-append-to-body option 2013-12-20 09:28:30 +01:00
Tasos Bekos 1fbcb5d6c9 fix(datepicker): remove edge case position updates
Closes #1296
2013-12-18 21:46:16 +01:00
dmitry-dedukhin 48955d692b fix(datepicker): remove datepicker's popup on scope destroy 2013-12-16 16:46:50 +01:00
Tasos Bekos 41bea46b55 refactor(alert): move logic to controller & add tests
* Add missing tests that `close` button is actually visible
   Tests were passing even if link function was empty.
2013-12-14 11:08:57 +01:00
Tasos Bekos 3fe7aa8cec fix(tooltip): unbind element events on scope destroy
Closes #1339
Closes #1346
Closes #1400
2013-12-14 10:31:15 +01:00
Joonas Muhonen 5dd9823835 fix(tooltip): support IE8 2013-12-14 09:55:00 +01:00
Tasos Bekos 6b1c68fb96 fix(datepicker): fire ngChange on today/clear button press
Closes #1379
2013-12-10 09:44:54 +01:00
Tasos Bekos 93cd0df8d4 fix(datepicker): set default zero time after no date selected
Closes #1065
2013-12-09 13:38:26 +01:00
Tasos Bekos 60515ae16f fix(tooltip): update tooltip content when empty
Closes #1348
2013-12-09 13:24:22 +01:00
Christopher Bebry 40b80c3b31 docs(pagination): spelling corrections
Closes #1358
2013-12-06 19:49:57 +01:00
Tasos Bekos 365573ab24 feat(progressbar): add max attribute & support transclusion
* General refactor. Move logic to controller.
 * Remove `onFull` & `onEmpty` handlers.
 * Remove automatic types and stacked types.
 * `progress` & `bar` transclude content to support text & extra elements.

BREAKING CHANGE: The onFull/onEmpty handlers & auto/stacked types have been removed.

  To migrate your code change your markup like below.

  Before:

  <progress percent="var" class="progress-warning"></progress>

  After:

  <progressbar value="var" type="warning"></progressbar>

  and for stacked instead of passing array/objects you can do:

  <progress><bar ng-repeat="obj in objs" value="obj.var" type="{{obj.type}}"></bar></progress>
2013-11-30 21:36:56 +01:00
Sterling Camden d64f4a976b fix(modal): put backdrop in before window
Closes #1313
2013-11-29 18:45:05 +01:00
Tasos Bekos 8b1ab79a83 feat(timepicker): default meridian labels based on locale
Closes #1150
2013-11-29 11:34:40 +01:00
Tasos Bekos 79f836c394 refactor(accordion): remove unused dependency injections 2013-11-28 09:21:35 +01:00
Tasos Bekos 4d158e0dd9 feat(datepicker): option whether to display button bar in popup 2013-11-27 16:47:32 +01:00
Tasos Bekos 9ec21286ea fix(accordion): correct is-open handling for dynamic groups
Closes #1297
2013-11-26 20:15:02 +01:00
Pawel Kozlowski 2abadcad2c chore(release): Starting v0.8.0-SNAPSHOT 2013-11-26 20:08:49 +01:00
Pawel Kozlowski 9dbc2390f2 chore(release): v0.7.0 2013-11-22 20:33:52 +01:00
Tasos Bekos c7b097b5ab test(alert): fix wrong assertion test for close button 2013-11-22 19:13:36 +01:00
Murray Smith 6efd6745b2 docs(modal): fix typo 2013-11-21 19:32:08 +01:00
Sean Kenny 0e9f9980ed fix(typeahead): support IE8 2013-11-18 20:03:00 +01:00
Pawel Kozlowski 0d810acdb9 fix(tooltip): tackle DOM node and event handlers leak
Closes #1133
2013-11-17 21:13:40 +01:00
Pawel Kozlowski 127ab70dc3 style(all): rename test files to keep extensions consistent 2013-11-17 12:42:01 +01:00
Pawel Kozlowski d290fd2b54 refactor(modal): remove unused templates 2013-11-13 21:06:59 +01:00
Pawel Kozlowski b3b2a9845b docs(README): info on building a subset of modules 2013-11-13 19:30:59 +01:00
Pierre Tardy a7bd3169a9 chore(readme): add a note in readme about custom build 2013-11-13 19:25:20 +01:00
Pawel Kozlowski 9eca35a8de fix(collapse): add the "in" class for expanded panels
Closes #1192
2013-11-11 19:17:11 +01:00
Pawel Kozlowski a72c635c76 fix(collapse): remove element height watching
For unclear reasons the directive was watching DOM element's height
which incurs performance penalty. Normally this watching shouldn't be
necessery as collapsible elements should get height: auto;

Closes #1222
2013-11-11 19:03:37 +01:00
Pawel Kozlowski fd21214d42 fix(typeahead): evaluate matches source against a correct scope
Closes #1238
2013-11-09 19:20:33 +01:00
Utkarsh Upadhyay 968e54072b fix(position): correct positioning for SVG elements
Bootstrap tooltips calculate the `width` and `height` of elements
using first getBoundingClientRect and fall back to `offsetWidth` and
`offsetHeight` if it is not available:

https://github.com/twbs/bootstrap/blob/master/js/tooltip.js#L297

This fixes a problem with tooltips/popovers on SVG elements in
Firefox: https://github.com/twbs/bootstrap/issues/5956

This change mimics that behavior.

Closes #1225
2013-11-03 21:22:37 +01:00
Tyler Akins 5a01a6960c docs(modal): fix double "a" typo
Closes #1214
2013-10-28 20:34:23 +01:00
metimus 570dba904f fix(datepicker): properly handle showWeeks config option
Closes #1132
2013-10-27 19:29:33 +01:00
Pawel Kozlowski 253c49ff26 fix(typeahead): prevent accidental form submission on ENTER 2013-10-27 19:22:17 +01:00
Pawel Kozlowski 85647c9b64 docs(README): fix markup 2013-10-27 18:55:45 +01:00
scarletsky cc2df9a02d docs(README): add info about templates customization 2013-10-27 18:51:40 +01:00
Pawel Kozlowski 4801564390 refactor(alert): clean-up unused variables 2013-10-27 18:00:12 +01:00
Martin Cortez ee67a9c843 test(typeahead): corrects typos
Closes #1209
2013-10-26 10:48:28 +02:00
Jonas 104bdd1be8 feat(dropdownToggle): disable dropdown when it has the disabled class 2013-10-11 20:02:37 +02:00
stan-z 78a1e9d749 fix(datapicker): set popup initial position in append-to-body case
Set the initial position offsets of the datepicker popup element in case of appended to 'body'.

Todo: refresh the position on parent elements resize.
2013-10-11 18:59:37 +02:00
sohai 5d9bd0584e feat(tooltip): add ability to enable / disable tooltip 2013-10-11 13:22:57 +02:00
Pawel Kozlowski cf5c27ae8f fix(tooltip): hide tooltips when content becomes empty
Closes #875
2013-10-08 22:06:14 +02:00
Pawel Kozlowski 0149eff61e fix(typeahead): fix loading callback when deleting characters
Closes #1140
2013-10-08 20:51:23 +02:00
Caitlin Potter 0cdc4609d7 feat(datepicker): datepicker-append-to-body attribute
Attribute / option specifies where in the DOM to place the datepicker
popup elements.

If this option evaluates to 'true', the datepicker popup elements are
appended to 'body'. Otherwise, they follow the directive element.
2013-10-04 19:35:16 +02:00
Josh Clanton 4540476fa3 fix(datapicker): some IE8 compatibility improvements 2013-10-04 18:42:36 +02:00
Arve Seljebu e01bddf14d docs(README): add build instructions for explicit modules 2013-10-04 17:58:53 +02:00
Tasos Bekos 8ecf93edb0 fix(pagination): handle extreme values for total-items
Closes #1104
2013-10-02 12:41:09 +02:00
sebastian 53709f0ff6 fix(timepicker): use html5 for input elements 2013-10-01 16:40:57 +02:00
Tasos Bekos cf228827a5 chore(demo): document BS's supported version & link to dependencies
Closes #1093
2013-09-29 15:23:06 +02:00
Tasos Bekos 81164dae38 fix(pagination): fix altering of current page caused by totals change
Closes #1079
2013-09-29 15:20:16 +02:00
J Bruni 58cd74bc09 refactor(datepicker): removed duplicated css class in a template 2013-09-29 15:16:20 +02:00
Tasos Bekos aa3eaa9148 feat(datepicker): dynamic date format for popup
Closes #1071
2013-09-27 13:47:46 +02:00
Caitlin Potter 473838677f docs(README): Add david-dm.org devDependencies status image 2013-09-27 09:26:57 +02:00
Chris Chua a08173ec79 fix(tabs): initial tab selection
Closes #834, Fixes #747

- Avoid re-initializing `tab.active`
- `setActive` only when all `tab.active` are set up (on the next
  digest cycle)

Before I go to explain, there are up to two expressions that indicate
whether a tab is active:

  1. `active` variable in the isolate scope of the tab directive
  2. The expression from the active attribute (`attrs.active`) if it
     is set, I'll call this `getActive`, as that's the variable that
     refers to it.

During initial linking (adding of tabs), the `active` variable in the
tab's isolate scope tracks the active tab. When the first tab is
added, it's `active` is set to true since there's no way to know if
subsequent tabs are active since they haven't been added yet. As such,
at this point, it is not meaningful to set assign the `getActive`
with the value of `active`. At least not until all the tabs have been
added. Hence, a good time would be to wait until the next $digest
cycle.

A watcher is called asynchronously after initialization even if there
is no change on the expression's value.

As such, we can leave that to the watcher for the `active` expression
to initialize getActive by calling setActive during its initlization
cycle.

However, there is a chance (if the $digest cycles and planets
align...) that the `active` variable gets initialized a second time
using the `getActive` (in the watcher for `getActive`). Since we're
already setting `active` to `getActive`, and the `active` variable
should now be carrying the *truth*. Avoid this re-initialization.
2013-09-23 08:14:57 -04:00
mrmrs 509357e76e style(all): remove unneccessary px declarations from values set to 0 2013-09-23 08:53:06 +02:00
Pawel Kozlowski e67dfbcda2 chore(demo): fix custom build link
Closes #1054
2013-09-22 13:54:41 +02:00
Pawel Kozlowski d1f9453003 fix(typeahead): don't show matches if an element is not focused
Closes #964
2013-09-22 13:03:16 +02:00
Tasos Bekos c6ba8d7f31 feat(datepicker): add i18n support for bar buttons in popup
Closes #777
2013-09-21 19:03:16 +03:00
Pawel Kozlowski dde804b6b6 fix(typeahead): remove popup flickering
Closes #1011
2013-09-19 20:13:37 +02:00
Tasos Bekos 157f614a82 fix(accordion): assign is-open to correct scope
Closes #1034
2013-09-19 19:40:07 +02:00
Ian Joseph Wilson 006986db1d fix(typeahead): do not set editable error when input is empty
Closes #1038
2013-09-19 16:11:41 +02:00
Tasos Bekos 0b5ca7812e refactor(tabs): remove unused dependency injections
Closes #1009
2013-09-19 14:10:12 +02:00
Till Kothe a5577f857b docs(modal): add template parameter to documentation
Closes #1026
2013-09-19 14:04:02 +02:00
Eddie Monge Jr 5723a9e18c style(buttons): cleanup button formatting
Normalize spacing issues
2013-09-13 20:34:29 +02:00
Tasos Bekos 6a2f481477 refactor(rating): compatibility with AngularJS 1.2 2013-09-13 19:35:14 +02:00
Tasos Bekos 0e3e295ccc refactor(pagination): change the way num-pages is assigned
Closes #976
2013-09-11 18:54:11 +02:00
Pawel Kozlowski e55c2de3e1 fix(modal): correctly close modals with no backdrop
backdropDomEl was not initialised if only modal without backdrop was opened.

Closes #974
Closes #979
2013-09-10 19:52:42 +02:00
Jim Rollenhagen 08d8b21d63 fix(tooltip): restore html-unsafe compatibility with AngularJS 1.2 2013-09-10 19:31:33 +02:00
Pawel Kozlowski 7c5cb18f24 chore(release): Starting v0.7.0-SNAPSHOT 2013-09-09 19:26:57 +02:00
Pawel Kozlowski 3e5f796442 chore(release): v0.6.0 2013-09-08 18:49:49 +02:00
Pawel Kozlowski 8e7fbf06a5 fix(modal): allow replacing object with default options
Closes #967
2013-09-08 18:17:45 +02:00
Pawel Kozlowski 8d153acbf8 feat(modal): expose $close and $dismiss options on modal's scope
Closes #966
2013-09-08 18:09:56 +02:00
Pawel Kozlowski 0caea91744 chore(angular): update AngularJS to 1.0.8 2013-09-07 19:45:18 +02:00
Pawel Kozlowski 7fce2fe82f fix(modal): backdrop should cover previously opened modals
Closes #922
Closes #931
2013-09-07 16:16:18 +02:00
Pawel Kozlowski 015625d1ae feat(modal): add support for custom window settings
Closes #892
2013-09-06 13:32:14 +02:00
Pawel Kozlowski 37777caf9d docs(README): clarify IE8 support
Closes #901
2013-09-04 19:48:05 +02:00
Pawel Kozlowski 82532d1b74 fix(modal): opening a modal should not change default options
Closes #935
2013-09-03 21:34:26 +02:00
Tasos Bekos dd99f35d93 fix(datepicker): use $setViewValue for inner changes
Closes #855
2013-09-03 20:18:56 +02:00
Tasos Bekos 1f89fd4bd5 fix(timepicker): add type attribute for meridian button 2013-09-03 20:08:02 +02:00
Pawel Kozlowski 7589339330 fix(typeahead): remove dependency on ng-bind-html-unsafe
Closes #813
2013-09-03 20:01:36 +02:00
Pawel Kozlowski c0215c8be9 chore(build): update custom build to use $modal service
Closes #927
2013-09-01 20:18:47 +02:00
Romain Laï-King 9aecd4ed8e fix(position): fallback for IE8's scrollTop/Left for offset 2013-08-27 21:27:34 +02:00
Chris Chua 5f9e270d0a fix(typeahead): keep pop-up on clicking input
Also, keep reference to event listener to unbind when scope is
destroyed. (Memory leak)
2013-08-27 20:58:51 +02:00
Chris Chua 45dd9be184 fix(typeahead): highlight return match if no query
This makes the highlighter behave more consistently like other filters.

It also makes it more useful as an empty query doesn't result in an
empty result.
2013-08-27 19:56:07 +02:00
Tasos Bekos 87b4aa7457 refactor(rating): moving default class names back to template 2013-08-27 19:39:46 +02:00
kfb ff9d969ec4 fix(modal): ie8 fix after $modal rewrite 2013-08-27 19:34:58 +02:00
Sterling Camden d870f21297 fix(modal): insert backdrop before modal window 2013-08-25 13:03:00 +02:00
Pawel Kozlowski 21d2ecb839 docs(README): clarify IE8 support 2013-08-24 18:35:20 +02:00
Tasos Bekos 20ab01ad10 feat(rating): add support for custom icons per instance 2013-08-24 18:21:51 +02:00
Tasos Bekos e55d906381 feat(pagination): total-items & optional items-per-page API
Closes #820.

BREAKING CHANGE: API has undergone some changes in order to be easier to use.
 * `current-page` is replaced from `page`.
 * Number of pages is not defined by `num-pages`, but from `total-items` &
  `items-per-page` instead. If `items-per-page` is missing, default is 10.
 * `num-pages` still exists but is just readonly.

  Before:

  <pagination num-pages="10" ...></pagination>

  After:

  <pagination total-items="100" ...></pagination>
2013-08-24 18:12:48 +02:00
Tasos Bekos 9af6f96e27 fix(tabs): evaluate vertical on parent scope
Closes #849.
2013-08-24 18:09:09 +02:00
Pawel Kozlowski d7a48523e4 feat(modal): rewrite $dialog as $modal
BREAKING CHANGE:
* `$dialog` service was refactored into `$modal`
* `modal` directive was removed - use the `$modal` service instead

Check the documentation for the `$modal` service to migrate from `$dialog`
2013-08-24 17:33:45 +02:00
Pawel Kozlowski 80cef61475 fix(typeahead): plug in front of existing parsers
Closes #863
2013-08-24 11:13:24 +02:00
Pawel Kozlowski ed5f97902f chore(test): remove IE10 tests 2013-08-22 19:46:36 +02:00
Pawel Kozlowski 17163c22dd fix(tooltip): remove placement='mouse' option
Closes #832

BREAKING CHANGE:

The placment='mouse' is gone with no equivalent
2013-08-17 19:01:45 +02:00
Tasos Bekos ed3700be00 refactor(rating): move logic to controller 2013-08-17 11:57:43 +02:00
Tasos Bekos ce226fa65d demo(all): remove jQuery dependency
* Replace select2 in custom build with checkbox buttons.
2013-08-16 17:50:52 +02:00
Pawel Kozlowski 8620aedba9 docs(all): add info about styling cursors for <a> tags
Closes #752
Closes #816
2013-08-15 19:22:39 +02:00
Pawel Kozlowski 366e0c8a1f fix(typeahead): set validity flag for non-editable inputs
Closes #806
2013-08-15 18:24:25 +02:00
Michał Michałowski d34f2de189 fix(carousel): correct reflow triggering on FFox and Safari 2013-08-15 12:21:26 +02:00
Louis Sivillo d3da8b78fd fix(dialog): reintroduced dialogOpenClass option
This option represents  class which is added to the body when the dialog is open.
It was present before in twitter bootstrap, then removed in 2.3.0,
but then recently reintroduced in 3.0

Closes #798
2013-08-13 19:36:16 +02:00
Swiip bf30898da2 fix(datepicker): compatibility with angular 1.1.5 and no jquery
Closes #760
2013-08-10 19:32:42 +02:00
Tasos Bekos b08e993fb4 feat(timepicker): plug into ngModel controller
Closes #773
Closes #785
2013-08-10 14:25:44 +02:00
Pawel Kozlowski 5de71216de fix(typeahead): fix label rendering for equal model and items names 2013-08-10 12:02:20 +02:00
Pawel Kozlowski 64df05e367 docs(typeahead): correct default value for the editable attribute 2013-08-08 19:24:01 +02:00
Arnaud Lachaume aac4a0dd4a fix(tabs): add DI array-style annotations 2013-08-08 19:04:25 +02:00
Jérémy DECOOL 7fdf73016b docs(typeahead): document all allowed attributes 2013-08-06 19:21:57 +02:00
Sergey R a89be34576 docs(CHANGELOG): typo fix 2013-08-06 19:19:36 +02:00
Dan Wahlin d474824b7c fix(datepicker): correctly manage focus without jQuery present
The element.focus() will throw an error since the object needs to be unwrapped first.
Should be:  element[0].focus() at a minimum to unwrap the jqlite object since it doesn't expose focus().

Closes #758
2013-08-05 19:30:33 +02:00
Pawel Kozlowski f6aa26bd07 demo(datepicker): fix tag name in an example 2013-08-05 19:12:33 +02:00
Pawel Kozlowski 290b268384 chore(release): Starting v0.6.0-SNAPSHOT 2013-08-04 18:29:29 +02:00
Pawel Kozlowski ceb396f716 chore(release): v0.5.0 2013-08-04 17:31:19 +02:00
Tasos Bekos dab18336e4 feat(datepikcer): ngModelController plug & new datepikcerPopup
* `ngModelController` integration
 * `datepikcerPopup` directive ti use with inputs
 * invalid & disabled validation
 * add `min` / `max` into configuration

Closes #612
2013-08-04 16:48:06 +02:00
Pawel Kozlowski a742690b65 demo(pagination): correct quotes in pagination demo 2013-08-04 13:13:22 +02:00
Paul Gibbs d50b0547f8 fix(tooltip): bind correct 'hide' event handler
If a user defines a tooltip-trigger attribute, this ensures the correct event handlers is used to hide the tooltip.

Fixes a bug where if a user sets both a default trigger using the tooltip provider, and then tries to override with an attribute, the wrong 'hide' event was being used.
2013-08-03 21:14:29 +02:00
Pawel Kozlowski 4fd5bf4345 fix(tooltip): correctly handle initial events unbinding
Closes #750
2013-08-03 18:27:20 +02:00
Pawel Kozlowski 58e8ef4f87 fix(tooltip): triggers should be local to tooltip instances
Closes #692
2013-08-03 12:59:28 +02:00
Tasos Bekos f45815cb11 fix(pagination): use interpolation for text attributes
Closes #696

BREAKING CHANGE: The 'first-text', 'previous-text', 'next-text' and 'last-text'
  attributes are now interpolated.

  To migrate your code, remove quotes for constant attributes and/or
  interpolate scope variables.

  Before:

  <pagination first-text="'<<'" ...></pagination>

  and/or

  $scope.var1 = '<<';
  <pagination first-text="var1" ...></pagination>

  After:

  <pagination first-text="<<" ...></pagination>

  and/or

  $scope.var1 = '<<';
  <pagination first-text="{{var1}}" ...></pagination>
2013-08-01 13:39:19 +02:00
Tasos Bekos 25caf5fb83 fix(datepicker): add type attribute for buttons 2013-08-01 12:38:28 +02:00
Andy Joslin ba1f741dff fix(tabs): if tab is active at start, always select it
Closes #648, #676
2013-07-27 14:23:18 -04:00
Pawel Kozlowski a51c309ea8 docs(typeahead): clarify subset of select's syntax used
Closes #715
Closes #506
2013-07-27 19:45:40 +02:00
Lucas Galfasó 220e7b6012 feat(tabs): add the ability to set the direction of the tabs
Add the ability to set the direction of the tabs, the possible
values are 'right', 'left' and 'below'. If no direction is defined
the tabs are rendered on the top as they do now

Closes #659
2013-07-27 12:35:20 -04:00
Pawel Kozlowski d9e5bc9e8d demo(all): sort directives alphabetically 2013-07-27 10:01:21 +02:00
Pawel Kozlowski 5ffae83d66 feat(typeahead): expose index to custom templates
Closes #699
2013-07-26 19:35:39 +02:00
Vicki fe47c9bb61 feat(tabs): added onDeselect callback, used similarly as onSelect 2013-07-25 21:25:48 +02:00
Tasos Bekos 682ae66e36 refactor(pagination): keep it DRY between pagination & pager 2013-07-25 21:18:05 +02:00
Nick Serebrennikov 8d904867f1 docs(README): fix typo 2013-07-25 21:16:36 +02:00
Pawel Kozlowski 8278f53b88 test(typeahead): verify initial rendeirng with complex labels
Closes #706
2013-07-25 20:58:54 +02:00
Pawel Kozlowski b21f70aa59 chore(build): add demo as a valid commit msg qualifier 2013-07-23 21:48:11 +02:00
Pawel Kozlowski c74684fe9b docs(accordion): demonstrate usage of accordion-heading
Closes #690
2013-07-23 21:38:59 +02:00
Pawel Kozlowski 93a82af0e4 fix(popover): correctly position popovers appended to body
Closes #682
2013-07-23 19:38:47 +02:00
Pawel Kozlowski 56f624a263 fix(popover): don't unbind event handlers created by other directives
Closes #456
2013-07-23 19:14:28 +02:00
Pedro A. Melendez 8dc92afa74 fix(timepicker): added wheel event to enable mousewheel on Firefox
Closes #669
2013-07-23 18:57:52 +02:00
Tasos Bekos b1fa7bb89a fix(pagination): handle currentPage number as string 2013-07-23 18:49:37 +02:00
Pawel Kozlowski 3e30cd94a4 feat(buttons): support dynamic true / false values in btn-checkbox
Closes #666
2013-07-16 19:53:48 +02:00
Pawel Kozlowski 63ae7e122d fix(tooltip): fix positioning inside scrolling element
Closes #533
2013-07-13 18:01:05 +02:00
Andy Joslin 360cd5ca95 fix(tabs): make tabs added with active=true be selected 2013-07-08 15:45:50 -04:00
Andy Joslin 224bc2f599 fix(tabs): fix tab content compiling wrong (Closes #599, #631, #574)
* Before, tab content was being transcluded before the tab content area
 was ready. This forced us to disconnect the tab contents from the DOM
 temporarily, then reocnnect them later. This caused a lot of problems.
* Now, neither the tab content or header are transcluded until both
 the heading and content areas are loaded. This is simpler and fixes
 many weird compilation bugs.
2013-07-08 14:37:07 -04:00
Pawel Kozlowski f5b37f68de refactor(dialog): remove dead code 2013-07-08 19:08:17 +02:00
Pawel Kozlowski e2238174d2 feat(typeahead): support custom templates for matched items
Closes #182
2013-07-06 17:44:20 +02:00
Pawel Kozlowski 624fd5f565 fix(typeahead): correctly close popup on match selection 2013-07-06 17:29:26 +02:00
Pawel Kozlowski 4da17a4418 docs(typeahead): demo how to limit number of matches 2013-07-05 20:31:56 +02:00
Stefan Valentin 90a8aa79c8 fix(typeahead): fixed waitTime functionality
Closes #573
2013-07-05 20:24:44 +02:00
Paul Chechetin a3890e753b docs(dialog): add forgotten options 2013-07-02 18:50:17 +02:00
Paul Chechetin 38050bb624 docs(CONTRIBUTING): fix typo 2013-07-01 20:59:55 +02:00
Tasos Bekos 566bdd1641 fix(datepicker): handle correctly min/max when cleared 2013-06-30 17:41:37 +02:00
Pawel Kozlowski 1c990397df test(typeahead): activate all tests 2013-06-30 17:31:41 +02:00
Pawel Kozlowski ea1e858a49 fix(typeahead): separate text field rendering and drop down rendering
Closes #240
Closes #274
2013-06-30 17:25:10 +02:00
Pawel Kozlowski c4e169cbb7 fix(typeahead): properly render initial input value
Closes #591
2013-06-30 12:57:07 +02:00
Pawel Kozlowski d2df0b35ae fix(typeahead): play nicelly with existing formatters 2013-06-30 12:57:04 +02:00
Pawel Kozlowski 5ddd01f56d test(typeahead): re-organize tests 2013-06-30 12:57:02 +02:00
Pawel Kozlowski 7e178a38ce chore(build): activate multiple browsers on Jenkins-CI
Closes #595
2013-06-30 12:50:57 +02:00
Tasos Bekos 60619d511b fix(rating): evaluate max attribute on parent scope 2013-06-29 14:12:49 +03:00
Tasos Bekos 64fff6761e refactor(rating): add helpers to access stars in tests 2013-06-29 12:11:51 +03:00
Sean Desmond 5b1115e3f6 feat(rating): added onHover and onLeave. 2013-06-29 11:25:00 +03:00
Andy Joslin 015913259b style(tabs): remove unused attribute from template 2013-06-28 14:57:35 -04:00
Andy Joslin 8868f236ee fix(tabs): Make tabset template correctly use tabset attributes (#584)
* replace is now set to true in the tabset directive options
2013-06-28 14:57:23 -04:00
Andy Joslin be7ecff01c fix(tabs): make tab contents be correctly connected to parent (#524)
* Make tab contents be compiled into outer scope after being appended to
tab-pane elements.
2013-06-28 14:55:10 -04:00
Pawel Kozlowski b867538979 chore(demo): fix plunker link
Closes #563
2013-06-27 19:09:21 +02:00
Tasos Bekos ee7417071d fix(timepicker): prevent date change 2013-06-25 22:42:29 +03:00
Andy Joslin 1fb30d1b62 style(CHANGELOG): Highlight code blocks in breaking changes 2013-06-24 17:30:42 -03:00
Andy Joslin 86243cb2e0 style(CHANGELOG): Fix code blocks in breaking changes 2013-06-24 17:25:23 -03:00
Pawel Kozlowski 9291aaa884 chore(release): Starting v0.5.0-SNAPSHOT 2013-06-24 22:20:25 +02:00
Pawel Kozlowski 23a32265ee chore(release): v0.4.0 2013-06-24 21:49:37 +02:00
Pawel Kozlowski cd889b60b6 chore(build): split release process into steps 2013-06-24 21:49:03 +02:00
Joe Grund 9246905acc fix(tooltip): make sure tooltip scope is evicted from cache
This fix makes sure the tooltip.$scope is cleared from angular.element.cache when $destroy is called, preventing a memory leak.

Closes #484
2013-06-24 21:20:25 +02:00
mokesmokes 3fcb70f0f6 fix(carousel): fix error with deleting multiple slides at once 2013-06-24 12:21:41 -04:00
Josh David Miller 6a4527b7ea docs(tooltip): add $tooltipProvider docs
Until now, the $tooltipProvider has been an undocumented feature, but as
there are now several options requested by the community at large, it is
finally included in the documentation.
2013-06-24 11:44:18 +02:00
Josh David Miller dfa53155bf feat(tooltip): add custom trigger support
The $tooltipProvider now allows extending the default set of open and
close trigger mappings.

Closes #382.
2013-06-24 11:43:26 +02:00
Josh David Miller d08962634b feat(tooltip): add *-append-to-body attribute
The tooltip and popover directives (through the $tooltip service) now
support using an attribute in addition to the provider to set a
particular tooltip or popover to use $body as the container for the
popup element rather than the directive element's parent.

Closes #395.
2013-06-24 11:42:31 +02:00
_pants ace7bc60e5 feat(tooltip): Added mouse placement option
Adds a mouse() method to the $position service API to return the current
mouse position. The $tooltip API has been changed to allow using this
value to set the position of the tooltip element. The top left corner of
the element will be at the cursor position.
2013-06-23 10:18:19 -07:00
Pawel Kozlowski 56fd692e38 chore(build): various fixes to the changelog task 2013-06-22 16:26:58 -04:00
Andy Joslin 465ad140c3 refactor(carousel): make optional active binding more efficient 2013-06-22 12:14:08 -04:00
Andy Joslin 311ffcb9e5 docs(carousel): add ng-docs, update demo 2013-06-22 12:05:30 -04:00
Andy Joslin 17d6c3b58c fix(carousel): make slide 'active' binding optional 2013-06-22 12:05:21 -04:00
mokesmokes 5f895c13ec feat(carousel): add option to prevent pause
sometimes we want the carousel to spin even if the mouse hovers over it. Added an option for an optional attribute, doesn't break current templates
2013-06-22 11:24:23 -04:00
tbekos d952647565 feat(pagination): add pager directive 2013-06-21 19:50:05 +02:00
Nils Wisiol 88c94ee681 fix(tooltip): support of custom $interpolate.startSymbol 2013-06-21 19:44:17 +02:00
Tasos Bekos 58efec801c fix(progressbar): user percent attribute instead of value.
Closes #535. Problem with IE10.

BREAKING CHANGE: The 'value' is replaced by 'percent'.

  Before:

  <progress value="..."></progress>

  After:

  <progress percent="..."></progress>
2013-06-21 19:41:12 +02:00
Nishes Joshi 25f6e55c3c fix(accordion): Allow accordion heading directives as attributes.
Closes #540
2013-06-21 19:07:26 +02:00
Pawel Kozlowski e63ebbaf20 refactor(buttons): use toggleClass instead of add/remove class 2013-06-15 22:41:18 +02:00
Pawel Kozlowski e8c5b548c7 feat(buttons): support dynamic values in btn-radio 2013-06-15 22:41:13 +02:00
Pawel Kozlowski 9c6240914e refactor(buttons): use $render instead of model $watch 2013-06-15 22:41:09 +02:00
Łukasz Żak 853199e0da docs(CONTRIBUTING): correct 3rd level list tab
Before changes it was on the same level as text above
2013-06-14 19:30:56 +02:00
Andy Joslin 356cfb577d chore(build): Add 'enforce' task, custom changelog template 2013-06-09 21:18:36 +02:00
Andy Joslin 201fdf8318 chore(docs): Start grunt-ngdocs 2013-06-09 21:18:32 +02:00
Andy Joslin bb523cd760 chore(): Add release task 2013-06-09 21:18:29 +02:00
Pawel Kozlowski 6c8219cdd0 refactor(dropdownToggle): remove unused variables 2013-06-09 20:37:50 +02:00
tbekos 9bc5207b2c feat(timepicker): add timepicker directive 2013-06-09 14:33:36 +02:00
tbekos e1bff6b703 fix(pagination): bind *-text attributes
BREAKING CHANGE: The 'first-text', 'previous-text', 'next-text' and 'last-text'
  attributes are now binded to parent scope.

  To migrate your code, surround the text of these attributes with quotes.

  Before:

  <pagination first-text="<<" ...></pagination>

  After:

  <pagination first-text="'<<'" ...></pagination>
2013-06-09 12:28:08 +02:00
tbekos 53e0a39f71 feat(tabs): add support for other navigation types, like 'pills' 2013-06-09 12:08:49 +02:00
Pawel Kozlowski 497ba15f4b docs(README): update TDD documentation after build changes 2013-06-09 11:15:56 +02:00
Pawel Kozlowski 7f35a3f2e7 feat(typeahead): support wait-ms option 2013-06-08 21:42:50 +02:00
Pawel Kozlowski db366a89c2 revert($dialog): revert handling of location change events 2013-06-08 20:37:12 +02:00
Charles 04a21e33b0 fix(typeahead): return focus to the input after selecting a suggestion
Currently focus is lost if you mouse click on the suggestions model instead of using the keyboard. This keeps the focus.
2013-06-08 12:18:40 +02:00
Pawel Kozlowski 67e9d23a25 refactor(typeahead): avoid string manipulation for DOM elements 2013-06-08 12:00:26 +02:00
Pawel Kozlowski 91ac17c9ed feat(typeahead): support typeahead-on-select callback
Closes #433
2013-06-08 11:43:24 +02:00
Pawel Kozlowski 5f7f307995 demo(*): remove a dead link 2013-06-05 19:15:01 +02:00
Gias Kay Lee 1d19663f27 fix(carousel): do not allow user to change slide if transitioning 2013-05-30 10:00:22 -04:00
tbekos 88d17a75dc feat(tabs): add support for vertical option 2013-05-30 09:41:02 -04:00
Pawel Kozlowski c2e8d38899 demo(*): fix the link to the ui-router project
Closes #476
2013-05-29 20:29:26 +03:00
tbekos 2b78dd16ab feat(tabs): support disabled state 2013-05-24 12:59:16 +03:00
tbekos c690b834a7 refactor(datepicker): inject dateFilter instead of $filter 2013-05-23 21:44:58 +02:00
tbekos a023d082b3 feat(pagination): option for different mode when maxSize
* Allow user to specify if current page is rotated, moving the left/right
   limit, or page is moving between page groups.
2013-05-22 12:45:20 -04:00
Pawel Kozlowski b0745c8e05 chore(*): normalize line endings
Closes #423
2013-05-20 21:42:16 +02:00
Amir H. Hajizamani 48dac234c3 style(dialog): use double quotes around HTML attribute value 2013-05-20 18:54:00 +02:00
PowerKiKi 421ef0eb73 docs(dialog): document dialogFadere option instead of non-existing modalFade option 2013-05-15 18:42:31 +02:00
Pawel Kozlowski 32d298443d demo(modal): Use 'h3' tag in template instead of 'h1' 2013-05-13 21:04:27 +02:00
adam77 06081e815c style(modal): Use 'h3' tag in template instead of 'h1' 2013-05-13 08:23:17 -04:00
tbekos 30a00a0773 feat(datepicker): add datepicker directive
Closes #366
2013-05-11 20:44:07 +02:00
Pawel Kozlowski f009b23f2d fix(dialog): remove dialogOpenClass to get in line with v2.3 2013-05-11 20:25:13 +02:00
Josh David Miller 3e5a58e54c fix(tooltip): tooltips will hide on scope.$destroy
When an element on which the tooltip is applied is destroyed (along with
its scope), the tooltip popup will now be closed if it was open.

Also refactored the $locationChangeSuccess binding as well to not waste
a run of `hide()` unless the tooltip was already open, following the
same pattern used in this bug fix.

Closes #410.
2013-05-09 09:24:10 -07:00
Andy Joslin c53265955b feat(tabs): Change directive name, add features
* Rename 'tabs' directive to 'tabset', and 'pane' directive to 'tab'.
 The new syntax is more intuitive; The word pane does not obviously
 represent a subset of a tab group. (Closes #186)
* Add 'tab-heading' directive, which is a child of a 'tab'. Allows
HTML in tab headings. (Closes #124)
* Add option for a 'select' attribute callback when a tab is selected.
 (Closes #141)
* Tabs transclude to title elements instead of content elements. Now the
 ordering of tab titles is always correct. (Closes #153)

BREAKING CHANGE: The 'tabs' directive has been renamed to 'tabset', and
 the 'pane' directive has been renamed to 'tab'.

    To migrate your code, follow the example below.

    Before:

    <tabs>
      <pane heading="one">
        First Content
      </pane>
      <pane ng-repeat="apple in basket" heading="{{apple.heading}}">
        {{apple.content}}
      </pane>
    </tabs>

    After:

    <tabset>
      <tab heading="one">
        First Content
      </tab>
      <tab ng-repeat="apple in basket" heading="{{apple.heading}}">
        {{apple.content}}
      </tab>
    </tabset>
2013-05-09 10:51:18 -04:00
Andy Joslin 39d7661435 chore(build): Use grunt-karma for testing 2013-05-09 10:48:19 -04:00
Pawel Kozlowski 041261b536 fix(tooltip): close tooltips appended to body on location change
Closes #345
2013-05-04 07:18:11 -07:00
bowenisdum 76fee1f9e1 fix(tooltip): fix positioning error when appendToBody is set to true
Closes #387

use offset function instead position function when appednToBody is set to true
2013-05-04 12:25:00 +02:00
Pawel Kozlowski d87ed0e216 chore(release): starting 0.4.0 2013-04-30 22:38:39 +02:00
251 changed files with 34663 additions and 25706 deletions
+18
View File
@@ -0,0 +1,18 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
root = true
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
# Tabs in JS unless otherwise specified
[**.js]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
+76
View File
@@ -0,0 +1,76 @@
{
"env": {
"browser": true,
"es6": true
},
"rules": {
"comma-dangle": 2,
"no-cond-assign": 2,
"no-control-regex": 2,
"no-debugger": 2,
"no-dupe-args": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty-character-class": 2,
"no-empty": 2,
"no-ex-assign": 2,
"no-extra-boolean-cast": 2,
"no-extra-parens": 2,
"no-extra-semi": 2,
"no-func-assign": 2,
"no-inner-declarations": 2,
"no-invalid-regexp": 2,
"no-negated-in-lhs": 2,
"no-regex-spaces": 2,
"no-sparse-arrays": 2,
"no-unexpected-multiline": 2,
"no-unreachable": 2,
"valid-typeof": 2,
"accessor-pairs": 2,
"block-scoped-var": 2,
"complexity": 2,
"curly": 2,
"dot-notation": [2, {"allowKeywords": false}],
"eqeqeq": 2,
"guard-for-in": 2,
"semi": 2,
"no-alert": 2,
"no-caller": 2,
"no-case-declarations": 2,
"no-div-regex": 2,
"no-else-return": 2,
"no-empty-label": 2,
"no-empty-pattern": 2,
"no-eq-null": 2,
"no-eval": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-floating-decimal": 2,
"no-implied-eval": 2,
"no-invalid-this": 2,
"no-iterator": 2,
"no-lone-blocks": 2,
"no-loop-func": 2,
"no-multi-spaces": 2,
"no-native-reassign": 2,
"no-new-func": 2,
"no-new-wrappers": 2,
"no-new": 2,
"no-octal-escape": 2,
"no-octal": 2,
"no-proto": 2,
"no-redeclare": 2,
"no-script-url": 2,
"no-self-compare": 2,
"no-sequences": 2,
"no-throw-literal": 2,
"no-unused-expressions": 2,
"no-useless-call": 2,
"no-useless-concat": 2,
"no-void": 2,
"no-with": 2,
"radix": 2,
"wrap-iife": 2,
"yoda": 2
}
}
+6
View File
@@ -0,0 +1,6 @@
*.html eol=lf
*.css eol=lf
*.js eol=lf
*.md eol=lf
*.json eol=lf
*.yml eol=lf
+17
View File
@@ -0,0 +1,17 @@
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:
### Steps to reproduce the issue:
### Version of Angular, UIBS, and Bootstrap
Angular:
UIBS:
Bootstrap:
+3
View File
@@ -9,11 +9,14 @@ lib-cov
*.swp
*.swo
.DS_Store
.idea
pids
logs
results
dist
# test coverage files
.coverage/
node_modules
npm-debug.log
+30
View File
@@ -0,0 +1,30 @@
{
"curly": true,
"immed": true,
"newcap": true,
"noarg": true,
"sub": true,
"boss": true,
"eqnull": true,
"quotmark": "single",
"trailing": true,
"undef": true,
"browser": true,
"jquery": true,
"globals": {
"angular": false,
// For Jasmine
"after" : false,
"afterEach" : false,
"before" : false,
"beforeEach" : false,
"describe" : false,
"expect" : false,
"jasmine" : false,
"module" : false,
"spyOn" : false,
"inject" : false,
"it" : false
}
}
+38
View File
@@ -0,0 +1,38 @@
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
*.swp
*.swo
.DS_Store
pids
logs
results
# test coverage files
.coverage/
node_modules
npm-debug.log
.git
docs
misc
.editorconfig
.gitattributes
.gitignore
.jshintrc
.travis.yml
CONTRIBUTING.md
Gruntfile.js
karma.conf.js
ROADMAP.md
dist/assets
dist/index.html
dist/versions-mapping.json
dist/*-SNAPSHOT*
+19 -11
View File
@@ -1,11 +1,19 @@
language: node_js
node_js:
- "0.8"
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm install --quiet -g grunt-cli karma
- npm install
script: grunt
language: node_js
node_js:
- "5.9"
env:
- CXX=g++-4.8
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
before_install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm install --quiet -g karma
script: grunt
sudo: false
+2093 -93
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
* Other unethical or unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
+45 -12
View File
@@ -1,12 +1,45 @@
We are always looking for the quality contributions and will be happy to accept your Pull Requests as long as those adhere to some basic rules:
* Please make sure that your contribution fits well in the project's context:
* we are aiming at rebuilding boostrap directives in pure AngularJS, without any dependencies on any external JavaScript library;
* the only dependency should be boostrap CSS and its markup structure;
* directives should be html-agnostic as much as possible which in practice means:
* templates should be referred to using the `templateUrl` property
* it should be easy to change a default template to a custom one
* directives shouldn't manipulate DOM structure directly (when possible)
* Please assure that you are submitting quality code, specifically make sure that:
* your directive has accompanying tests and all the tests are passing; don't hesitate to contact us (angular-ui@googlegroups.com) if you ned any help with unit testing
* your PR doesn't break the build; check the Travis-CI build status after opening a PR and push corrective commits if anything goes wrong
## Got a question or problem?
Firstly, please go over our FAQ: https://github.com/angular-ui/bootstrap/wiki/FAQ
Please, do not open issues for the general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [StackOverflow](http://stackoverflow.com/questions/tagged/angular-ui-bootstrap) where maintainers are looking at questions tagged with `angular-ui-bootstrap`.
StackOverflow is a much better place to ask questions since:
* there are hundreds of people willing to help on StackOverflow
* questions and answers stay available for public viewing so your question / answer might help someone else
* SO voting system assures that the best answers are prominently visible.
To save your and our time we will be systematically closing all the issues that are requests for general support and redirecting people to StackOverflow.
## You think you've found a bug?
Oh, we are ashamed and want to fix it asap! But before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs we will systematically ask you to provide a _minimal_ reproduce scenario using http://plnkr.co/. Having a live reproduce scenario gives us wealth of important information without going back & forth to you with additional questions like:
* version of AngularJS used
* version of this library that you are using
* 3rd-party libraries used, if any
* and most importantly - a use-case that fails
A minimal reproduce scenario using http://plnkr.co/ allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem.
We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
The best part is that you don't need to create plunks from scratch - you can use one from our [demo page](http://angular-ui.github.io/bootstrap/).
Unfortunately we are not able to investigate / fix bugs without a minimal reproduce scenario using http://plnkr.co/, so if we don't hear back from you we are going to close an issue that don't have enough info to be reproduced.
## You want to contribute some code?
We are always looking for the quality contributions and will be happy to accept your Pull Requests as long as those adhere to some basic rules:
* Please make sure that your contribution fits well in the project's context:
* we are aiming at rebuilding bootstrap directives in pure AngularJS, without any dependencies on any external JavaScript library;
* the only dependency should be bootstrap CSS and its markup structure;
* directives should be html-agnostic as much as possible which in practice means:
* templates should be referred to using the `templateUrl` property
* it should be easy to change a default template to a custom one
* directives shouldn't manipulate DOM structure directly (when possible)
* Please assure that you are submitting quality code, specifically make sure that:
* your directive has accompanying tests and all the tests are passing; don't hesitate to contact us (angular-ui@googlegroups.com) if you need any help with unit testing
* your PR doesn't break the build; check the Travis-CI build status after opening a PR and push corrective commits if anything goes wrong
* your commits conform to the conventions established [here](https://github.com/stevemao/conventional-changelog-angular/blob/master/convention.md)
+306 -167
View File
@@ -1,18 +1,16 @@
var markdown = require('node-markdown').Markdown;
var marked = require('marked');
var fs = require('fs');
var _ = require('lodash');
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-html2js');
require('load-grunt-tasks')(grunt);
// Project configuration.
grunt.util.linefeed = '\n';
grunt.initConfig({
ngversion: '1.0.5',
bsversion: '2.3.1',
ngversion: '1.6.1',
bsversion: '3.3.7',
modules: [],//to be filled in by build task
pkg: grunt.file.readJSON('package.json'),
dist: 'dist',
@@ -21,32 +19,46 @@ module.exports = function(grunt) {
meta: {
modules: 'angular.module("ui.bootstrap", [<%= srcModules %>]);',
tplmodules: 'angular.module("ui.bootstrap.tpls", [<%= tplModules %>]);',
all: 'angular.module("ui.bootstrap", ["ui.bootstrap.tpls", <%= srcModules %>]);'
all: 'angular.module("ui.bootstrap", ["ui.bootstrap.tpls", <%= srcModules %>]);',
cssInclude: '',
cssFileBanner: '/* Include this file in your html if you are using the CSP mode. */\n\n',
cssFileDest: '<%= dist %>/<%= filename %>-<%= pkg.version %>-csp.css',
banner: [
'/*',
' * <%= pkg.name %>',
' * <%= pkg.homepage %>\n',
' * Version: <%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>',
' * License: <%= pkg.license %>',
' */'
].join('\n')
},
watch: {
delta: {
docs: {
files: ['misc/demo/index.html'],
tasks: ['after-test']
},
html: {
files: ['template/**/*.html'],
tasks: ['html2js']
tasks: ['html2js', 'karma:watch:run']
},
js: {
//nospawn makes the tests start faster
nospawn: true,
files: ['src/**/*.js'],
//we don't need to jshint here, it slows down everything else
tasks: ['test-run']
files: ['src/**/*.js', '!src/**/index.js'],
tasks: ['karma:watch:run']
}
},
concat: {
dist: {
options: {
banner: '<%= meta.modules %>\n'
banner: '<%= meta.banner %><%= meta.modules %>\n',
footer: '<%= meta.cssInclude %>'
},
src: [], //src filled in by build task
dest: '<%= dist %>/<%= filename %>-<%= pkg.version %>.js'
},
dist_tpls: {
options: {
banner: '<%= meta.all %>\n<%= meta.tplmodules %>\n'
banner: '<%= meta.banner %><%= meta.all %>\n<%= meta.tplmodules %>\n',
footer: '<%= meta.cssInclude %>'
},
src: [], //src filled in by build task
dest: '<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.js'
@@ -60,28 +72,31 @@ module.exports = function(grunt) {
},
files: [{
expand: true,
src: ["**/*.html"],
cwd: "misc/demo/",
dest: "dist/"
src: ['**/*.html'],
cwd: 'misc/demo/',
dest: 'dist/'
}]
},
demoassets: {
files: [{
expand: true,
//Don't re-copy html files, we process those
src: ["**/**/*", "!**/*.html"],
cwd: "misc/demo",
dest: "dist/"
src: ['**/**/*', '!**/*.html'],
cwd: 'misc/demo',
dest: 'dist/'
}]
}
},
uglify: {
options: {
banner: '<%= meta.banner %>'
},
dist:{
src:['<%= dist %>/<%= filename %>-<%= pkg.version %>.js'],
src:['<%= concat.dist.dest %>'],
dest:'<%= dist %>/<%= filename %>-<%= pkg.version %>.min.js'
},
dist_tpls:{
src:['<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.js'],
src:['<%= concat.dist_tpls.dest %>'],
dest:'<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.min.js'
}
},
@@ -89,7 +104,10 @@ module.exports = function(grunt) {
dist: {
options: {
module: null, // no bundle module for all the html2js templates
base: '.'
base: '.',
rename: function(moduleName) {
return `uib/${moduleName}`;
}
},
files: [{
expand: true,
@@ -98,30 +116,94 @@ module.exports = function(grunt) {
}]
}
},
jshint: {
files: ['Gruntfile.js','src/**/*.js'],
eslint: {
files: ['Gruntfile.js','src/**/*.js']
},
karma: {
options: {
curly: true,
immed: true,
newcap: true,
noarg: true,
sub: true,
boss: true,
eqnull: true,
globals: {
angular: true
}
configFile: 'karma.conf.js'
},
watch: {
background: true
},
continuous: {
singleRun: true
},
jenkins: {
singleRun: true,
autoWatch: false,
colors: false,
reporters: ['dots', 'junit'],
browsers: ['Chrome', 'ChromeCanary', 'Firefox', 'Opera', '/Users/jenkins/bin/safari.sh']
},
travis: {
singleRun: true,
autoWatch: false,
reporters: ['dots'],
browsers: ['Firefox']
},
coverage: {
preprocessors: {
'src/*/*.js': 'coverage'
},
reporters: ['progress', 'coverage']
}
},
conventionalChangelog: {
options: {
changelogOpts: {
preset: 'angular'
},
templateFile: 'misc/changelog.tpl.md'
},
release: {
src: 'CHANGELOG.md'
}
},
shell: {
//We use %version% and evaluate it at run-time, because <%= pkg.version %>
//is only evaluated once
'release-prepare': [
'grunt before-test after-test',
'grunt version', //remove "-SNAPSHOT"
'grunt conventionalChangelog'
],
'release-complete': [
'git commit CHANGELOG.md package.json -m "chore(release): v%version%"',
'git tag %version%'
],
'release-start': [
'grunt version:minor:"SNAPSHOT"',
'git commit package.json -m "chore(release): Starting v%version%"'
]
},
'ddescribe-iit': {
files: [
'src/**/*.spec.js'
]
}
});
//register before and after test tasks so we've don't have to change cli options on the goole's CI server
grunt.registerTask('before-test', ['jshint', 'html2js']);
//register before and after test tasks so we've don't have to change cli
//options on the google's CI server
grunt.registerTask('before-test', ['enforce', 'ddescribe-iit', 'eslint', 'html2js']);
grunt.registerTask('after-test', ['build', 'copy']);
//Rename our watch task to 'delta', then make actual 'watch'
//task build things, then start test server
grunt.renameTask('watch', 'delta');
grunt.registerTask('watch', ['before-test', 'after-test', 'karma:watch', 'delta']);
// Default task.
grunt.registerTask('default', ['before-test', 'test', 'after-test']);
grunt.registerTask('enforce', `Install commit message enforce script if it doesn't exist`, function() {
if (!grunt.file.exists('.git/hooks/commit-msg')) {
grunt.file.copy('misc/validate-commit-msg.js', '.git/hooks/commit-msg');
require('fs').chmodSync('.git/hooks/commit-msg', '0755');
}
});
//Common ui.bootstrap module containing all modules for src and templates
//findModule: Adds a given module to config
var foundModules = {};
@@ -140,34 +222,49 @@ module.exports = function(grunt) {
});
}
function enquote(str) {
return '"' + str + '"';
return `"${str}"`;
}
function enquoteUibDir(str) {
return enquote(`uib/${str}`);
}
var module = {
name: name,
moduleName: enquote('ui.bootstrap.' + name),
moduleName: enquote(`ui.bootstrap.${name}`),
displayName: ucwords(breakup(name, ' ')),
srcFiles: grunt.file.expand("src/"+name+"/*.js"),
tplFiles: grunt.file.expand("template/"+name+"/*.html"),
tpljsFiles: grunt.file.expand("template/"+name+"/*.html.js"),
tplModules: grunt.file.expand("template/"+name+"/*.html").map(enquote),
srcFiles: grunt.file.expand([`src/${name}/*.js`, `!src/${name}/index.js`, `!src/${name}/index-nocss.js`]),
cssFiles: grunt.file.expand(`src/${name}/*.css`),
tplFiles: grunt.file.expand(`template/${name}/*.html`),
tpljsFiles: grunt.file.expand(`template/${name}/*.html.js`),
tplModules: grunt.file.expand(`template/${name}/*.html`).map(enquoteUibDir),
dependencies: dependenciesForModule(name),
docs: {
md: grunt.file.expand("src/"+name+"/docs/*.md")
.map(grunt.file.read).map(markdown).join("\n"),
js: grunt.file.expand("src/"+name+"/docs/*.js")
.map(grunt.file.read).join("\n"),
html: grunt.file.expand("src/"+name+"/docs/*.html")
.map(grunt.file.read).join("\n")
md: grunt.file.expand(`src/${name}/docs/*.md`)
.map(grunt.file.read).map((str) => marked(str)).join('\n'),
js: grunt.file.expand(`src/${name}/docs/*.js`)
.map(grunt.file.read).join('\n'),
html: grunt.file.expand(`src/${name}/docs/*.html`)
.map(grunt.file.read).join('\n')
}
};
var styles = {
css: [],
js: []
};
module.cssFiles.forEach(processCSS.bind(null, module.name, styles, true));
if (styles.css.length) {
module.css = styles.css.join('\n');
module.cssJs = styles.js.join('\n');
}
module.dependencies.forEach(findModule);
grunt.config('modules', grunt.config('modules').concat(module));
}
function dependenciesForModule(name) {
var deps = [];
grunt.file.expand('src/' + name + '/*.js')
grunt.file.expand([`src/${name}/*.js`, `!src/${name}/index.js`, `!src/${name}/index-nocss.js`])
.map(grunt.file.read)
.forEach(function(contents) {
//Strategy: find where module is declared,
@@ -196,6 +293,8 @@ module.exports = function(grunt) {
});
grunt.registerTask('build', 'Create bootstrap build files', function() {
var _ = grunt.util._;
//If arguments define what modules to build, build those. Else, everything
if (this.args.length) {
this.args.forEach(findModule);
@@ -203,28 +302,41 @@ module.exports = function(grunt) {
} else {
grunt.file.expand({
filter: 'isDirectory', cwd: '.'
}, 'src/*').forEach(function(dir) {
}, 'src/*').forEach((dir) => {
findModule(dir.split('/')[1]);
});
}
//Pluck will take an array of objects, and map the given key to a new array
//@example: expect( pluck([{a:1},{a:2}], 'a') ).toBe([1,2])
function pluck(array, key) {
return array.map(function(obj) {
return obj[key];
});
}
var modules = grunt.config('modules');
grunt.config('srcModules', pluck(modules, 'moduleName'));
grunt.config('tplModules', pluck(modules, 'tplModules').filter(function(tpls) { return tpls.length > 0;} ));
grunt.config('demoModules', modules.filter(function(module) {
return module.docs.md && module.docs.js && module.docs.html;
}));
grunt.config('srcModules', _.pluck(modules, 'moduleName'));
grunt.config('tplModules', _.pluck(modules, 'tplModules').filter((tpls) => tpls.length > 0));
grunt.config('demoModules', modules
.filter((module) => module.docs.md && module.docs.js && module.docs.html)
.sort((a, b) => {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
})
);
var srcFiles = pluck(modules, 'srcFiles');
var tpljsFiles = pluck(modules, 'tpljsFiles');
var cssStrings = _.flatten(_.compact(_.pluck(modules, 'css')));
var cssJsStrings = _.flatten(_.compact(_.pluck(modules, 'cssJs')));
if (cssStrings.length) {
grunt.config('meta.cssInclude', cssJsStrings.join('\n'));
grunt.file.write(grunt.config('meta.cssFileDest'), grunt.config('meta.cssFileBanner') +
cssStrings.join('\n'));
grunt.log.writeln('File ' + grunt.config('meta.cssFileDest') + ' created');
}
var moduleFileMapping = _.clone(modules, true);
moduleFileMapping.forEach((module) => delete module.docs);
grunt.config('moduleFileMapping', moduleFileMapping);
var srcFiles = _.pluck(modules, 'srcFiles');
var tpljsFiles = _.pluck(modules, 'tpljsFiles');
//Set the concat task to concatenate the given src modules
grunt.config('concat.dist.src', grunt.config('concat.dist.src')
.concat(srcFiles));
@@ -232,114 +344,141 @@ module.exports = function(grunt) {
grunt.config('concat.dist_tpls.src', grunt.config('concat.dist_tpls.src')
.concat(srcFiles).concat(tpljsFiles));
grunt.task.run(['concat', 'uglify']);
grunt.task.run(['concat', 'uglify', 'makeModuleMappingFile', 'makeRawFilesJs', 'makeVersionsMappingFile']);
});
grunt.registerTask('test', 'run tests on single-run server', function() {
var options = ['--single-run', '--no-auto-watch', '--log-level=warn']
.concat(this.args) //Let user augment test args with command line args
.concat(process.env.TRAVIS ? '--browsers=Firefox' : '');
runKarma('start', options);
});
grunt.registerTask('server', 'start karma server', function() {
var options = ['--no-single-run', '--no-auto-watch'].concat(this.args);
runKarma('start', options);
});
grunt.registerTask('test-run', 'run tests against continuous karma server', function() {
var options = ['--single-run', '--no-auto-watch'].concat(this.args);
runKarma('run', options);
});
grunt.registerTask('test-watch', 'start karma server, watch & execute tests', function() {
var options = ['--no-single-run', '--auto-watch'].concat(this.args);
runKarma('start', options);
});
//changelog generation
grunt.registerTask('changelog', 'generates changelog markdown from git commits', function () {
var changeFrom = this.args[0], changeTo = this.args[1] || 'HEAD';
var done = grunt.task.current.async();
var child = grunt.util.spawn({
cmd:process.platform === 'win32' ? 'git.cmd' : 'git',
args: [
'log',
changeFrom + '..' + changeTo,
'--format=%H%n%s%n%b%n==END=='
]
}, function (err, result, code) {
var changelog = {};
function addChange(changeType, component, change) {
if (!changelog[changeType]) {
changelog[changeType] = {};
}
if (!changelog[changeType][component]) {
changelog[changeType][component] = [];
}
changelog[changeType][component].push(change);
grunt.registerTask('test', 'Run tests on singleRun karma server', function() {
//this task can be executed in 3 different environments: local, Travis-CI and Jenkins-CI
//we need to take settings for each one into account
if (process.env.TRAVIS) {
grunt.task.run('karma:travis');
} else {
var isToRunJenkinsTask = !!this.args.length;
if (grunt.option('coverage')) {
var karmaOptions = grunt.config.get('karma.options'),
coverageOpts = grunt.config.get('karma.coverage');
grunt.util._.extend(karmaOptions, coverageOpts);
grunt.config.set('karma.options', karmaOptions);
}
grunt.task.run(this.args.length ? 'karma:jenkins' : 'karma:continuous');
}
});
var COMMIT_MSG_REGEXP = /^(chore|demo|docs|feat|fix|refactor|style|test)\((.+)\):? (.+)$/;
var gitlog = result.toString().split('\n==END==\n').reverse();
grunt.registerTask('makeModuleMappingFile', function() {
var _ = grunt.util._;
var moduleMappingJs = 'dist/assets/module-mapping.json';
var moduleMappings = grunt.config('moduleFileMapping');
var moduleMappingsMap = _.object(_.pluck(moduleMappings, 'name'), moduleMappings);
var jsContent = JSON.stringify(moduleMappingsMap);
grunt.file.write(moduleMappingJs, jsContent);
grunt.log.writeln('File ' + moduleMappingJs.cyan + ' created.');
});
if (code) {
grunt.log.error(err);
done(false);
} else {
grunt.registerTask('makeRawFilesJs', function() {
var _ = grunt.util._;
var jsFilename = 'dist/assets/raw-files.json';
var genRawFilesJs = require('./misc/raw-files-generator');
gitlog.forEach(function (logItem) {
var lines = logItem.split('\n');
var sha1 = lines.shift().substr(0,8); //Only first 7 of sha1
var subject = lines.shift();
genRawFilesJs(grunt, jsFilename, _.flatten(grunt.config('concat.dist_tpls.src')),
grunt.config('meta.banner'), grunt.config('meta.cssFileBanner'));
});
var msgMatches = subject.match(COMMIT_MSG_REGEXP);
var changeType = msgMatches[1];
var component = msgMatches[2];
var componentMsg = msgMatches[3];
grunt.registerTask('makeVersionsMappingFile', function() {
var done = this.async();
var breaking = logItem.match(/BREAKING CHANGE:([\s\S]*)/);
if (breaking) {
addChange('breaking', component, {
sha1: sha1,
msg: breaking[1]
});
}
addChange(changeType, component, {sha1:sha1, msg:componentMsg});
});
var exec = require('child_process').exec;
console.log(grunt.template.process(grunt.file.read('misc/changelog.tpl.md'), {data: {
changelog: changelog,
today: grunt.template.today('yyyy-mm-dd'),
version : grunt.config('pkg.version')
}}));
var versionsMappingFile = 'dist/versions-mapping.json';
done();
}
exec('git tag --sort -version:refname', function(error, stdout, stderr) {
// Let's remove the oldest 14 versions.
var versions = stdout.split('\n').slice(0, -14);
var jsContent = versions.map(function(version) {
version = version.replace(/^v/, '');
return {
version: version,
url: `/bootstrap/versioned-docs/${version}`
};
});
jsContent = _.sortBy(jsContent, 'version').reverse();
jsContent.unshift({
version: 'Current',
url: '/bootstrap'
});
grunt.file.write(versionsMappingFile, JSON.stringify(jsContent));
grunt.log.writeln(`File ${versionsMappingFile.cyan} created.`);
done();
});
});
// Karma configuration
function runKarma(command, options) {
var karmaCmd = process.platform === 'win32' ? 'karma.cmd' : 'karma';
var args = [command].concat(options);
var done = grunt.task.current.async();
var child = grunt.util.spawn({
cmd: karmaCmd,
args: args
}, function(err, result, code) {
if (code) {
done(false);
} else {
done();
}
});
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
/**
* Logic from AngularJS
* https://github.com/angular/angular.js/blob/36831eccd1da37c089f2141a2c073a6db69f3e1d/lib/grunt/utils.js#L121-L145
*/
function processCSS(moduleName, state, minify, file) {
var css = fs.readFileSync(file).toString(),
js;
state.css.push(css);
if (minify) {
css = css
.replace(/\r?\n/g, '')
.replace(/\/\*.*?\*\//g, '')
.replace(/:\s+/g, ':')
.replace(/\s*\{\s*/g, '{')
.replace(/\s*\}\s*/g, '}')
.replace(/\s*\,\s*/g, ',')
.replace(/\s*\;\s*/g, ';');
}
//escape for js
css = css
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(/\r?\n/g, '\\n');
js = `angular.module('ui.bootstrap.${moduleName}').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uib${_.capitalize(moduleName)}Css && angular.element(document).find('head').prepend('<style type="text/css">${css}</style>'); angular.$$uib${_.capitalize(moduleName)}Css = true; });`;
state.js.push(js);
return state;
}
function setVersion(type, suffix) {
var file = 'package.json';
var VERSION_REGEX = /([\'|\"]version[\'|\"][ ]*:[ ]*[\'|\"])([\d|.]*)(-\w+)*([\'|\"])/;
var contents = grunt.file.read(file);
var version;
contents = contents.replace(VERSION_REGEX, function(match, left, center) {
version = center;
if (type) {
version = require('semver').inc(version, type);
}
//semver.inc strips our suffix if it existed
if (suffix) {
version += '-' + suffix;
}
return left + version + '"';
});
grunt.log.ok('Version set to ' + version.cyan);
grunt.file.write(file, contents);
return version;
}
grunt.registerTask('version', 'Set version. If no arguments, it just takes off suffix', function() {
setVersion(this.args[0], this.args[1]);
});
grunt.registerMultiTask('shell', 'run shell commands', function() {
var self = this;
var sh = require('shelljs');
self.data.forEach(function(cmd) {
cmd = cmd.replace('%version%', grunt.file.readJSON('package.json').version);
grunt.log.ok(cmd);
var result = sh.exec(cmd,{silent:true});
if (result.code !== 0) {
grunt.fatal(result.output);
}
});
});
return grunt;
};
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2012-2013 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
Copyright (c) 2012-2017 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+160 -52
View File
@@ -1,80 +1,188 @@
# bootstrap - [AngularJS](http://angularjs.org/) directives specific to [twitter bootstrap](http://twitter.github.io/bootstrap/)
### UI Bootstrap - [AngularJS](http://angularjs.org/) directives specific to [Bootstrap](http://getbootstrap.com)
***
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular-ui/bootstrap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://secure.travis-ci.org/angular-ui/bootstrap.svg)](http://travis-ci.org/angular-ui/bootstrap)
[![devDependency Status](https://david-dm.org/angular-ui/bootstrap/dev-status.svg?branch=master)](https://david-dm.org/angular-ui/bootstrap#info=devDependencies)
[![CDNJS](https://img.shields.io/cdnjs/v/angular-ui-bootstrap.svg)](https://cdnjs.com/libraries/angular-ui-bootstrap/)
[![Build Status](https://secure.travis-ci.org/angular-ui/bootstrap.png)](http://travis-ci.org/angular-ui/bootstrap)
### Quick links
- [Demo](#demo)
- [Angular 2](#angular-2)
- [Installation](#installation)
- [NPM](#install-with-npm)
- [Bower](#install-with-bower)
- [NuGet](#install-with-nuget)
- [Custom](#custom-build)
- [Manual](#manual-download)
- [Webpack / JSPM](#webpack--jspm)
- [Support](#support)
- [FAQ](#faq)
- [Code of Conduct](#code-of-conduct)
- [PREFIX MIGRATION GUIDE](#prefix-migration-guide)
- [Supported browsers](#supported-browsers)
- [Need help?](#need-help)
- [Found a bug?](#found-a-bug)
- [Contributing to the project](#contributing-to-the-project)
- [Development, meeting minutes, roadmap and more.](#development-meeting-minutes-roadmap-and-more)
## Demo
Do you want to see directives in action? Visit http://angular-ui.github.io/bootstrap/!
# Demo
## Installation
Do you want to see directives in action? Visit https://angular-ui.github.io/bootstrap/!
Installation is easy as angular-ui-bootstrap has minimal dependencies - only the AngularJS and Bootstrap's CSS are required.
After downloading dependencies (or better yet, referencing them from your favourite CDN) you need to download build version of this project. All the files and their purposes are described here:
# Angular 2
Are you interested in Angular 2? We are on our way! Check out [ng-bootstrap](https://github.com/ui-bootstrap/core).
# Installation
Installation is easy as UI Bootstrap has minimal dependencies - only the AngularJS and Twitter Bootstrap's CSS are required.
*Notes:*
* Since version 0.13.0, UI Bootstrap depends on [ngAnimate](https://docs.angularjs.org/api/ngAnimate) for transitions and animations, such as the accordion, carousel, etc. Include `ngAnimate` in the module dependencies for your app in order to enable animation.
* UI Bootstrap depends on [ngTouch](https://docs.angularjs.org/api/ngTouch) for swipe actions. Include `ngTouch` in the module dependencies for your app in order to enable swiping.
## Angular Requirements
* UI Bootstrap 1.0 and higher _requires_ Angular 1.4.x or higher and it has been tested with Angular 1.4.8.
* UI Bootstrap 0.14.3 is the _last_ version that supports Angular 1.3.x.
* UI Bootstrap 0.12.0 is the _last_ version that supports Angular 1.2.x.
## Bootstrap Requirements
* UI Bootstrap requires Bootstrap CSS version 3.x or higher and it has been tested with Bootstrap CSS 3.3.6.
* UI Bootstrap 0.8 is the _last_ version that supports Bootstrap CSS 2.3.x.
#### Install with NPM
```sh
$ npm install angular-ui-bootstrap
```
This will install AngularJS and Bootstrap NPM packages.
#### Install with Bower
```sh
$ bower install angular-bootstrap
```
Note: do not install 'angular-ui-bootstrap'. A separate repository - [bootstrap-bower](https://github.com/angular-ui/bootstrap-bower) - hosts the compiled javascript file and bower.json.
#### Install with NuGet
To install AngularJS UI Bootstrap, run the following command in the Package Manager Console
```sh
PM> Install-Package Angular.UI.Bootstrap
```
#### Custom build
Head over to https://angular-ui.github.io/bootstrap/ and hit the *Custom build* button to create your own custom UI Bootstrap build, just the way you like it.
#### Manual download
After downloading dependencies (or better yet, referencing them from your favorite CDN) you need to download build version of this project. All the files and their purposes are described here:
https://github.com/angular-ui/bootstrap/tree/gh-pages#build-files
Don't worry, if you are not sure which file to take, opt for `ui-bootstrap-tpls-[version].min.js`.
### Adding dependency to your project
When you are done downloading all the dependencies and project files the only remaining part is to add dependencies on the `ui.bootstrap` AngularJS module:
```javascript
```js
angular.module('myModule', ['ui.bootstrap']);
```
Project files are also available through your favourite package manager:
* **Bower**: `bower install angular-bootstrap`
* **NuGet**: https://nuget.org/packages/Angular.UI.Bootstrap/
# Webpack / JSPM
## Project philosophy
To use this project with webpack, follow the [NPM](#install-with-npm) instructions.
Now, if you want to use only the accordion, you can do:
### Native, lightweight directives
```js
import accordion from 'angular-ui-bootstrap/src/accordion';
We are aiming at providing a set of AngularJS directives based on Twitter Bootstrap's markup and CSS. The goal is to provide **native AngularJS directives** without any dependency on jQuery or Bootstrap's JavaScript.
It is often better to rewrite an existing JavaScript code and create a new, pure AngularJS directive. Most of the time the resulting directive is smaller as compared to the orginal JavaScript code size and better integrated into the AngularJS ecosystem.
angular.module('myModule', [accordion]);
```
### Customizability
You can import all the pieces you need in the same way:
All the directives in this repository should have their markup externalized as templates (loaded via `templateUrl`). In practice it means that you can **customize directive's markup at will**. One could even imagine providing a non-Boostrap version of the templates!
```js
import accordion from 'angular-ui-bootstrap/src/accordion';
import datepicker from 'angular-ui-bootstrap/src/datepicker';
### Take what you need and not more
angular.module('myModule', [accordion, datepicker]);
```
Each directive has its own AngularJS module without any dependencies on other modules or third-pary JavaScript code. In practice it means that you can **just grab the code for the directives you need** and you are not obliged to drag the whole repository.
This will load all the dependencies (if any) and also the templates (if any).
### Quality and stability
Be sure to have a loader able to process `css` files like `css-loader`.
Directives should work. All the time and in all browsers. This is why all the directives have a comprehensive suite of unit tests. All the automated tests are executed on each checkin in several browsers: Chrome, ChromeCanary, Firefox, Opera, Safari, IE9.
In fact we are fortunate enough to **benefit from the same testing infrastructure as AngularJS**!
If you would prefer not to load your css through your JavaScript file loader/bundler, you can choose to import the `index-nocss.js` file instead, which is available for the modules:
* carousel
* datepicker
* datepickerPopup
* dropdown
* modal
* popover
* position
* timepicker
* tooltip
* typeahead
## Contributing to the project
The other modules, such as `accordion` in the example below, do not have CSS resources to load, so you should continue to import them as normal:
```js
import accordion from 'angular-ui-bootstrap/src/accordion';
import typeahead from 'angular-ui-bootstrap/src/typeahead/index-nocss.js';
angular.module('myModule', [accordion, typeahead]);
```
# Versioning
Pre-2.0.0 does not follow a particular versioning system. 2.0.0 and onwards follows [semantic versioning](http://semver.org/). All release changes can be viewed on our [changelog](CHANGELOG.md).
# Support
## FAQ
https://github.com/angular-ui/bootstrap/wiki/FAQ
# Code of Conduct
Take a moment to read our [Code of Conduct](CODE_OF_CONDUCT.md)
## PREFIX MIGRATION GUIDE
If you're updating your application to use prefixes, please check the [migration guide](https://github.com/angular-ui/bootstrap/wiki/Migration-guide-for-prefixes).
## Supported browsers
Directives from this repository are automatically tested with the following browsers:
* Chrome (stable and canary channel)
* Firefox
* IE 9 and 10
* Opera
* Safari
Modern mobile browsers should work without problems.
## Need help?
Need help using UI Bootstrap?
* Live help in the IRC (`#angularjs` channel at the `freenode` network). Use this [webchat](https://webchat.freenode.net/) or your own IRC client.
* Ask a question in [StackOverflow](http://stackoverflow.com/) under the [angular-ui-bootstrap](http://stackoverflow.com/questions/tagged/angular-ui-bootstrap) tag.
**Please do not create new issues in this repository to ask questions about using UI Bootstrap**
## Found a bug?
Please take a look at [CONTRIBUTING.md](CONTRIBUTING.md#you-think-youve-found-a-bug) and submit your issue [here](https://github.com/angular-ui/bootstrap/issues/new).
----
# Contributing to the project
We are always looking for the quality contributions! Please check the [CONTRIBUTING.md](CONTRIBUTING.md) for the contribution guidelines.
### Development
#### Prepare your environment
* Install [Node.js](http://nodejs.org/) and NPM (should come with)
* Install global dev dependencies: `npm install -g grunt-cli karma`
* Instal local dev dependencies: `npm install` while current directory is bootstrap repo
# Development, meeting minutes, roadmap and more.
#### Build
* Build the whole project: `grunt` - this will run `lint`, `test`, and `concat` targets
Check the Grunt build file for other tasks that are defined for this project
#### TDD
* Start karma server: `grunt server`
* Run test: `grunt test-run`
### Release
* Bump up version number in `package.json`
* Commit the version change with the following message: `chore(release): [versio number]`
* tag
* push changes and a tag (`git push --tags`)
* switch to the `gh-pages` branch: `git checkout gh-pages`
* copy content of the dist folder to the main folder
* Commit the version change with the following message: `chore(release): [versio number]`
* push changes
* switch back to the `main branch` and modify `package.json` to bump up version for the next iteration
* commit (`chore(release): starting [versio number]`) and push
* publish Bower and NuGet packages
Well done! (If you don't like repeating yourself open a PR with a grunt task taking care of the above!)
Head over to the [Wiki](https://github.com/angular-ui/bootstrap/wiki) for notes on development for UI Bootstrap, meeting minutes from the UI Bootstrap team, roadmap plans, project philosophy and more.
+3
View File
@@ -0,0 +1,3 @@
require('./dist/ui-bootstrap-tpls');
module.exports = 'ui.bootstrap';
+69 -43
View File
@@ -1,55 +1,81 @@
// Karma configuration
// Generated on Sat Mar 28 2015 11:17:34 GMT-0700 (PDT)
// base path, that will be used to resolve files and exclude
basePath = '.';
module.exports = function(config) {
config.set({
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
'misc/test-lib/jquery-1.8.2.min.js',
'misc/test-lib/angular.js',
'misc/test-lib/angular-mocks.js',
'misc/test-lib/helpers.js',
'src/**/*.js',
'template/**/*.js'
];
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// list of files to exclude
exclude = [
];
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari
// - PhantomJS
browsers = [
'Chrome'
];
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// test results reporter to use
// possible values: dots || progress
reporter = 'progress';
// web server port
port = 9018;
// list of files / patterns to load in the browser
files: [
'misc/test-lib/jquery-1.8.2.min.js',
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'node_modules/angular-sanitize/angular-sanitize.js',
'misc/test-lib/helpers.js',
'src/**/*.js',
'template/**/*.js'
],
// cli runner port
runnerPort = 9100;
// enable / disable colors in the output (reporters and logs)
colors = true;
// list of files to exclude
exclude: [
'src/**/index.js',
'src/**/index-nocss.js',
'src/**/docs/*'
],
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_INFO;
// enable / disable watching file and executing tests whenever any file changes
autoWatch = false;
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'src/*/{*.js,!(test)/**/*.js}': ['coverage']
},
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = false;
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],
coverageReporter: {
dir: '.coverage/',
type: 'html'
},
reportSlowerThan: 100,
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
+16 -28
View File
@@ -1,28 +1,16 @@
# <%= version%> (<%= today%>)
## Features
<% _(changelog.feat).forEach(function(changes, component) { %>
- **<%= component%>:**
<% changes.forEach(function(change) { %>
- <%= change.msg%> ([<%= change.sha1%>](https://github.com/angular-ui/bootstrap/commit/<%= change.sha1%>))
<% }) %>
<% }) %>
## Bug Fixes
<% _(changelog.fix).forEach(function(changes, component) { %>
- **<%= component%>:**
<% changes.forEach(function(change) { %>
- <%= change.msg%> ([<%= change.sha1%>](https://github.com/angular-ui/bootstrap/commit/<%= change.sha1%>))
<% }) %>
<% }) %>
## Breaking Changes
<% _(changelog.breaking).forEach(function(changes, component) { %>
- **<%= component%>:**
<% changes.forEach(function(change) { %>
<%= change.msg%>
<% }) %>
<% }) %>
# <%= version%> (<%= today%>)
<% if (_(changelog.feat).size() > 0) { %>
## Features
<% _(changelog.feat).keys().sort().forEach(function(scope) { %>
- **<%= scope%>:** <% changelog.feat[scope].forEach(function(change) { %>
- <%= change.msg%> (<%= helpers.commitLink(change.sha1) %>)<% }); %><% }); %> <% } %>
<% if (_(changelog.fix).size() > 0) { %>
## Bug Fixes
<% _(changelog.fix).keys().sort().forEach(function(scope) { %>
- **<%= scope%>:** <% changelog.fix[scope].forEach(function(change) { %>
- <%= change.msg%> (<%= helpers.commitLink(change.sha1) %>)<% }); %><% }); %> <% } %>
<% if (_(changelog.breaking).size() > 0) { %>
## Breaking Changes
<% _(changelog.breaking).keys().sort().forEach(function(scope) { %>
- **<%= scope%>:** <% changelog.breaking[scope].forEach(function(change) { %>
<%= change.msg%><% }); %><% }); %> <% } %>
+308 -22
View File
@@ -1,31 +1,317 @@
/* global FastClick, smoothScroll */
angular.module('ui.bootstrap.demo', ['ui.bootstrap', 'plunker', 'ngTouch', 'ngAnimate', 'ngSanitize'], function($httpProvider){
if (!!window.FastClick) {
FastClick.attach(document.body);
}
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}).run(['$location', function($location){
//Allows us to navigate to the correct element on initialization
if ($location.path() !== '' && $location.path() !== '/') {
smoothScroll(document.getElementById($location.path().substring(1)), 500, function(el) {
location.replace('#' + el.id);
});
}
}]).factory('buildFilesService', function ($http, $q) {
angular.module('bootstrapDemoApp', ['ui.directives', 'ui.bootstrap', 'plunker']);
var moduleMap;
var rawFiles;
function MainCtrl($scope, $http, orderByFilter) {
var url = "http://50.116.42.77:3001";
$scope.selectedModules = [];
//iFrame for downloading
var $iframe = $("<iframe>").css('display','none').appendTo(document.body);
$scope.showBuildModal = function() {
$scope.buildModalShown = true;
//Load modules if they aren't loaded yet
if (!$scope.modules) {
$http.get(url + "/api/bootstrap").then(function(response) {
$scope.modules = response.data.modules;
}, function() {
$scope.buildGetErrorText = "Error retrieving build files from server.";
return {
getModuleMap: getModuleMap,
getRawFiles: getRawFiles,
get: function () {
return $q.all({
moduleMap: getModuleMap(),
rawFiles: getRawFiles()
});
}
};
$scope.downloadBuild = function() {
var downloadUrl = url + "/api/bootstrap/download?";
angular.forEach($scope.selectedModules, function(module) {
downloadUrl += "modules=" + module + "&";
function getModuleMap() {
return moduleMap ? $q.when(moduleMap) : $http.get('assets/module-mapping.json')
.then(function (result) {
moduleMap = result.data;
return moduleMap;
});
}
function getRawFiles() {
return rawFiles ? $q.when(rawFiles) : $http.get('assets/raw-files.json')
.then(function (result) {
rawFiles = result.data;
return rawFiles;
});
}
})
.controller('MainCtrl', MainCtrl)
.controller('SelectModulesCtrl', SelectModulesCtrl)
.controller('DownloadCtrl', DownloadCtrl);
function MainCtrl($scope, $http, $document, $uibModal, orderByFilter) {
// Grab old version docs
$http.get('/bootstrap/versions-mapping.json')
.then(function(result) {
$scope.oldDocs = result.data;
});
$scope.showBuildModal = function() {
var modalInstance = $uibModal.open({
templateUrl: 'buildModal.html',
controller: 'SelectModulesCtrl',
resolve: {
modules: function(buildFilesService) {
return buildFilesService.getModuleMap()
.then(function (moduleMap) {
return Object.keys(moduleMap);
});
}
}
});
};
$scope.showDownloadModal = function() {
var modalInstance = $uibModal.open({
templateUrl: 'downloadModal.html',
controller: 'DownloadCtrl'
});
$iframe.attr('src','');
$iframe.attr('src', downloadUrl);
$scope.buildModalShown = false;
};
}
function SelectModulesCtrl($scope, $uibModalInstance, modules, buildFilesService) {
$scope.selectedModules = [];
$scope.modules = modules;
$scope.selectedChanged = function(module, selected) {
if (selected) {
$scope.selectedModules.push(module);
} else {
$scope.selectedModules.splice($scope.selectedModules.indexOf(module), 1);
}
};
$scope.downloadBuild = function () {
$uibModalInstance.close($scope.selectedModules);
};
$scope.cancel = function () {
$uibModalInstance.dismiss();
};
$scope.isOldBrowser = function () {
return isOldBrowser;
};
$scope.build = function (selectedModules, version) {
/* global JSZip, saveAs */
var moduleMap, rawFiles;
buildFilesService.get().then(function (buildFiles) {
moduleMap = buildFiles.moduleMap;
rawFiles = buildFiles.rawFiles;
generateBuild();
});
function generateBuild() {
var srcModuleNames = selectedModules
.map(function (module) {
return moduleMap[module];
})
.reduce(function (toBuild, module) {
addIfNotExists(toBuild, module.name);
module.dependencies.forEach(function (depName) {
addIfNotExists(toBuild, depName);
});
return toBuild;
}, []);
var srcModules = srcModuleNames
.map(function (moduleName) {
return moduleMap[moduleName];
});
var srcModuleFullNames = srcModules
.map(function (module) {
return module.moduleName;
});
var srcJsContent = srcModules
.reduce(function (buildFiles, module) {
return buildFiles.concat(module.srcFiles);
}, [])
.map(getFileContent)
.join('\n')
;
var jsFile = createNoTplFile(srcModuleFullNames, srcJsContent);
var tplModuleNames = srcModules
.reduce(function (tplModuleNames, module) {
return tplModuleNames.concat(module.tplModules);
}, []);
var tplJsContent = srcModules
.reduce(function (buildFiles, module) {
return buildFiles.concat(module.tpljsFiles);
}, [])
.map(getFileContent)
.join('\n')
;
var jsTplFile = createWithTplFile(srcModuleFullNames, srcJsContent, tplModuleNames, tplJsContent);
var cssContent = srcModules
.map(function (module) {
return module.css;
})
.filter(function (css) {
return css;
})
.join('\n')
;
var cssJsContent = srcModules
.map(function (module) {
return module.cssJs;
})
.filter(function (cssJs) {
return cssJs;
})
.join('\n')
;
var footer = cssJsContent;
var zip = new JSZip();
zip.file('ui-bootstrap-custom-' + version + '.js', rawFiles.banner + jsFile + footer);
zip.file('ui-bootstrap-custom-' + version + '.min.js', rawFiles.banner + uglify(jsFile + footer));
zip.file('ui-bootstrap-custom-tpls-' + version + '.js', rawFiles.banner + jsTplFile + footer);
zip.file('ui-bootstrap-custom-tpls-' + version + '.min.js', rawFiles.banner + uglify(jsTplFile + footer));
zip.file('ui-bootstrap-custom-tpls-' + version + '.min.js', rawFiles.banner + uglify(jsTplFile + footer));
if (cssContent) {
zip.file('ui-bootstrap-custom-' + version + '-csp.css', rawFiles.cssBanner + cssContent);
}
saveAs(zip.generate({type: 'blob'}), 'ui-bootstrap-custom-build.zip');
}
function createNoTplFile(srcModuleNames, srcJsContent) {
return 'angular.module("ui.bootstrap", [' + srcModuleNames.join(',') + ']);\n' +
srcJsContent;
}
function createWithTplFile(srcModuleNames, srcJsContent, tplModuleNames, tplJsContent) {
var depModuleNames = srcModuleNames.slice();
depModuleNames.unshift('"ui.bootstrap.tpls"');
return 'angular.module("ui.bootstrap", [' + depModuleNames.join(',') + ']);\n' +
'angular.module("ui.bootstrap.tpls", [' + tplModuleNames.join(',') + ']);\n' +
srcJsContent + '\n' + tplJsContent;
}
function addIfNotExists(array, element) {
if (array.indexOf(element) == -1) {
array.push(element);
}
}
function getFileContent(fileName) {
return rawFiles.files[fileName];
}
function uglify(js) {
/* global UglifyJS */
var ast = UglifyJS.parse(js);
ast.figure_out_scope();
var compressor = UglifyJS.Compressor();
var compressedAst = ast.transform(compressor);
compressedAst.figure_out_scope();
compressedAst.compute_char_frequency();
compressedAst.mangle_names();
var stream = UglifyJS.OutputStream();
compressedAst.print(stream);
return stream.toString();
}
};
}
function DownloadCtrl($scope, $uibModalInstance) {
$scope.options = {
minified: true,
tpls: true
};
$scope.download = function (version) {
var options = $scope.options;
var downloadUrl = ['ui-bootstrap-'];
if (options.tpls) {
downloadUrl.push('tpls-');
}
downloadUrl.push(version);
if (options.minified) {
downloadUrl.push('.min');
}
downloadUrl.push('.js');
return downloadUrl.join('');
};
$scope.cancel = function () {
$uibModalInstance.dismiss();
};
}
/*
* The following compatibility check is from:
*
* Bootstrap Customizer (http://getbootstrap.com/customize/)
* Copyright 2011-2014 Twitter, Inc.
*
* Licensed under the Creative Commons Attribution 3.0 Unported License. For
* details, see http://creativecommons.org/licenses/by/3.0/.
*/
var isOldBrowser;
(function () {
var supportsFile = (window.File && window.FileReader && window.FileList && window.Blob);
function failback() {
isOldBrowser = true;
}
/**
* Based on:
* Blob Feature Check v1.1.0
* https://github.com/ssorallen/blob-feature-check/
* License: Public domain (http://unlicense.org)
*/
var url = window.URL;
var svg = new Blob(
['<svg xmlns=\'http://www.w3.org/2000/svg\'></svg>'],
{ type: 'image/svg+xml;charset=utf-8' }
);
var objectUrl = url.createObjectURL(svg);
if (/^blob:/.exec(objectUrl) === null || !supportsFile) {
// `URL.createObjectURL` created a URL that started with something other
// than "blob:", which means it has been polyfilled and is not supported by
// this browser.
failback();
} else {
angular.element('<img/>')
.on('load', function () {
isOldBrowser = false;
})
.on('error', failback)
.attr('src', objectUrl);
}
})();
+323 -92
View File
@@ -1,92 +1,323 @@
body {
opacity: 1;
-webkit-transition: opacity 1s ease;
-moz-transition: opacity 1s ease;
transition: opacity 1s;
}
.ng-cloak {
opacity: 0;
}
section {
padding-top: 30px;
}
.page-header h1 > small > a {
color: #999;
}
.page-header h1 > small > a:hover {
text-decoration: none;
}
.footer {
text-align: center;
padding: 30px 0;
margin-top: 70px;
border-top: 1px solid #e5e5e5;
background-color: #f5f5f5;
}
.hero-unit {
position: relative;
padding: 40px 0;
color: #fff;
text-align: center;
text-shadow: 0 1px 3px rgba(0,0,0,.4), 0 0 30px rgba(0,0,0,.075);
background: #020031;
background: -moz-linear-gradient(45deg, #020031 0%, #6d3353 100%);
background: -webkit-gradient(linear, left bottom, right top, color-stop(0%,#020031), color-stop(100%,#6d3353));
background: -webkit-linear-gradient(45deg, #020031 0%,#6d3353 100%);
background: -o-linear-gradient(45deg, #020031 0%,#6d3353 100%);
background: -ms-linear-gradient(45deg, #020031 0%,#6d3353 100%);
background: linear-gradient(45deg, #020031 0%,#6d3353 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#020031', endColorstr='#6d3353',GradientType=1 );
-webkit-box-shadow: inset 0 3px 7px rgba(0,0,0,.2), inset 0 -3px 7px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 3px 7px rgba(0,0,0,.2), inset 0 -3px 7px rgba(0,0,0,.2);
box-shadow: inset 0 3px 7px rgba(0,0,0,.2), inset 0 -3px 7px rgba(0,0,0,.2);
border-radius: 0;
-moz-border-radius: 0;
-webkit-border-radius: 0;
-o-border-radius: 0;
}
.hero-unit .btn, .pagination-centered .btn {
float: none;
font-weight: normal;
}
.hero-unit p {
margin: 1em 0;
}
.bs-docs-social {
margin-top: 1em;
padding: 15px 0;
text-align: center;
background-color: rgba(245,245,245,0.3);
border-top: 1px solid rgba(255,255,255,0.3);
border-bottom: 1px solid rgba(221,221,221,0.3);
}
.bs-docs-social-buttons {
margin-left: 0;
margin-bottom: 0;
padding-left: 0;
list-style: none;
}
.bs-docs-social-buttons li {
display: inline-block;
padding: 5px 8px;
line-height: 1;
}
.icon-github {
background: no-repeat url('github-16px.png');
width: 16px;
height: 16px;
}
/* Not enough room on mobile for markup tab, js tab, and plunk btn.
And no one cares about plunk button on a phone anyway */
@media only screen and (max-device-width: 480px) {
#plunk-btn {
display: none;
}
}
body {
opacity: 1;
-webkit-transition: opacity 1s ease;
-moz-transition: opacity 1s ease;
transition: opacity 1s;
}
.ng-cloak {
opacity: 0;
}
.ng-invalid {
border: 1px solid red !important;
}
section {
padding-top: 30px;
}
.page-header h1 > small > a {
color: #999;
}
.page-header h1 > small > a:hover {
text-decoration: none;
}
.footer {
text-align: center;
padding: 30px 0;
margin-top: 70px;
border-top: 1px solid #e5e5e5;
background-color: #f5f5f5;
}
.bs-social {
margin-top: 20px;
margin-bottom: 20px;
text-align: center;
}
@media (min-width: 768px) {
.bs-social {
text-align: left;
}
}
.nav, .pagination, .carousel, .panel-title a {
cursor: pointer;
}
.bs-social-buttons {
display: inline-block;
margin-bottom: 0;
padding-left: 0;
list-style: none;
}
.bs-social-buttons li {
display: inline-block;
padding: 5px 8px;
line-height: 1;
}
@media (max-width: 767px) {
.visible-xs.collapse.in {
display: block!important;
}
.visible-xs.collapse {
display: none!important;
}
}
.navbar-fixed-top .collapse {
border-top: 1px solid #e7e7e7;
margin-left: -15px;
margin-right: -15px;
padding-right: 15px;
padding-left: 15px;
}
.show-grid {
margin-bottom: 15px;
}
/*
* Container
*
* Tweak to width of container.
*/
/*@media (min-width: 1200px) {
.container{
max-width: 970px;
}
}*/
/*
* Tabs
*
* Tweaks to the Tabs.
*/
.code .nav-tabs {
border-bottom: 1px solid #ccc;
}
.code pre, .code code {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.code .nav-tabs>li.active>a, .code .nav-tabs>li.active>a:hover, .code .nav-tabs>li.active>a:focus {
background-color: #f8f8f8;
border: 1px solid #ccc;
border-bottom-color: transparent;
}
/*
* Button Inverse
*
* Buttons in the masthead.
*/
.btn-outline-inverse {
color: #fff;
background-color: transparent;
border-color: #cdbfe3;
margin: 10px;
}
@media (min-width: 768px) {
.btn-outline-inverse {
width: auto;
margin: 20px 5px 20px 0;
padding: 18px 24px;
font-size: 21px;
}
}
.btn-outline-inverse:hover, .btn-outline-inverse:focus, .btn-outline-inverse:active {
color: #563d7c;
text-shadow: none;
background-color: #fff;
border-color: #fff;
}
/* Page headers */
.bs-header {
padding: 30px 15px 40px; /* side padding builds on .container 15px, so 30px */
font-size: 16px;
text-align: center;
text-shadow: 0 1px 0 rgba(0,0,0,.15);
color: #cdbfe3;
background-color: #563d7c;
background-image: url(header.png);
}
.bs-header a {
color: #fff;
font-weight: normal;
}
.bs-header h1 {
color: #fff;
}
.bs-header p {
font-weight: 200;
line-height: 1.4;
}
.bs-header .container {
position: relative;
}
@media (min-width: 768px) {
.bs-header {
font-size: 30px;
text-align: left;
}
.bs-header h1 {
font-size: 100px;
line-height: 1;
}
}
@media (min-width: 992px) {
.bs-header p {
margin-right: 25%;
}
}
.navbar-inner {
-webkit-box-shadow: 0 3px 3px rgba(0,0,0,0.175);
box-shadow: 0 3px 3px rgba(0,0,0,0.175);
}
/*
* Side navigation
*
* Scrollspy and affixed enhanced navigation to highlight sections and secondary
* sections of docs content.
*/
/* By default it's not affixed in mobile views, so undo that */
.bs-sidebar.affix {
position: static;
}
/* First level of nav */
.bs-sidenav {
margin-top: 30px;
margin-bottom: 30px;
padding-top: 10px;
padding-bottom: 10px;
text-shadow: 0 1px 0 #fff;
background-color: #f7f5fa;
border-radius: 5px;
}
/* All levels of nav */
.bs-sidebar .nav > li > a {
display: block;
color: #716b7a;
padding: 5px 20px;
}
.bs-sidebar .nav > li > a:hover,
.bs-sidebar .nav > li > a:focus {
text-decoration: none;
background-color: #e5e3e9;
border-right: 1px solid #dbd8e0;
}
.bs-sidebar .nav > .active > a,
.bs-sidebar .nav > .active:hover > a,
.bs-sidebar .nav > .active:focus > a {
font-weight: bold;
color: #563d7c;
background-color: transparent;
border-right: 1px solid #563d7c;
}
/* Nav: second level (shown on .active) */
.bs-sidebar .nav .nav {
display: none; /* Hide by default, but at >768px, show it */
margin-bottom: 8px;
}
.bs-sidebar .nav .nav > li > a {
padding-top: 3px;
padding-bottom: 3px;
padding-left: 30px;
font-size: 90%;
}
/* Show and affix the side nav when space allows it */
@media (min-width: 992px) {
.bs-sidebar .nav > .active > ul {
display: block;
}
/* Widen the fixed sidebar */
.bs-sidebar.affix,
.bs-sidebar.affix-bottom {
width: 213px;
}
.bs-sidebar.affix {
position: fixed; /* Undo the static from mobile first approach */
top: 80px;
}
.bs-sidebar.affix-bottom {
position: absolute; /* Undo the static from mobile first approach */
}
.bs-sidebar.affix-bottom .bs-sidenav,
.bs-sidebar.affix .bs-sidenav {
margin-top: 0;
margin-bottom: 0;
}
}
@media (min-width: 1200px) {
/* Widen the fixed sidebar again */
.bs-sidebar.affix-bottom,
.bs-sidebar.affix {
width: 263px;
}
}
/* Not enough room on mobile for markup tab, js tab, and plunk btn.
And no one cares about plunk button on a phone anyway */
@media only screen and (max-device-width: 480px) {
#plunk-btn {
display: none;
}
}
.navbar-nav .dropdown .navbar-brand {
max-width: 100%;
margin-right: inherit;
margin-left: inherit;
}
.header-placeholder {
height: 50px;
}
@media screen and (min-width: 768px) {
.dropdown.open > .navbar-brand + .dropdown-menu {
left: 10px;
}
.header-placeholder {
height: 50px;
}
.navbar-nav .dropdown .navbar-brand {
max-width: 200px;
margin-right: 5px;
margin-left: 10px;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

+60 -58
View File
@@ -1,58 +1,60 @@
angular.module('plunker', [])
.factory('plunkGenerator', function ($document) {
return function (ngVersion, bsVersion, version, module, content) {
var form = angular.element('<form style="display: none;" method="post" action="http://plnkr.co/edit/?p=preview" target="_blank"></form>');
var addField = function (name, value) {
var input = angular.element('<input type="hidden" name="' + name + '">');
input.attr('value', value);
form.append(input);
};
var indexContent = function (content, version) {
return '<!doctype html>\n' +
'<html ng-app="plunker">\n' +
' <head>\n' +
' <script src="http://ajax.googleapis.com/ajax/libs/angularjs/'+ngVersion+'/angular.js"></script>\n' +
' <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-'+version+'.js"></script>\n' +
' <script src="example.js"></script>\n' +
' <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/'+bsVersion+'/css/bootstrap-combined.min.css" rel="stylesheet">\n' +
' </head>\n' +
' <body>\n\n' +
content + '\n' +
' </body>\n' +
'</html>\n';
};
var scriptContent = function(content) {
return "angular.module('plunker', ['ui.bootstrap']);" + "\n" + content;
};
addField('description', 'http://angular-ui.github.io/bootstrap/');
addField('files[index.html]', indexContent(content.markup, version));
addField('files[example.js]', scriptContent(content.javascript));
$document.find('body').append(form);
form[0].submit();
form.remove();
};
})
.controller('PlunkerCtrl', function ($scope, plunkGenerator) {
$scope.content = {};
$scope.edit = function (ngVersion, bsVersion, version, module) {
plunkGenerator(ngVersion, bsVersion, version, module, $scope.content);
};
})
.directive('plunkerContent', function () {
return {
link:function (scope, element, attrs) {
scope.$parent.content[attrs.plunkerContent] = element.text();
}
}
});
angular.module('plunker', [])
.factory('plunkGenerator', function ($document) {
return function (ngVersion, bsVersion, version, module, content) {
var form = angular.element('<form style="display: none;" method="post" action="https://plnkr.co/edit/?p=preview" target="_blank"></form>');
var addField = function (name, value) {
var input = angular.element('<input type="hidden" name="' + name + '">');
input.attr('value', value);
form.append(input);
};
var indexContent = function (content, version) {
return '<!doctype html>\n' +
'<html ng-app="ui.bootstrap.demo">\n' +
' <head>\n' +
' <script src="//ajax.googleapis.com/ajax/libs/angularjs/'+ngVersion+'/angular.js"></script>\n' +
' <script src="//ajax.googleapis.com/ajax/libs/angularjs/'+ngVersion+'/angular-animate.js"></script>\n' +
' <script src="//ajax.googleapis.com/ajax/libs/angularjs/'+ngVersion+'/angular-sanitize.js"></script>\n' +
' <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-'+version+'.js"></script>\n' +
' <script src="example.js"></script>\n' +
' <link href="//netdna.bootstrapcdn.com/bootstrap/'+bsVersion+'/css/bootstrap.min.css" rel="stylesheet">\n' +
' </head>\n' +
' <body>\n\n' +
content + '\n' +
' </body>\n' +
'</html>\n';
};
var scriptContent = function(content) {
return "angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);" + "\n" + content;
};
addField('description', 'http://angular-ui.github.io/bootstrap/');
addField('files[index.html]', indexContent(content.markup, version));
addField('files[example.js]', scriptContent(content.javascript));
$document.find('body').append(form);
form[0].submit();
form.remove();
};
})
.controller('PlunkerCtrl', function ($scope, plunkGenerator) {
$scope.content = {};
$scope.edit = function (ngVersion, bsVersion, version, module) {
plunkGenerator(ngVersion, bsVersion, version, module, $scope.content);
};
})
.directive('plunkerContent', function () {
return {
link:function (scope, element, attrs) {
scope.content[attrs.plunkerContent] = element.text().trim();
}
}
});
+8 -8
View File
@@ -14,18 +14,18 @@ pre {
code {
border: 1px solid #eaeaea;
margin: 0px 2px;
padding: 0px 5px;
margin: 0 2px;
padding: 0 5px;
font-size: 12px;
}
pre code {
border: 0px;
padding: 0px;
margin: 0px;
-moz-border-radius: 0px;
-webkit-border-radius: 0px;
border-radius: 0px;
border: 0;
padding: 0;
margin: 0;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
}
pre, code {
+2 -2
View File
@@ -311,9 +311,9 @@ window['Rainbow'] = (function() {
_processPattern(regex, pattern, code, callback);
};
// every 100 items we process let's call set timeout
// every 50 items we process let's call set timeout
// to let the ui breathe a little
return match_counter % 100 > 0 ? nextCall() : setTimeout(nextCall, 0);
return match_counter % 50 > 0 ? nextCall() : setTimeout(nextCall, 0);
};
// if this is not a child match and it falls inside of another
-524
View File
@@ -1,524 +0,0 @@
/*
Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012
*/
.select2-container {
position: relative;
display: inline-block;
/* inline-block for ie7 */
zoom: 1;
*display: inline;
vertical-align: top;
}
.select2-container,
.select2-drop,
.select2-search,
.select2-search input{
/*
Force border-box so that % widths fit the parent
container without overlap because of margin/padding.
More Info : http://www.quirksmode.org/css/box.html
*/
-moz-box-sizing: border-box; /* firefox */
-ms-box-sizing: border-box; /* ie */
-webkit-box-sizing: border-box; /* webkit */
-khtml-box-sizing: border-box; /* konqueror */
box-sizing: border-box; /* css3 */
}
.select2-container .select2-choice {
background-color: #fff;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white));
background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%);
background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%);
background-image: -o-linear-gradient(bottom, #eeeeee 0%, #ffffff 50%);
background-image: -ms-linear-gradient(top, #eeeeee 0%, #ffffff 50%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#ffffff', GradientType = 0);
background-image: linear-gradient(top, #eeeeee 0%, #ffffff 50%);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #aaa;
display: block;
overflow: hidden;
white-space: nowrap;
position: relative;
height: 26px;
line-height: 26px;
padding: 0 0 0 8px;
color: #444;
text-decoration: none;
}
.select2-container.select2-drop-above .select2-choice
{
border-bottom-color: #aaa;
-webkit-border-radius:0px 0px 4px 4px;
-moz-border-radius:0px 0px 4px 4px;
border-radius:0px 0px 4px 4px;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.9, white));
background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 90%);
background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 90%);
background-image: -o-linear-gradient(bottom, #eeeeee 0%, white 90%);
background-image: -ms-linear-gradient(top, #eeeeee 0%,#ffffff 90%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 );
background-image: linear-gradient(top, #eeeeee 0%,#ffffff 90%);
}
.select2-container .select2-choice span {
margin-right: 26px;
display: block;
overflow: hidden;
white-space: nowrap;
-o-text-overflow: ellipsis;
-ms-text-overflow: ellipsis;
text-overflow: ellipsis;
}
.select2-container .select2-choice abbr {
display: block;
position: absolute;
right: 26px;
top: 8px;
width: 12px;
height: 12px;
font-size: 1px;
background: url('select2.png') right top no-repeat;
cursor: pointer;
text-decoration: none;
border:0;
outline: 0;
}
.select2-container .select2-choice abbr:hover {
background-position: right -11px;
cursor: pointer;
}
.select2-drop {
background: #fff;
color: #000;
border: 1px solid #aaa;
border-top: 0;
position: absolute;
top: 100%;
-webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
-moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
-o-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
z-index: 9999;
width:100%;
margin-top:-1px;
-webkit-border-radius: 0 0 4px 4px;
-moz-border-radius: 0 0 4px 4px;
border-radius: 0 0 4px 4px;
}
.select2-drop.select2-drop-above {
-webkit-border-radius: 4px 4px 0px 0px;
-moz-border-radius: 4px 4px 0px 0px;
border-radius: 4px 4px 0px 0px;
margin-top:1px;
border-top: 1px solid #aaa;
border-bottom: 0;
-webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
-moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
-o-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
}
.select2-container .select2-choice div {
-webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
background: #ccc;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
background-image: -o-linear-gradient(bottom, #ccc 0%, #eee 60%);
background-image: -ms-linear-gradient(top, #cccccc 0%, #eeeeee 60%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#cccccc', endColorstr = '#eeeeee', GradientType = 0);
background-image: linear-gradient(top, #cccccc 0%, #eeeeee 60%);
border-left: 1px solid #aaa;
position: absolute;
right: 0;
top: 0;
display: block;
height: 100%;
width: 18px;
}
.select2-container .select2-choice div b {
background: url('select2.png') no-repeat 0 1px;
display: block;
width: 100%;
height: 100%;
}
.select2-search {
display: inline-block;
white-space: nowrap;
z-index: 10000;
min-height: 26px;
width: 100%;
margin: 0;
padding-left: 4px;
padding-right: 4px;
}
.select2-search-hidden {
display: block;
position: absolute;
left: -10000px;
}
.select2-search input {
background: #fff url('select2.png') no-repeat 100% -22px;
background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
background: url('select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
background: url('select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
padding: 4px 20px 4px 5px;
outline: 0;
border: 1px solid #aaa;
font-family: sans-serif;
font-size: 1em;
width:100%;
margin:0;
height:auto !important;
min-height: 26px;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
border-radius: 0;
-moz-border-radius: 0;
-webkit-border-radius: 0;
}
.select2-drop.select2-drop-above .select2-search input
{
margin-top:4px;
}
.select2-search input.select2-active {
background: #fff url('spinner.gif') no-repeat 100%;
background: url('spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
background: url('spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
background: url('spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
background: url('spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
background: url('spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
background: url('spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
}
.select2-container-active .select2-choice,
.select2-container-active .select2-choices {
-webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
-moz-box-shadow : 0 0 5px rgba(0,0,0,.3);
-o-box-shadow : 0 0 5px rgba(0,0,0,.3);
box-shadow : 0 0 5px rgba(0,0,0,.3);
border: 1px solid #5897fb;
outline: none;
}
.select2-dropdown-open .select2-choice {
border: 1px solid #aaa;
border-bottom-color: transparent;
-webkit-box-shadow: 0 1px 0 #fff inset;
-moz-box-shadow : 0 1px 0 #fff inset;
-o-box-shadow : 0 1px 0 #fff inset;
box-shadow : 0 1px 0 #fff inset;
background-color: #eee;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee));
background-image: -webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%);
background-image: -moz-linear-gradient(center bottom, white 0%, #eeeeee 50%);
background-image: -o-linear-gradient(bottom, white 0%, #eeeeee 50%);
background-image: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 50%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 );
background-image: linear-gradient(top, #ffffff 0%,#eeeeee 50%);
-webkit-border-bottom-left-radius : 0;
-webkit-border-bottom-right-radius: 0;
-moz-border-radius-bottomleft : 0;
-moz-border-radius-bottomright: 0;
border-bottom-left-radius : 0;
border-bottom-right-radius: 0;
}
.select2-dropdown-open .select2-choice div {
background: transparent;
border-left: none;
}
.select2-dropdown-open .select2-choice div b {
background-position: -18px 1px;
}
/* results */
.select2-results {
margin: 4px 4px 4px 0;
padding: 0 0 0 4px;
position: relative;
overflow-x: hidden;
overflow-y: auto;
max-height: 200px;
}
.select2-results ul.select2-result-sub {
margin: 0 0 0 0;
}
.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }
.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }
.select2-results li {
list-style: none;
display: list-item;
}
.select2-results li.select2-result-with-children > .select2-result-label {
font-weight: bold;
}
.select2-results .select2-result-label {
padding: 3px 7px 4px;
margin: 0;
cursor: pointer;
}
.select2-results .select2-highlighted {
background: #3875d7;
color: #fff;
}
.select2-results li em {
background: #feffde;
font-style: normal;
}
.select2-results .select2-highlighted em {
background: transparent;
}
.select2-results .select2-no-results,
.select2-results .select2-searching,
.select2-results .select2-selection-limit {
background: #f4f4f4;
display: list-item;
}
/*
disabled look for already selected choices in the results dropdown
.select2-results .select2-disabled.select2-highlighted {
color: #666;
background: #f4f4f4;
display: list-item;
cursor: default;
}
.select2-results .select2-disabled {
background: #f4f4f4;
display: list-item;
cursor: default;
}
*/
.select2-results .select2-disabled {
display: none;
}
.select2-more-results.select2-active {
background: #f4f4f4 url('spinner.gif') no-repeat 100%;
}
.select2-more-results {
background: #f4f4f4;
display: list-item;
}
/* disabled styles */
.select2-container.select2-container-disabled .select2-choice {
background-color: #f4f4f4;
background-image: none;
border: 1px solid #ddd;
cursor: default;
}
.select2-container.select2-container-disabled .select2-choice div {
background-color: #f4f4f4;
background-image: none;
border-left: 0;
}
/* multiselect */
.select2-container-multi .select2-choices {
background-color: #fff;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
background-image: -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
background-image: linear-gradient(top, #eeeeee 1%, #ffffff 15%);
border: 1px solid #aaa;
margin: 0;
padding: 0;
cursor: text;
overflow: hidden;
height: auto !important;
height: 1%;
position: relative;
}
.select2-container-multi .select2-choices {
min-height: 26px;
}
.select2-container-multi.select2-container-active .select2-choices {
-webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
-moz-box-shadow : 0 0 5px rgba(0,0,0,.3);
-o-box-shadow : 0 0 5px rgba(0,0,0,.3);
box-shadow : 0 0 5px rgba(0,0,0,.3);
border: 1px solid #5897fb;
outline: none;
}
.select2-container-multi .select2-choices li {
float: left;
list-style: none;
}
.select2-container-multi .select2-choices .select2-search-field {
white-space: nowrap;
margin: 0;
padding: 0;
}
.select2-container-multi .select2-choices .select2-search-field input {
color: #666;
background: transparent !important;
font-family: sans-serif;
font-size: 100%;
height: 15px;
padding: 5px;
margin: 1px 0;
outline: 0;
border: 0;
-webkit-box-shadow: none;
-moz-box-shadow : none;
-o-box-shadow : none;
box-shadow : none;
}
.select2-container-multi .select2-choices .select2-search-field input.select2-active {
background: #fff url('spinner.gif') no-repeat 100% !important;
}
.select2-default {
color: #999 !important;
}
.select2-container-multi .select2-choices .select2-search-choice {
-webkit-border-radius: 3px;
-moz-border-radius : 3px;
border-radius : 3px;
-moz-background-clip : padding;
-webkit-background-clip: padding-box;
background-clip : padding-box;
background-color: #e4e4e4;
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
-moz-box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
color: #333;
border: 1px solid #aaaaaa;
line-height: 13px;
padding: 3px 5px 3px 18px;
margin: 3px 0 3px 5px;
position: relative;
cursor: default;
}
.select2-container-multi .select2-choices .select2-search-choice span {
cursor: default;
}
.select2-container-multi .select2-choices .select2-search-choice-focus {
background: #d4d4d4;
}
.select2-search-choice-close {
display: block;
position: absolute;
right: 3px;
top: 4px;
width: 12px;
height: 13px;
font-size: 1px;
background: url('select2.png') right top no-repeat;
outline: none;
}
.select2-container-multi .select2-search-choice-close {
left: 3px;
}
.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
background-position: right -11px;
}
.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
background-position: right -11px;
}
/* disabled styles */
.select2-container-multi.select2-container-disabled .select2-choices{
background-color: #f4f4f4;
background-image: none;
border: 1px solid #ddd;
cursor: default;
}
.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
background-image: none;
background-color: #f4f4f4;
border: 1px solid #ddd;
padding: 3px 5px 3px 5px;
}
.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close {
display: none;
}
/* end multiselect */
.select2-result-selectable .select2-match,
.select2-result-unselectable .select2-result-selectable .select2-match { text-decoration: underline; }
.select2-result-unselectable .select2-match { text-decoration: none; }
.select2-offscreen { position: absolute; left: -10000px; }
/* Retina-ize icons */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5) {
.select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice div b {
background-image: url(select2x2.png) !important;
background-repeat: no-repeat !important;
background-size: 60px 40px !important;
}
.select2-search input {
background-position: 100% -21px !important;
}
}
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 613 B

@@ -0,0 +1,97 @@
/*
* https://github.com/alicelieutier/smoothScroll/
* A teeny tiny, standard compliant, smooth scroll script with ease-in-out effect and no jQuery (or any other dependancy, FWIW).
* MIT License
*/
window.smoothScroll = (function(){
// We do not want this script to be applied in browsers that do not support those
// That means no smoothscroll on IE9 and below.
if(document.querySelectorAll === void 0 || window.pageYOffset === void 0 || history.pushState === void 0) { return; }
// Get the top position of an element in the document
var getTop = function(element) {
// return value of html.getBoundingClientRect().top ... IE : 0, other browsers : -pageYOffset
if(element.nodeName === 'HTML') return -window.pageYOffset
return element.getBoundingClientRect().top + window.pageYOffset;
}
// ease in out function thanks to:
// http://blog.greweb.fr/2012/02/bezier-curve-based-easing-functions-from-concept-to-implementation/
var easeInOutCubic = function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 }
// calculate the scroll position we should be in
// given the start and end point of the scroll
// the time elapsed from the beginning of the scroll
// and the total duration of the scroll (default 500ms)
var position = function(start, end, elapsed, duration) {
if (elapsed > duration) return end;
return start + (end - start) * easeInOutCubic(elapsed / duration); // <-- you can change the easing funtion there
// return start + (end - start) * (elapsed / duration); // <-- this would give a linear scroll
}
// we use requestAnimationFrame to be called by the browser before every repaint
// if the first argument is an element then scroll to the top of this element
// if the first argument is numeric then scroll to this location
// if the callback exist, it is called when the scrolling is finished
var smoothScroll = function(el, duration, callback){
duration = duration || 500;
var start = window.pageYOffset;
if (typeof el === 'number') {
var end = parseInt(el);
} else {
var end = getTop(el);
}
var clock = Date.now();
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
function(fn){window.setTimeout(fn, 15);};
var step = function(){
var elapsed = Date.now() - clock;
window.scroll(0, position(start, end, elapsed, duration));
if (elapsed > duration) {
if (typeof callback === 'function') {
callback(el);
}
} else {
requestAnimationFrame(step);
}
}
step();
}
var linkHandler = function(ev) {
ev.preventDefault();
if (location.hash !== this.hash) {
//NOTE(@ajoslin): Changed this line to stop $digest errors
//window.history.pushState(null, null, this.hash)
angular.element(document).injector().get('$location').hash(this.hash);
}
// using the history api to solve issue #1 - back doesn't work
// most browser don't update :target when the history api is used:
// THIS IS A BUG FROM THE BROWSERS.
// change the scrolling duration in this call
var targetEl = document.getElementById(this.hash.substring(1));
if (targetEl) {
smoothScroll(document.getElementById(this.hash.substring(1)), 500, function(el) {
location.replace('#' + el.id)
// this will cause the :target to be activated.
});
}
}
// We look for all the internal links in the documents and attach the smoothscroll function
document.addEventListener("DOMContentLoaded", function () {
var internal = document.querySelectorAll('a[href^="#"]'), a;
for(var i=internal.length; a=internal[--i];){
a.addEventListener("click", linkHandler, false);
}
});
// return smoothscroll API
return smoothScroll;
})();
File diff suppressed because one or more lines are too long
-117
View File
@@ -1,117 +0,0 @@
angular.module('ui.config', []).value('ui.config', {});
angular.module('ui.directives', ['ui.config']);
/**
* Enhanced Select2 Dropmenus
*
* @AJAX Mode - When in this mode, your value will be an object (or array of objects) of the data used by Select2
* This change is so that you do not have to do an additional query yourself on top of Select2's own query
* @params [options] {object} The configuration options passed to $.fn.select2(). Refer to the documentation
*/
angular.module('ui.directives').directive('uiSelect2', ['ui.config', '$http', function (uiConfig, $http) {
var options = {};
if (uiConfig.select2) {
angular.extend(options, uiConfig.select2);
}
return {
require: '?ngModel',
compile: function (tElm, tAttrs) {
var watch,
repeatOption,
repeatAttr,
isSelect = tElm.is('select'),
isMultiple = (tAttrs.multiple !== undefined);
// Enable watching of the options dataset if in use
if (tElm.is('select')) {
repeatOption = tElm.find('option[ng-repeat], option[data-ng-repeat]');
if (repeatOption.length) {
repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');
watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();
}
}
return function (scope, elm, attrs, controller) {
// instance-specific options
var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
if (isSelect) {
// Use <select multiple> instead
delete opts.multiple;
delete opts.initSelection;
} else if (isMultiple) {
opts.multiple = true;
}
if (controller) {
// Watch the model for programmatic changes
controller.$render = function () {
if (isSelect) {
elm.select2('val', controller.$modelValue);
} else {
if (isMultiple && !controller.$modelValue) {
elm.select2('data', []);
} else if (angular.isObject(controller.$modelValue)) {
elm.select2('data', controller.$modelValue);
} else {
elm.select2('val', controller.$modelValue);
}
}
};
// Watch the options dataset for changes
if (watch) {
scope.$watch(watch, function (newVal, oldVal, scope) {
if (!newVal) return;
// Delayed so that the options have time to be rendered
setTimeout(function () {
elm.select2('val', controller.$viewValue);
// Refresh angular to remove the superfluous option
elm.trigger('change');
});
});
}
if (!isSelect) {
// Set the view and model value and update the angular template manually for the ajax/multiple select2.
elm.bind("change", function () {
scope.$apply(function () {
controller.$setViewValue(elm.select2('data'));
});
});
if (opts.initSelection) {
var initSelection = opts.initSelection;
opts.initSelection = function (element, callback) {
initSelection(element, function (value) {
controller.$setViewValue(value);
callback(value);
});
};
}
}
}
attrs.$observe('disabled', function (value) {
elm.select2(value && 'disable' || 'enable');
});
if (attrs.ngMultiple) {
scope.$watch(attrs.ngMultiple, function(newVal) {
elm.select2(opts);
});
}
// Set initial value since Angular doesn't
elm.val(scope.$eval(attrs.ngModel));
// Initialize the plugin late so that the injected DOM does not disrupt the template compiler
setTimeout(function () {
elm.select2(opts);
});
};
}
};
}]);
+298 -165
View File
@@ -1,202 +1,272 @@
<!DOCTYPE html>
<html lang="en" ng-app="bootstrapDemoApp" id="top">
<html lang="en" ng-app="ui.bootstrap.demo" id="top">
<head>
<meta charset="utf-8">
<title>Angular directives for Twitter's Bootstrap</title>
<meta name="description" content="AngularJS (Angular) native directives for Twitter Bootstrap. Small footprint (5kB gzipped!), no 3rd party JS dependencies (jQuery, bootstrap JS) required! Widgets: <% demoModules.forEach(function(module) { %><%= module.displayName %>, <% }); %>">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="icon" href="assets/favicon.ico" />
<title>Angular directives for Bootstrap</title>
<meta name="description" content="AngularJS (Angular) native directives for Bootstrap. Small footprint (5kB gzipped!), no 3rd party JS dependencies (jQuery, bootstrap JS) required! Widgets: <% demoModules.forEach(function(module) { %><%= module.displayName %>, <% }); %>">
<meta name="google-site-verification" content="7lc5HyceLDqpV_6oNHteYFfxDJH7-S3DwnJKtNUKcRg" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/<%= ngversion %>/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fastclick/0.6.7/fastclick.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.0.0/FileSaver.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jszip/2.4.0/jszip.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/<%= ngversion %>/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/<%= ngversion %>/angular-animate.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/<%= ngversion %>/angular-touch.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/<%= ngversion %>/angular-sanitize.js"></script>
<script src="ui-bootstrap-tpls-<%= pkg.version%>.min.js"></script>
<script src="assets/select2.js"></script>
<script src="assets/ui-select2.js"></script>
<script src="assets/plunker.js"></script>
<script src="assets/app.js"></script>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/<%= bsversion %>/css/bootstrap.min.css" rel="stylesheet"/>
<link href="//netdna.bootstrapcdn.com/bootstrap/<%= bsversion %>/css/bootstrap.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="assets/rainbow.css"/>
<link rel="stylesheet" href="assets/demo.css"/>
<link rel="stylesheet" href="assets/select2.css"/>
<link rel="author" href="https://github.com/angular-ui/bootstrap/graphs/contributors">
</head>
<body class="ng-cloak" ng-controller="MainCtrl">
<header class="navbar navbar-fixed-top">
<div class="navbar-inner">
<header class="navbar navbar-default navbar-fixed-top navbar-inner">
<div class="container">
<div class="dropdown pull-left">
<a class="brand dropdown-toggle" role="button" data-toggle="dropdown" href="#">
UI Bootstrap
<b class="caret"></b>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><a href="https://github.com/angular-ui/"><strong>Related Projects:</strong></a></li>
<li class="divider"></li>
<li><a href="http://angular-ui.github.io/">AngularUI</a></li>
<li><a href="http://angular-ui.github.io/ng-grid/">Grid</a></li>
<li><a href="https://github.com/angular-ui/AngularJs.tmbundle">AngularJS.tmbundle</a></li>
<li><a href="http://angular-ui.github.io/router/">Router <span class="label label-success">New!</span></a></li>
<li><a href="http://angular-ui.github.io/Tips-n-Tricks/">Tips-n-Tricks <span class="label">WIP</span></a></li>
</ul>
</div>
<div class="nav-collapse">
<ul class="nav">
<li>
<a href="#" role="button" class="dropdown-toggle">
Directives <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<% demoModules.forEach(function(module) { %>
<li><a href="#<%= module.name %>"><%= module.displayName %></a></li>
<% }); %>
</ul>
</li>
<li><a href="#getting_started">Getting started</a></li>
</ul>
</div>
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-3" ng-click="isCollapsed = !isCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand visible-xs" href="#">UI Bootstrap</a>
</div>
<nav class="hidden-xs">
<ul class="nav navbar-nav">
<a href="#top" role="button" class="navbar-brand">
UI Bootstrap
</a>
<li class="dropdown" uib-dropdown>
<a role="button" class="dropdown-toggle" uib-dropdown-toggle>
Directives <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<% demoModules.forEach(function(module) { %><li><a href="#<%= module.name %>"><%= module.displayName %></a></li><% }); %>
</ul>
</li>
<li><a href="#getting_started">Getting started</a></li>
<li class="dropdown" uib-dropdown>
<a role="button" class="dropdown-toggle" uib-dropdown-toggle>
Previous docs <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li ng-repeat="version in oldDocs">
<a ng-href="{{version.url}}">{{version.version}}</a>
</li>
</ul>
</li>
</ul>
</nav>
<nav class="visible-xs" uib-collapse="!isCollapsed">
<ul class="nav navbar-nav">
<li><a href="#getting_started" ng-click="isCollapsed = !isCollapsed">Getting started</a></li>
<li><a href="#directives_small" ng-click="isCollapsed = !isCollapsed">Directives</a></li>
</ul>
</nav>
</div>
</div>
</header>
<div style="margin: 32px;"></div>
<div class="header-placeholder"></div>
<div role="main">
<header class="hero-unit" id="overview">
<header class="bs-header text-center" id="overview">
<div class="container">
<h1>
UI Bootstrap
</h1>
<p>Bootstrap components written in pure <strong><a href="http://angularjs.org">AngularJS</a></strong> by the <strong><a
href="http://angular-ui.github.io">AngularUI Team</a></strong></p>
<p>Bootstrap components written in pure <a href="http://angularjs.org">AngularJS</a> by the <a
href="http://angular-ui.github.io">AngularUI Team</a></p>
<p class="btn-group">
<a class="btn" href="https://github.com/angular-ui/bootstrap"><i class="icon-github"></i> Code on Github</a>
<a class="btn btn-primary" href="https://github.com/angular-ui/bootstrap/tree/gh-pages">
<i class="icon-download-alt icon-white"></i> Download <small>(<%= pkg.version%>)</small>
</a>
<a class="btn" ng-click="showBuildModal()"><i class="icon-wrench"></i> Create a Build</a>
<p>
<a class="btn btn-outline-inverse btn-lg" href="https://github.com/angular-ui/bootstrap"><i class="icon-github"></i>Code on Github</a>
<button type="button" class="btn btn-outline-inverse btn-lg" ng-click="showDownloadModal()">
<i class="glyphicon glyphicon-download-alt"></i> Download <small>(<%= pkg.version%>)</small>
</button>
<button type="button" class="btn btn-outline-inverse btn-lg" ng-click="showBuildModal()"><i class="glyphicon glyphicon-wrench"></i> Create a Build</button>
</p>
</div>
<div class="bs-docs-social">
<div class="container">
<ul class="bs-docs-social-buttons">
<li>
<iframe src="http://ghbtns.com/github-btn.html?user=angular-ui&repo=bootstrap&type=watch&count=true"
allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
</li>
<li>
<iframe src="http://ghbtns.com/github-btn.html?user=angular-ui&repo=bootstrap&type=fork&count=true"
allowtransparency="true" frameborder="0" scrolling="0" width="95" height="20"></iframe>
</li>
<li>
<a href="https://twitter.com/share" class="twitter-share-button"
data-hashtags="angularjs">Tweet</a>
<script>!function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");</script>
</li>
<li>
<!-- Place this tag where you want the +1 button to render. -->
<div class="g-plusone" data-size="medium"></div>
<div class="bs-social container">
<ul class="bs-social-buttons">
<li>
<iframe src="//ghbtns.com/github-btn.html?user=angular-ui&repo=bootstrap&type=watch&count=true"
allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
</li>
<li>
<iframe src="//ghbtns.com/github-btn.html?user=angular-ui&repo=bootstrap&type=fork&count=true"
allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
</li>
<li>
<a href="https://twitter.com/share" class="twitter-share-button"
data-hashtags="angularjs">Tweet</a>
<script>!function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");</script>
</li>
<li>
<!-- Place this tag where you want the +1 button to render. -->
<div class="g-plusone" data-size="medium"></div>
<!-- Place this tag after the last +1 button tag. -->
<script type="text/javascript">
(function () {
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
</li>
</ul>
</div>
<!-- Place this tag after the last +1 button tag. -->
<script type="text/javascript">
(function () {
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
</li>
</ul>
</div>
</header>
<div class="container">
<div class="row">
<div class="col-md-12">
<section class="bs-sidebar visible-xs" id="directives_small">
<ul class="nav bs-sidenav">
<li><a href="#"><strong>Directives</strong></a></li>
<% demoModules.forEach(function(module) { %>
<li><a href="#<%= module.name %>"><%= module.displayName %></a></li>
<% }); %>
</ul>
</section>
<section id="getting_started">
<div class="page-header">
<h1>Getting started</h1>
</div>
<div class="row">
<div class="span12">
<section id="getting_started">
<div class="page-header">
<h1>Getting started</h1>
</div>
<h3>Angular 2</h3>
<p>
For Angular 2 support, check out
<a href="https://ng-bootstrap.github.io" target="_blank">
ng-bootstrap
</a>, created by the UI Bootstrap team.
</p>
<h3>Dependencies</h3>
<p>
This repository contains a set of <strong>native AngularJS directives</strong> based on
Twitter Bootstrap's markup and CSS. As a result no dependency on jQuery or Bootstrap's
Bootstrap's markup and CSS. As a result no dependency on jQuery or Bootstrap's
JavaScript is required. The <strong>only required dependencies</strong> are:
</p>
<ul>
<li>AngularJS (minimal version 1.0.4 or 1.1.2)</li>
<li>Bootstrap CSS</li>
<li><a href="http://angularjs.org" target="_blank">AngularJS</a> (requires AngularJS 1.4.x or higher, tested with <%= ngversion %>).
0.14.3 is the last version of this library that supports AngularJS 1.3.x and
0.12.0 is the last version that supports AngularJS 1.2.x.</li>
<li><a href="http://angularjs.org" target="_blank">Angular-animate</a> (the version should match with your angular's, tested with <%= ngversion %>) if you plan in using animations, you need to load angular-animate as well.</li>
<li><a href="http://angularjs.org" target="_blank">Angular-touch</a> (the version should match with your angular's, tested with <%= ngversion %>) if you plan in using swipe actions, you need to load angular-touch as well.</li>
<li><a href="http://getbootstrap.com" target="_blank">Bootstrap CSS</a> (tested with version <%= bsversion %>).
This version of the library (<%= pkg.version%>) works only with Bootstrap CSS in version 3.x.
0.8.0 is the last version of this library that supports Bootstrap CSS in version 2.3.x.
</li>
</ul>
<h3>Files to download</h3>
<p>
Build files for all directives are distributed in several flavours: minified for production usage, un-minified
for development, with or without templates. All the options are described and can be
<a href="https://github.com/angular-ui/bootstrap/tree/gh-pages">downloaded from here</a>.
<a href="https://github.com/angular-ui/bootstrap/tree/gh-pages">downloaded from here</a>. It should be noted that the <code>-tpls</code> files contain the templates bundled in JavaScript, while the regular version does not contain the bundled templates. For more information, check out the FAQ <a href="https://github.com/angular-ui/bootstrap/wiki/FAQ#full-explanation">here</a> and the README <a href="https://github.com/angular-ui/bootstrap/tree/gh-pages#build-files">here</a>.
</p>
<p>Alternativelly, if you are only interested in a subset of directives, you can
<a ng-click="showBuildModal()">create your own build</a>.
</p>
<p>Whichever method you choose the good news that the overall size of a download is very small:
&lt;20kB for all directives (~5kB with gzip compression!)</p>
<p>Whichever method you choose the good news that the overall size of a download is fairly small:
122K minified for all directives with templates and 98K without (~31kB with gzip
compression, with templates, and 28K gzipped without)</p>
<h3>Installation</h3>
<p>As soon as you've got all the files downloaded and included in your page you just need to declare
a dependency on the <code>ui.bootstrap</code> <a href="http://docs.angularjs.org/guide/module">module</a>:<br>
<code>angular.module('myModule', ['ui.bootstrap']);</code>
<pre><code>angular.module('myModule', ['ui.bootstrap']);</code></pre>
</p>
<p>If you are using UI Bootstrap in the CSP mode, e.g. in an extension, make sure you link to the <code>ui-bootstrap-csp.css</code> in your HTML manually.</p>
<p>You can fork one of the plunkers from this page to see a working example of what is described here.</p>
</div>
</div>
</section>
<h3>Migration to prefixes</h3>
<p>Since version 0.14.0 we started to prefix all our components. If you are upgrading from ui-bootstrap 0.13.4 or earlier,
check our <a href="https://github.com/angular-ui/bootstrap/wiki/Migration-guide-for-prefixes">migration guide</a>.</p>
<h3>CSS</h3>
<p>Original Bootstrap's CSS depends on empty <code>href</code> attributes to style cursors for several components (pagination, tabs etc.).
But in AngularJS adding empty <code>href</code> attributes to link tags will cause unwanted route changes. This is why we need to remove empty <code>href</code> attributes from directive templates and as a result styling is not applied correctly. The remedy is simple, just add the following styling to your application: <pre><code>.nav, .pagination, .carousel, .panel-title a { cursor: pointer; }</code></pre>
</p>
<h3>FAQ</h3>
<p>Please check <a href="https://github.com/angular-ui/bootstrap/wiki/FAQ" target="_blank">our FAQ section</a> for common problems / solutions.</p>
<h3>Reading the documentation</h3>
<p>
Each of the components provided in <code>ui-bootstrap</code> have documentation and interactive Plunker examples.
</p>
<p>
For the directives, we list the different attributes with their default values. In addition to this, some settings have a badge on it:
<% demoModules.forEach(function(module) { %>
<section id="<%= module.name %>">
<div class="page-header">
<h1><%= module.displayName %><small>
(<a target="_blank" href="https://github.com/angular-ui/bootstrap/tree/master/src/<%= module.name %>">ui.bootstrap.<%= module.name %></a>)
</small></h1>
</div>
<div class="row">
<div class="span6">
<%= module.docs.html %>
</div>
<div class="span6">
<%= module.docs.md %>
<ul>
<li><i class="glyphicon glyphicon-eye-open"></i> - This setting has an angular $watch listener applied to it.</li>
<li><small class="badge">B</small> - This setting is a boolean. It doesn't need a parameter.</li>
<li><small class="badge">C</small> - This setting can be configured globally in a constant service*.</li>
<li><small class="badge">$</small> - This setting expects an angular expression instead of a literal string. If the expression support a boolean / integer, you can pass it directly.</li>
<li><small class="badge">readonly</small> - This setting is readonly.</li>
</ul>
</p>
<p>
For the services (you will recognize them with the <code>$</code> prefix), we list all the possible parameters you can pass to them and their default values if any.
</p>
<p>
* Some directives have a config service that follows the next pattern: <code>uibDirectiveConfig</code>. The service's settings use camel case. The services can be configured in a <code>.config</code> function for example.
</p>
</section>
<% demoModules.forEach(function(module) { %>
<section id="<%= module.name %>">
<div class="page-header">
<h1><%= module.displayName %><small>
(<a target="_blank" href="https://github.com/angular-ui/bootstrap/tree/master/src/<%= module.name %>">ui.bootstrap.<%= module.name %></a>)
</small></h1>
</div>
<div class="row">
<div class="col-md-6 show-grid">
<%= module.docs.html %>
</div>
<div class="col-md-6">
<%= module.docs.md %>
</div>
</div>
<hr>
<div class="row code">
<div class="col-md-12" ng-controller="PlunkerCtrl">
<div class="pull-right">
<button type="button" class="btn btn-info plunk-btn" ng-click="edit('<%= ngversion%>', '<%= bsversion %>', '<%= pkg.version%>', '<%= module.name %>')"><i class="glyphicon glyphicon-edit"></i> Edit in plunker</button>
</div>
<uib-tabset active="activeTab">
<uib-tab index="0" heading="Markup">
<div plunker-content="markup">
<pre ng-non-bindable><code data-language="html"><%- module.docs.html %></code></pre>
</div>
</uib-tab>
<uib-tab index="1" heading="JavaScript">
<div plunker-content="javascript">
<pre ng-non-bindable><code data-language="javascript"><%- module.docs.js %></code></pre>
</div>
</uib-tab>
</uib-tabset>
</div>
</div>
</section>
<script><%= module.docs.js %></script>
<% }); %>
</div>
</div>
<hr>
<div class="row">
<div class="span12" ng-controller="PlunkerCtrl">
<div class="pull-right">
<button class="btn btn-info" id="plunk-btn" ng-click="edit('<%= ngversion%>', '<%= bsversion %>', '<%= pkg.version%>', '<%= module.name %>')"><i class="icon-edit icon-white"></i> Edit in plunker</button>
</div>
<tabs>
<pane heading="Markup" plunker-content="markup"><pre ng-non-bindable><code data-language="html"><%- module.docs.html %></code></pre></pane>
<pane heading="JavaScript" plunker-content="javascript"><pre ng-non-bindable><code data-language="javascript"><%- module.docs.js %></code></pre></pane>
</tabs>
</div>
</div>
</section>
<script><%= module.docs.js %></script>
<% }); %>
</div>
</div>
</div><!-- /.container -->
</div><!-- /.main -->
<footer class="footer">
<div class="container">
<p>Designed and built by <a href="https://github.com/angular-ui?tab=members" target="_blank">Angular-UI team</a> and <a href="https://github.com/angular-ui/bootstrap/graphs/contributors" target="_blank">contributors</a>.</p>
<p>Code licensed under <a href="https://github.com/angular-ui/bootstrap/blob/master/LICENSE">MIT License</a>.</p>
<p>Designed and built by all ui-bootstrap <a href="https://github.com/angular-ui/bootstrap/graphs/contributors" target="_blank">contributors</a>.</p>
<p>Code licensed under <a href="https://github.com/angular-ui/bootstrap/blob/master/LICENSE"><%= pkg.license %> License</a>.</p>
<p><a href="https://github.com/angular-ui/bootstrap/issues?state=open">Issues</a></p>
</div>
</footer>
@@ -204,28 +274,89 @@
<script src="assets/rainbow-generic.js"></script>
<script src="assets/rainbow-javascript.js"></script>
<script src="assets/rainbow-html.js"></script>
<div modal="buildModalShown" class="fade">
<div class="modal-header"><h2>Create a Custom Build</h2></div>
<div class="modal-body">
<div ng-show="buildErrorText">
<h3 style="text-align: center;">{{buildErrorText}}</h3>
<script type="text/ng-template" id="downloadModal.html">
<div class="modal-header"><h4 class="modal-title">Download Angular UI Bootstrap</h4></div>
<div class="modal-body">
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label"><strong>Build</strong></label>
<div class="col-sm-9">
<span class="btn-group">
<button type="button" class="btn btn-default" ng-model="options.minified" uib-btn-radio="true">Minified</button>
<button type="button" class="btn btn-default" ng-model="options.minified" uib-btn-radio="false">Uncompressed</button>
</span>
<small class="help-block">Use <b>Minified</b> version in your deployed application. <b>Uncompressed</b> source code is useful only for debugging and development purpose.</small>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"><strong>Include Templates</strong></label>
<div class="col-sm-9">
<span class="btn-group">
<button type="button" class="btn btn-default" ng-model="options.tpls" uib-btn-radio="true">Yes</button>
<button type="button" class="btn btn-default" ng-model="options.tpls" uib-btn-radio="false">No</button>
</span>
<small class="help-block">Whether you want to include the <i>default templates</i>, bundled with most of the directives. These templates are based on Bootstrap's markup and CSS.</small>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"><strong>npm</strong></label>
<div class="col-sm-9">
<pre style="margin-bottom:0;">npm install angular-ui-bootstrap</pre>
<small class="help-block"><a href="https://www.npmjs.com/" target="_blank">npm</a> is a package manager for the web.</small>
</div>
</div>
</form>
</div>
<div ng-hide="buildErrorText">
<label>Select the modules you wish to download:
<select style="width: 100%;" ui-select2 multiple
ui-options="{multiple: true}"
ng-model="selectedModules">
<% modules.forEach(function(module) { %>
<option value="<%= module.name %>"><%= module.displayName %></option>
<% }); %>
</select></label>
<div class="modal-footer">
<a class="btn btn-default" ng-click="cancel()">Close</a>
<a class="btn btn-primary" ng-href="{{download('<%= pkg.version%>')}}" download><i class="glyphicon glyphicon-download-alt"></i> Download <%= pkg.version %></a>
</div>
</div>
<div class="modal-footer">
<a class="btn btn-primary" ng-disabled="!selectedModules.length" ng-click="selectedModules.length && downloadBuild()"><i class="icon-download-alt icon-white"></i> Download {{selectedModules.length}} Modules</a>
<a class="btn" ng-click="buildModalShown = false">Cancel</a>
</div>
</div>
</script>
<script type="text/ng-template" id="buildModal.html">
<div class="modal-header">
<h4>
Create a Custom Build
<br>
<small>Select the modules you wish to download</small>
</h4>
</div>
<div class="modal-body">
<div ng-show="isOldBrowser()">
Your current browser doesn't support creating custom builds.
Please take a second to <a href="http://browsehappy.com/">upgrade to a
more modern browser</a> (other than Safari).
</div>
<div ng-show="buildErrorText">
<h4 style="text-align: center;">{{buildErrorText}}</h4>
</div>
<div ng-hide="buildErrorText || isOldBrowser()">
<% modules.forEach(function(module,i) { %>
<% if (i % 3 === 0) {%>
<div class="btn-group" style="width: 100%;">
<% } %>
<button type="button" class="btn btn-default"
style="width: 33%; border-radius: 0;"
ng-class="{'btn-primary': module.<%= module.name %>}"
ng-model="module.<%= module.name %>"
uib-btn-checkbox
ng-change="selectedChanged('<%= module.name %>', module.<%= module.name %>)">
<%= module.displayName %>
</button>
<% if ((i+1) % 3 === 0) { //end button group%>
</div>
<% } %>
<% }); %>
</div>
</div>
<div class="modal-footer">
<a class="btn btn-default" ng-click="cancel()">Close</a>
<a class="btn btn-primary" ng-hide="isOldBrowser()"
ng-disabled="isOldBrowser() !== false && !selectedModules.length"
ng-click="selectedModules.length && build(selectedModules, '<%= pkg.version %>')">
<i class="glyphicon glyphicon-download-alt"></i> Download {{selectedModules.length}} Modules
</a>
</div>
</script>
<script type="text/javascript">
@@ -240,5 +371,7 @@
})();
</script>
<script src="assets/smoothscroll-angular-custom.js"></script>
<script src="assets/uglifyjs.js"></script>
</body>
</html>
+46
View File
@@ -0,0 +1,46 @@
/*!
* Forked from:
* Bootstrap Grunt task for generating raw-files.min.js for the Customizer
* http://getbootstrap.com
* Copyright 2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
/* jshint node: true */
'use strict';
var fs = require('fs');
function getFiles(filePaths) {
var files = {};
filePaths
.forEach(function (path) {
files[path] = fs.readFileSync(path, 'utf8');
});
return files;
}
module.exports = function generateRawFilesJs(grunt, jsFilename, files, banner, cssBanner) {
if (!banner) {
banner = '';
}
if (!cssBanner) {
cssBanner = '';
}
var filesJsObject = {
banner: banner,
cssBanner: cssBanner,
files: getFiles(files),
};
var filesJsContent = JSON.stringify(filesJsObject);
try {
fs.writeFileSync(jsFilename, filesJsContent);
}
catch (err) {
grunt.fail.warn(err);
}
grunt.log.writeln('File ' + jsFilename.cyan + ' created.');
};
-1764
View File
File diff suppressed because it is too large Load Diff
-14733
View File
File diff suppressed because it is too large Load Diff
+50 -6
View File
@@ -1,13 +1,57 @@
// jasmine matcher for expecting an element to have a css class
// https://github.com/angular/angular.js/blob/master/test/matchers.js
beforeEach(function() {
this.addMatchers({
toHaveClass: function(cls) {
this.message = function() {
return "Expected '" + angular.mock.dump(this.actual) + "' to have class '" + cls + "'.";
};
jasmine.addMatchers({
toHaveClass: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var result = {
pass: actual.hasClass(expected)
};
return this.actual.hasClass(cls);
if (result.pass) {
result.message = 'Expected "' + actual + '" not to have the "' + expected + '" class.';
} else {
result.message = 'Expected "' + actual + '" to have the "' + expected + '" class.';
}
return result;
}
}
},
toBeHidden: function(util, customEqualityTesters) {
return {
compare: function(actual) {
var result = {
pass: actual.hasClass('ng-hide') || actual.css('display') === 'none'
};
if (result.pass) {
result.message = 'Expected "' + actual + '" not to be hidden';
} else {
result.message = 'Expected "' + actual + '" to be hidden';
}
return result;
}
}
},
toHaveFocus: function(util, customEqualityTesters) {
return {
compare: function(actual) {
var result = {
pass: document.activeElement === actual[0]
};
if (result.pass) {
result.message = 'Expected "' + actual + '" not to have focus';
} else {
result.message = 'Expected "' + actual + '" to have focus';
}
return result;
}
}
}
});
});
+106
View File
@@ -0,0 +1,106 @@
#!/usr/bin/env node
/**
* Git COMMIT-MSG hook for validating commit message
* See https://docs.google.com/document/d/1rk04jEuGfk9kYzfqCuOlPTSJw3hEDZJTBN5E5f1SALo/edit
*
* Installation:
* >> cd <angular-repo>
* >> ln -s validate-commit-msg.js .git/hooks/commit-msg
*/
var fs = require('fs');
var util = require('util');
var MAX_LENGTH = 70;
var PATTERN = /^(?:fixup!\s*)?(\w*)(\((\w+)\))?\: (.*)$/;
var IGNORED = /^WIP\:/;
var TYPES = {
chore: true,
demo: true,
docs: true,
feat: true,
fix: true,
refactor: true,
revert: true,
style: true,
test: true
};
var error = function() {
// gitx does not display it
// http://gitx.lighthouseapp.com/projects/17830/tickets/294-feature-display-hook-error-message-when-hook-fails
// https://groups.google.com/group/gitx/browse_thread/thread/a03bcab60844b812
console.error('INVALID COMMIT MSG: ' + util.format.apply(null, arguments));
};
var validateMessage = function(message) {
var isValid = true;
if (IGNORED.test(message)) {
console.log('Commit message validation ignored.');
return true;
}
if (message.length > MAX_LENGTH) {
error('is longer than %d characters !', MAX_LENGTH);
isValid = false;
}
var match = PATTERN.exec(message);
if (!match) {
error('does not match "<type>(<scope>): <subject>" ! was: "' + message + '"\nNote: <scope> must be only letters.');
return false;
}
var type = match[1];
var scope = match[3];
var subject = match[4];
if (!TYPES.hasOwnProperty(type)) {
error('"%s" is not allowed type !', type);
return false;
}
// Some more ideas, do want anything like this ?
// - allow only specific scopes (eg. fix(docs) should not be allowed ?
// - auto correct the type to lower case ?
// - auto correct first letter of the subject to lower case ?
// - auto add empty line after subject ?
// - auto remove empty () ?
// - auto correct typos in type ?
// - store incorrect messages, so that we can learn
return isValid;
};
var firstLineFromBuffer = function(buffer) {
return buffer.toString().split('\n').shift();
};
// publish for testing
exports.validateMessage = validateMessage;
// hacky start if not run by jasmine :-D
if (process.argv.join('').indexOf('jasmine-node') === -1) {
var commitMsgFile = process.argv[2];
var incorrectLogFile = commitMsgFile.replace('COMMIT_EDITMSG', 'logs/incorrect-commit-msgs');
fs.readFile(commitMsgFile, function(err, buffer) {
var msg = firstLineFromBuffer(buffer);
if (!validateMessage(msg)) {
fs.appendFile(incorrectLogFile, msg + '\n', function() {
process.exit(1);
});
} else {
process.exit(0);
}
});
}
+55 -10
View File
@@ -1,16 +1,61 @@
{
"author": "https://github.com/angular-ui/bootstrap/graphs/contributors",
"name": "angular-ui-bootstrap",
"version": "0.3.0",
"version": "2.5.1-SNAPSHOT",
"description": "Native AngularJS (Angular) directives for Bootstrap",
"homepage": "http://angular-ui.github.io/bootstrap/",
"keywords": [
"angularjs",
"angular",
"bootstrap",
"ui"
],
"dependencies": {},
"directories": {
"lib": "src/"
},
"files": [
"index.js",
"dist/",
"src/",
"template/"
],
"main": "index.js",
"scripts": {
"demo": "grunt after-test && static dist -a 0.0.0.0 -H '{\"Cache-Control\": \"no-cache, must-revalidate\"}'",
"test": "grunt"
},
"repository": {
"type": "git",
"url": "https://github.com/angular-ui/bootstrap.git"
},
"devDependencies": {
"grunt": "~0.4.1",
"node-markdown": "0.1.1",
"grunt-contrib-concat": "~0.1.3",
"grunt-contrib-copy": "~0.4.1",
"grunt-contrib-uglify": "~0.2.0",
"grunt-contrib-watch": "~0.3.1",
"grunt-contrib-jshint": "~0.4.0",
"grunt-html2js": "~0.1.3"
}
"angular": "1.6.1",
"angular-mocks": "1.6.1",
"angular-sanitize": "1.6.1",
"grunt": "^0.4.5",
"grunt-cli": "^1.2.0",
"grunt-contrib-concat": "^1.0.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-uglify": "^1.0.1",
"grunt-contrib-watch": "^1.0.0",
"grunt-conventional-changelog": "^6.1.0",
"grunt-ddescribe-iit": "0.0.6",
"grunt-eslint": "^17.3.1",
"grunt-html2js": "^0.3.0",
"grunt-karma": "^0.12.0",
"jasmine-core": "^2.2.0",
"karma": "0.13.22",
"karma-chrome-launcher": "^0.2.0",
"karma-coverage": "^0.5.0",
"karma-firefox-launcher": "^0.1.4",
"karma-jasmine": "^0.3.5",
"load-grunt-tasks": "^3.3.0",
"lodash": "^4.1.0",
"marked": "^0.3.5",
"node-static": "^0.7.8",
"semver": "^5.0.1",
"shelljs": "^0.6.0"
},
"license": "MIT"
}
+145 -141
View File
@@ -1,141 +1,145 @@
angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
.constant('accordionConfig', {
closeOthers: true
})
.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) {
// This array keeps track of the accordion groups
this.groups = [];
// Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
this.closeOthers = function(openGroup) {
var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
if ( closeOthers ) {
angular.forEach(this.groups, function (group) {
if ( group !== openGroup ) {
group.isOpen = false;
}
});
}
};
// This is called from the accordion-group directive to add itself to the accordion
this.addGroup = function(groupScope) {
var that = this;
this.groups.push(groupScope);
groupScope.$on('$destroy', function (event) {
that.removeGroup(groupScope);
});
};
// This is called from the accordion-group directive when to remove itself
this.removeGroup = function(group) {
var index = this.groups.indexOf(group);
if ( index !== -1 ) {
this.groups.splice(this.groups.indexOf(group), 1);
}
};
}])
// The accordion directive simply sets up the directive controller
// and adds an accordion CSS class to itself element.
.directive('accordion', function () {
return {
restrict:'EA',
controller:'AccordionController',
transclude: true,
replace: false,
templateUrl: 'template/accordion/accordion.html'
};
})
// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
.directive('accordionGroup', ['$parse', '$transition', '$timeout', function($parse, $transition, $timeout) {
return {
require:'^accordion', // We need this directive to be inside an accordion
restrict:'EA',
transclude:true, // It transcludes the contents of the directive into the template
replace: true, // The element containing the directive will be replaced with the template
templateUrl:'template/accordion/accordion-group.html',
scope:{ heading:'@' }, // Create an isolated scope and interpolate the heading attribute onto this scope
controller: ['$scope', function($scope) {
this.setHeading = function(element) {
this.heading = element;
};
}],
link: function(scope, element, attrs, accordionCtrl) {
var getIsOpen, setIsOpen;
accordionCtrl.addGroup(scope);
scope.isOpen = false;
if ( attrs.isOpen ) {
getIsOpen = $parse(attrs.isOpen);
setIsOpen = getIsOpen.assign;
scope.$watch(
function watchIsOpen() { return getIsOpen(scope.$parent); },
function updateOpen(value) { scope.isOpen = value; }
);
scope.isOpen = getIsOpen ? getIsOpen(scope.$parent) : false;
}
scope.$watch('isOpen', function(value) {
if ( value ) {
accordionCtrl.closeOthers(scope);
}
if ( setIsOpen ) {
setIsOpen(scope.$parent, value);
}
});
}
};
}])
// Use accordion-heading below an accordion-group to provide a heading containing HTML
// <accordion-group>
// <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
// </accordion-group>
.directive('accordionHeading', function() {
return {
restrict: 'E',
transclude: true, // Grab the contents to be used as the heading
template: '', // In effect remove this element!
replace: true,
require: '^accordionGroup',
compile: function(element, attr, transclude) {
return function link(scope, element, attr, accordionGroupCtrl) {
// Pass the heading to the accordion-group controller
// so that it can be transcluded into the right place in the template
// [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
accordionGroupCtrl.setHeading(transclude(scope, function() {}));
};
}
};
})
// Use in the accordion-group template to indicate where you want the heading to be transcluded
// You must provide the property on the accordion-group controller that will hold the transcluded element
// <div class="accordion-group">
// <div class="accordion-heading" ><a ... accordion-transclude="heading">...</a></div>
// ...
// </div>
.directive('accordionTransclude', function() {
return {
require: '^accordionGroup',
link: function(scope, element, attr, controller) {
scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {
if ( heading ) {
element.html('');
element.append(heading);
}
});
}
};
});
angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse', 'ui.bootstrap.tabindex'])
.constant('uibAccordionConfig', {
closeOthers: true
})
.controller('UibAccordionController', ['$scope', '$attrs', 'uibAccordionConfig', function($scope, $attrs, accordionConfig) {
// This array keeps track of the accordion groups
this.groups = [];
// Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
this.closeOthers = function(openGroup) {
var closeOthers = angular.isDefined($attrs.closeOthers) ?
$scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
if (closeOthers) {
angular.forEach(this.groups, function(group) {
if (group !== openGroup) {
group.isOpen = false;
}
});
}
};
// This is called from the accordion-group directive to add itself to the accordion
this.addGroup = function(groupScope) {
var that = this;
this.groups.push(groupScope);
groupScope.$on('$destroy', function(event) {
that.removeGroup(groupScope);
});
};
// This is called from the accordion-group directive when to remove itself
this.removeGroup = function(group) {
var index = this.groups.indexOf(group);
if (index !== -1) {
this.groups.splice(index, 1);
}
};
}])
// The accordion directive simply sets up the directive controller
// and adds an accordion CSS class to itself element.
.directive('uibAccordion', function() {
return {
controller: 'UibAccordionController',
controllerAs: 'accordion',
transclude: true,
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/accordion/accordion.html';
}
};
})
// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
.directive('uibAccordionGroup', function() {
return {
require: '^uibAccordion', // We need this directive to be inside an accordion
transclude: true, // It transcludes the contents of the directive into the template
restrict: 'A',
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';
},
scope: {
heading: '@', // Interpolate the heading attribute onto this scope
panelClass: '@?', // Ditto with panelClass
isOpen: '=?',
isDisabled: '=?'
},
controller: function() {
this.setHeading = function(element) {
this.heading = element;
};
},
link: function(scope, element, attrs, accordionCtrl) {
element.addClass('panel');
accordionCtrl.addGroup(scope);
scope.openClass = attrs.openClass || 'panel-open';
scope.panelClass = attrs.panelClass || 'panel-default';
scope.$watch('isOpen', function(value) {
element.toggleClass(scope.openClass, !!value);
if (value) {
accordionCtrl.closeOthers(scope);
}
});
scope.toggleOpen = function($event) {
if (!scope.isDisabled) {
if (!$event || $event.which === 32) {
scope.isOpen = !scope.isOpen;
}
}
};
var id = 'accordiongroup-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
scope.headingId = id + '-tab';
scope.panelId = id + '-panel';
}
};
})
// Use accordion-heading below an accordion-group to provide a heading containing HTML
.directive('uibAccordionHeading', function() {
return {
transclude: true, // Grab the contents to be used as the heading
template: '', // In effect remove this element!
replace: true,
require: '^uibAccordionGroup',
link: function(scope, element, attrs, accordionGroupCtrl, transclude) {
// Pass the heading to the accordion-group controller
// so that it can be transcluded into the right place in the template
// [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
accordionGroupCtrl.setHeading(transclude(scope, angular.noop));
}
};
})
// Use in the accordion-group template to indicate where you want the heading to be transcluded
// You must provide the property on the accordion-group controller that will hold the transcluded element
.directive('uibAccordionTransclude', function() {
return {
require: '^uibAccordionGroup',
link: function(scope, element, attrs, controller) {
scope.$watch(function() { return controller[attrs.uibAccordionTransclude]; }, function(heading) {
if (heading) {
var elem = angular.element(element[0].querySelector(getHeaderSelectors()));
elem.html('');
elem.append(heading);
}
});
}
};
function getHeaderSelectors() {
return 'uib-accordion-header,' +
'data-uib-accordion-header,' +
'x-uib-accordion-header,' +
'uib\\:accordion-header,' +
'[uib-accordion-header],' +
'[data-uib-accordion-header],' +
'[x-uib-accordion-header]';
}
});
+56 -16
View File
@@ -1,20 +1,60 @@
<div ng-controller="AccordionDemoCtrl">
<label class="checkbox">
<input type="checkbox" ng-model="oneAtATime">
Open only one at a time
</label>
<script type="text/ng-template" id="group-template.html">
<div class="panel-heading">
<h4 class="panel-title" style="color:#fa39c3">
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading">
<span uib-accordion-header ng-class="{'text-muted': isDisabled}">
{{heading}}
</span>
</a>
</h4>
</div>
<div class="panel-collapse collapse" uib-collapse="!isOpen">
<div class="panel-body" style="text-align: right" ng-transclude></div>
</div>
</script>
<accordion close-others="oneAtATime">
<accordion-group heading="Static Header">
<p>
<button type="button" class="btn btn-default btn-sm" ng-click="status.open = !status.open">Toggle last panel</button>
<button type="button" class="btn btn-default btn-sm" ng-click="status.isFirstDisabled = ! status.isFirstDisabled">Enable / Disable first panel</button>
</p>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="oneAtATime">
Open only one at a time
</label>
</div>
<uib-accordion close-others="oneAtATime">
<div uib-accordion-group class="panel-default" heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
This content is straight in the template.
</accordion-group>
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
</div>
<div uib-accordion-group class="panel-default" heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
<accordion-group heading="Dynamic Body Content">
<p>The body of the accordion group grows to fit the contents</p>
<button class="btn btn-small" ng-click="addItem()">Add Item</button>
<div ng-repeat="item in items">{{item}}</div>
</accordion-group>
</accordion>
</div>
</div>
<div uib-accordion-group class="panel-default" heading="Dynamic Body Content">
<p>The body of the uib-accordion group grows to fit the contents</p>
<button type="button" class="btn btn-default btn-sm" ng-click="addItem()">Add Item</button>
<div ng-repeat="item in items">{{item}}</div>
</div>
<div uib-accordion-group class="panel-default" heading="Custom template" template-url="group-template.html">
Hello
</div>
<div uib-accordion-group class="panel-default" is-open="status.isCustomHeaderOpen" template-url="group-template.html">
<uib-accordion-heading>
Custom template with custom header template <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.isCustomHeaderOpen, 'glyphicon-chevron-right': !status.isCustomHeaderOpen}"></i>
</uib-accordion-heading>
World
</div>
<div uib-accordion-group class="panel-danger" heading="Delete account">
<p>Please, to delete your account, click the button below</p>
<button class="btn btn-danger">Delete</button>
</div>
<div uib-accordion-group class="panel-default" is-open="status.open">
<uib-accordion-heading>
I can have markup, too! <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
</uib-accordion-heading>
This is just some content to illustrate fancy headings.
</div>
</uib-accordion>
</div>
+12 -6
View File
@@ -1,14 +1,14 @@
function AccordionDemoCtrl($scope) {
angular.module('ui.bootstrap.demo').controller('AccordionDemoCtrl', function ($scope) {
$scope.oneAtATime = true;
$scope.groups = [
{
title: "Dynamic Group Header - 1",
content: "Dynamic Group Body - 1"
title: 'Dynamic Group Header - 1',
content: 'Dynamic Group Body - 1'
},
{
title: "Dynamic Group Header - 2",
content: "Dynamic Group Body - 2"
title: 'Dynamic Group Header - 2',
content: 'Dynamic Group Body - 2'
}
];
@@ -18,4 +18,10 @@ function AccordionDemoCtrl($scope) {
var newItemNo = $scope.items.length + 1;
$scope.items.push('Item ' + newItemNo);
};
}
$scope.status = {
isCustomHeaderOpen: false,
isFirstOpen: true,
isFirstDisabled: false
};
});
+46 -2
View File
@@ -1,5 +1,49 @@
The **accordion directive** builds on top of the collapse directive to provide a list of items, with collapsible bodies that are collapsed or expanded by clicking on the item's header.
We can control whether expanding an item will cause the other items to close, using the `close-others` attribute on accordion.
The body of each accordion group is transcluded into the body of the collapsible element.
The body of each accordion group is transcluded in to the body of the collapsible element.
### uib-accordion settings
* `close-others`
<small class="badge">$</small>
<small class="badge">C</small>
_(Default: `true`)_ -
Control whether expanding an item will cause the other items to close.
* `template-url`
_(Default: `template/accordion/accordion.html`)_ -
Add the ability to override the template used on the component.
### uib-accordion-group settings
* `heading`
_(Default: `none`)_ -
The clickable text on the group's header. You need one to be able to click on the header for toggling.
* `is-disabled`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `false`)_ -
Whether the accordion group is disabled or not.
* `is-open`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `false`)_ -
Whether accordion group is open or closed.
* `template-url`
_(Default: `uib/template/accordion/accordion-group.html`)_ -
Add the ability to override the template used on the component.
### Accordion heading
Instead of the `heading` attribute on the `uib-accordion-group`, you can use an `uib-accordion-heading` element inside a group that will be used as the group's header.
If you're using a custom template for the `uib-accordion-group`, you'll need to have an element for the heading to be transcluded into using `uib-accordion-header` (e.g. `<div uib-accordion-header></div>`).
### Known issues
To use clickable elements within the accordion, you have to override the accordion-group template to use div elements instead of anchor elements, and add `cursor: pointer` in your CSS. This is due to browsers interpreting anchor elements as the target of any click event, which triggers routing when certain elements such as buttons are nested inside the anchor element.
If custom classes on the accordion-group element are desired, one needs to either modify the template to remove the `ng-class` usage in the accordion-group template and use ng-class on the accordion-group element (not recommended), or use an interpolated expression in the class attribute, i.e. `<uib-accordion-group class="{{customClass()}}"></uib-accordion-group>`.
+11
View File
@@ -0,0 +1,11 @@
require('../collapse');
require('../tabindex');
require('../../template/accordion/accordion-group.html.js');
require('../../template/accordion/accordion.html.js');
require('./accordion');
var MODULE_NAME = 'ui.bootstrap.module.accordion';
angular.module(MODULE_NAME, ['ui.bootstrap.accordion', 'uib/template/accordion/accordion.html', 'uib/template/accordion/accordion-group.html']);
module.exports = MODULE_NAME;
+624
View File
@@ -0,0 +1,624 @@
describe('uib-accordion', function() {
var $animate, $scope;
beforeEach(module('ui.bootstrap.accordion'));
beforeEach(module('ngAnimateMock'));
beforeEach(module('uib/template/accordion/accordion.html'));
beforeEach(module('uib/template/accordion/accordion-group.html'));
beforeEach(inject(function(_$animate_, $rootScope) {
$animate = _$animate_;
$scope = $rootScope;
}));
describe('controller', function () {
var ctrl, $element, $attrs;
beforeEach(inject(function($controller) {
$attrs = {};
ctrl = $controller('UibAccordionController', { $scope: $scope, $attrs: $attrs });
}));
describe('addGroup', function() {
it('adds a the specified panel to the collection', function() {
var group1, group2;
ctrl.addGroup(group1 = $scope.$new());
ctrl.addGroup(group2 = $scope.$new());
expect(ctrl.groups.length).toBe(2);
expect(ctrl.groups[0]).toBe(group1);
expect(ctrl.groups[1]).toBe(group2);
});
});
describe('closeOthers', function() {
var group1, group2, group3;
beforeEach(function() {
ctrl.addGroup(group1 = { isOpen: true, $on : angular.noop });
ctrl.addGroup(group2 = { isOpen: true, $on : angular.noop });
ctrl.addGroup(group3 = { isOpen: true, $on : angular.noop });
});
it('should close other panels if close-others attribute is not defined', function() {
delete $attrs.closeOthers;
ctrl.closeOthers(group2);
expect(group1.isOpen).toBe(false);
expect(group2.isOpen).toBe(true);
expect(group3.isOpen).toBe(false);
});
it('should close other panels if close-others attribute is true', function() {
$attrs.closeOthers = 'true';
ctrl.closeOthers(group3);
expect(group1.isOpen).toBe(false);
expect(group2.isOpen).toBe(false);
expect(group3.isOpen).toBe(true);
});
it('should not close other panels if close-others attribute is false', function() {
$attrs.closeOthers = 'false';
ctrl.closeOthers(group2);
expect(group1.isOpen).toBe(true);
expect(group2.isOpen).toBe(true);
expect(group3.isOpen).toBe(true);
});
describe('setting accordionConfig', function() {
var originalCloseOthers;
beforeEach(inject(function(uibAccordionConfig) {
originalCloseOthers = uibAccordionConfig.closeOthers;
uibAccordionConfig.closeOthers = false;
}));
afterEach(inject(function(uibAccordionConfig) {
// return it to the original value
uibAccordionConfig.closeOthers = originalCloseOthers;
}));
it('should not close other panels if accordionConfig.closeOthers is false', function() {
ctrl.closeOthers(group2);
expect(group1.isOpen).toBe(true);
expect(group2.isOpen).toBe(true);
expect(group3.isOpen).toBe(true);
});
});
});
describe('removeGroup', function() {
it('should remove the specified panel', function() {
var group1, group2, group3;
ctrl.addGroup(group1 = $scope.$new());
ctrl.addGroup(group2 = $scope.$new());
ctrl.addGroup(group3 = $scope.$new());
ctrl.removeGroup(group2);
expect(ctrl.groups.length).toBe(2);
expect(ctrl.groups[0]).toBe(group1);
expect(ctrl.groups[1]).toBe(group3);
});
it('should ignore remove of non-existing panel', function() {
var group1, group2;
ctrl.addGroup(group1 = $scope.$new());
ctrl.addGroup(group2 = $scope.$new());
expect(ctrl.groups.length).toBe(2);
ctrl.removeGroup({});
expect(ctrl.groups.length).toBe(2);
});
it('should remove a panel when the scope is destroyed', function() {
var group1, group2, group3;
ctrl.addGroup(group1 = $scope.$new());
ctrl.addGroup(group2 = $scope.$new());
ctrl.addGroup(group3 = $scope.$new());
group2.$destroy();
expect(ctrl.groups.length).toBe(2);
expect(ctrl.groups[0]).toBe(group1);
expect(ctrl.groups[1]).toBe(group3);
});
});
});
describe('uib-accordion', function() {
var scope, $compile, $templateCache, element;
beforeEach(inject(function($rootScope, _$compile_, _$templateCache_) {
scope = $rootScope;
$compile = _$compile_;
$templateCache = _$templateCache_;
}));
it('should be a tablist', function() {
element = $compile('<uib-accordion></uib-accordion>')(scope);
scope.$digest();
expect(element.html()).toContain('role="tablist"');
});
it('should expose the controller on the view', function() {
$templateCache.put('uib/template/accordion/accordion.html', '<div>{{accordion.text}}</div>');
element = $compile('<uib-accordion></uib-accordion>')(scope);
scope.$digest();
var ctrl = element.controller('uibAccordion');
expect(ctrl).toBeDefined();
ctrl.text = 'foo';
scope.$digest();
expect(element.html()).toBe('<div class="ng-binding">foo</div>');
});
it('should allow custom templates', function() {
$templateCache.put('foo/bar.html', '<div>baz</div>');
element = $compile('<uib-accordion template-url="foo/bar.html"></uib-accordion>')(scope);
scope.$digest();
expect(element.html()).toBe('<div>baz</div>');
});
});
describe('uib-accordion-group', function() {
var scope, $compile;
var element, groups;
var findGroupHeading = function(index) {
return groups.eq(index).find('.panel-heading').eq(0);
};
var findGroupLink = function(index) {
return groups.eq(index).find('.accordion-toggle').eq(0);
};
var findGroupBody = function(index) {
return groups.eq(index).find('.panel-collapse').eq(0);
};
beforeEach(inject(function(_$rootScope_, _$compile_) {
scope = _$rootScope_;
$compile = _$compile_;
}));
it('should allow custom templates', inject(function($templateCache) {
$templateCache.put('foo/bar.html', '<div>baz</div>');
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group heading="title 1" template-url="foo/bar.html"></div>' +
'</uib-accordion>';
element = $compile(tpl)(scope);
scope.$digest();
expect(element.find('[template-url]').html()).toBe('<div>baz</div>');
}));
describe('with static panels', function() {
beforeEach(function() {
spyOn(Math, 'random').and.returnValue(0.1);
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group heading="title 1">Content 1</div>' +
'<div uib-accordion-group heading="title 2">Content 2</div>' +
'</uib-accordion>';
element = angular.element(tpl);
$compile(element)(scope);
scope.$digest();
groups = element.find('.panel');
});
afterEach(function() {
element.remove();
});
it('should create accordion panels with content', function() {
expect(groups.length).toEqual(2);
expect(findGroupLink(0).text()).toEqual('title 1');
expect(findGroupBody(0).text().trim()).toEqual('Content 1');
expect(findGroupLink(1).text()).toEqual('title 2');
expect(findGroupBody(1).text().trim()).toEqual('Content 2');
});
it('should change selected element on click', function() {
findGroupLink(0).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(true);
expect(findGroupHeading(0).html()).toContain('aria-expanded="true"');
findGroupLink(1).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(false);
expect(findGroupHeading(0).html()).toContain('aria-expanded="false"');
expect(findGroupBody(1).scope().isOpen).toBe(true);
expect(findGroupHeading(1).html()).toContain('aria-expanded="true"');
});
it('should toggle element on click', function() {
findGroupLink(0).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(true);
expect(groups.eq(0).html()).toContain('aria-hidden="false"');
findGroupLink(0).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(false);
expect(groups.eq(0).html()).toContain('aria-hidden="true"');
});
it('should add, by default, "panel-open" when opened', function() {
var group = groups.eq(0);
findGroupLink(0).click();
scope.$digest();
expect(group).toHaveClass('panel-open');
findGroupLink(0).click();
scope.$digest();
expect(group).not.toHaveClass('panel-open');
});
it('should toggle element on spacebar when focused', function() {
var group = groups.eq(0);
findGroupLink(0)[0].focus();
var e = $.Event('keypress');
e.which = 32;
findGroupLink(0).trigger(e);
expect(group).toHaveClass('panel-open');
e = $.Event('keypress');
e.which = 32;
findGroupLink(0).trigger(e);
expect(group).not.toHaveClass('panel-open');
});
it('should not toggle with any other keyCode', function() {
var group = groups.eq(0);
findGroupLink(0)[0].focus();
var e = $.Event('keypress');
e.which = 65;
findGroupLink(0).trigger(e);
expect(group).not.toHaveClass('panel-open');
});
it('should generate an Id for the heading', function() {
var groupScope = findGroupBody(0).scope();
expect(groupScope.headingId).toEqual('accordiongroup-' + groupScope.$id + '-1000-tab');
});
it('should generate an Id for the panel', function() {
var groupScope = findGroupBody(0).scope();
expect(groupScope.panelId).toEqual('accordiongroup-' + groupScope.$id + '-1000-panel');
});
});
describe('with open-class attribute', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group heading="title 1" open-class="custom-open-class">Content 1</div>' +
'<div uib-accordion-group heading="title 2" open-class="custom-open-class">Content 2</div>' +
'</uib-accordion>';
element = angular.element(tpl);
$compile(element)(scope);
scope.$digest();
groups = element.find('.panel');
});
afterEach(function() {
element.remove();
});
it('should add custom-open-class when opened', function() {
var group = groups.eq(0);
findGroupLink(0).click();
scope.$digest();
expect(group).toHaveClass('custom-open-class');
findGroupLink(0).click();
scope.$digest();
expect(group).not.toHaveClass('custom-open-class');
});
});
describe('with dynamic panels', function() {
var model;
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}">{{group.content}}</div>' +
'</uib-accordion>';
element = angular.element(tpl);
model = [
{name: 'title 1', content: 'Content 1'},
{name: 'title 2', content: 'Content 2'}
];
$compile(element)(scope);
scope.$digest();
});
it('should have no panels initially', function() {
groups = element.find('.panel');
expect(groups.length).toEqual(0);
});
it('should have a panel for each model item', function() {
scope.groups = model;
scope.$digest();
groups = element.find('.panel');
expect(groups.length).toEqual(2);
expect(findGroupLink(0).text()).toEqual('title 1');
expect(findGroupBody(0).text().trim()).toEqual('Content 1');
expect(findGroupLink(1).text()).toEqual('title 2');
expect(findGroupBody(1).text().trim()).toEqual('Content 2');
});
it('should react properly on removing items from the model', function() {
scope.groups = model;
scope.$digest();
groups = element.find('.panel');
expect(groups.length).toEqual(2);
scope.groups.splice(0,1);
scope.$digest();
groups = element.find('.panel');
expect(groups.length).toEqual(1);
});
});
describe('is-open attribute', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group heading="title 1" is-open="open.first">Content 1</div>' +
'<div uib-accordion-group heading="title 2" is-open="open.second">Content 2</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.open = { first: false, second: true };
$compile(element)(scope);
scope.$digest();
groups = element.find('.panel');
});
it('should open the panel with isOpen set to true', function() {
expect(findGroupBody(0).scope().isOpen).toBe(false);
expect(findGroupBody(1).scope().isOpen).toBe(true);
});
it('should toggle variable on element click', function() {
findGroupLink(0).click();
scope.$digest();
expect(scope.open.first).toBe(true);
findGroupLink(0).click();
scope.$digest();
expect(scope.open.second).toBe(false);
});
});
describe('is-open attribute with dynamic content', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group heading="title 1" is-open="open1"><div ng-repeat="item in items">{{item}}</div></div>' +
'<div uib-accordion-group heading="title 2" is-open="open2">Static content</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.items = ['Item 1', 'Item 2', 'Item 3'];
scope.open1 = true;
scope.open2 = false;
angular.element(document.body).append(element);
$compile(element)(scope);
scope.$digest();
$animate.flush();
groups = element.find('.panel');
});
afterEach(function() {
element.remove();
});
it('should have visible panel body when the group with isOpen set to true', function() {
expect(findGroupBody(0)).toHaveClass('in');
expect(findGroupBody(1)).not.toHaveClass('in');
});
});
describe('is-open attribute with dynamic groups', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open">{{group.content}}</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.groups = [
{name: 'title 1', content: 'Content 1', open: false},
{name: 'title 2', content: 'Content 2', open: true}
];
$compile(element)(scope);
scope.$digest();
groups = element.find('.panel');
});
it('should have visible group body when the group with isOpen set to true', function() {
expect(findGroupBody(0).scope().isOpen).toBe(false);
expect(findGroupBody(1).scope().isOpen).toBe(true);
});
it('should toggle element on click', function() {
findGroupLink(0).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(true);
expect(scope.groups[0].open).toBe(true);
findGroupLink(0).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(false);
expect(scope.groups[0].open).toBe(false);
});
});
describe('is-open attribute with custom class', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open" class="testClass">{{group.content}}</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.groups = [
{name: 'title 1', content: 'Content 1', open: false},
{name: 'title 2', content: 'Content 2', open: true}
];
$compile(element)(scope);
scope.$digest();
groups = element.find('.panel');
});
it('should add "panel-open" class', function(){
expect(groups.eq(0)).not.toHaveClass('panel-open');
expect(groups.eq(1)).toHaveClass('panel-open');
});
});
describe('`is-disabled` attribute', function() {
var groupBody;
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<div uib-accordion-group heading="title 1" is-disabled="disabled">Content 1</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.disabled = true;
$compile(element)(scope);
scope.$digest();
groups = element.find('.panel');
groupBody = findGroupBody(0);
});
it('should open the panel with isOpen set to true', function() {
expect(groupBody.scope().isOpen).toBeFalsy();
});
it('should not toggle if disabled', function() {
findGroupLink(0).click();
scope.$digest();
expect(groupBody.scope().isOpen).toBeFalsy();
});
it('should toggle after enabling', function() {
scope.disabled = false;
scope.$digest();
expect(groupBody.scope().isOpen).toBeFalsy();
findGroupLink(0).click();
scope.$digest();
expect(groupBody.scope().isOpen).toBeTruthy();
});
it('should have text-muted styling', function() {
expect(findGroupLink(0).find('span:first')).toHaveClass('text-muted');
});
});
// This is re-used in both the uib-accordion-heading element and the uib-accordion-heading attribute tests
function isDisabledStyleCheck() {
var tpl =
'<uib-accordion ng-init="a = [1,2,3]">' +
'<div uib-accordion-group heading="I get overridden" is-disabled="true">' +
'<uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </uib-accordion-heading>' +
'Body' +
'</div>' +
'</uib-accordion>';
scope.disabled = true;
element = $compile(tpl)(scope);
scope.$digest();
groups = element.find('.panel');
expect(findGroupLink(0).find('span').hasClass('text-muted')).toBe(true);
}
describe('uib-accordion-heading element', function() {
beforeEach(function() {
var tpl =
'<uib-accordion ng-init="a = [1,2,3]">' +
'<div uib-accordion-group heading="I get overridden">' +
'<uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </uib-accordion-heading>' +
'Body' +
'</div>' +
'</uib-accordion>';
element = $compile(tpl)(scope);
scope.$digest();
groups = element.find('.panel');
});
it('transcludes the <uib-accordion-heading> content into the heading link', function() {
expect(findGroupLink(0).text()).toBe('Heading Element 123 ');
});
it('attaches the same scope to the transcluded heading and body', function() {
expect(findGroupLink(0).scope().$id).toBe(findGroupBody(0).scope().$id);
});
it('should wrap the transcluded content in a span', function() {
expect(findGroupLink(0).find('span:first').length).toEqual(1);
});
it('should have disabled styling when is-disabled is true', isDisabledStyleCheck);
});
describe('uib-accordion-heading attribute', function() {
beforeEach(function() {
var tpl =
'<uib-accordion ng-init="a = [1,2,3]">' +
'<div uib-accordion-group heading="I get overridden">' +
'<div uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </div>' +
'Body' +
'</div>' +
'</uib-accordion>';
element = $compile(tpl)(scope);
scope.$digest();
groups = element.find('.panel');
});
it('transcludes the <uib-accordion-heading> content into the heading link', function() {
expect(findGroupLink(0).text()).toBe('Heading Element 123 ');
});
it('attaches the same scope to the transcluded heading and body', function() {
expect(findGroupLink(0).scope().$id).toBe(findGroupBody(0).scope().$id);
});
it('should have disabled styling when is-disabled is true', isDisabledStyleCheck);
});
describe('uib-accordion-heading, with repeating uib-accordion-groups', function() {
it('should clone the uib-accordion-heading for each group', function() {
element = $compile('<uib-accordion><div uib-accordion-group ng-repeat="x in [1,2,3]"><uib-accordion-heading>{{x}}</uib-accordion-heading></div></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(groups.length).toBe(3);
expect(findGroupLink(0).text()).toBe('1');
expect(findGroupLink(1).text()).toBe('2');
expect(findGroupLink(2).text()).toBe('3');
});
});
describe('uib-accordion-heading attribute, with repeating uib-accordion-groups', function() {
it('should clone the uib-accordion-heading for each group', function() {
element = $compile('<uib-accordion><div uib-accordion-group ng-repeat="x in [1,2,3]"><div uib-accordion-heading>{{x}}</div></div></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(groups.length).toBe(3);
expect(findGroupLink(0).text()).toBe('1');
expect(findGroupLink(1).text()).toBe('2');
expect(findGroupLink(2).text()).toBe('3');
});
});
describe('uib-accordion-heading attribute, with custom template', function() {
it('should transclude heading to a template using data-uib-accordion-header', inject(function($templateCache) {
$templateCache.put('foo/bar.html', '<div class="panel"><a uib-accordion-transclude="heading" class="accordion-toggle"><span data-uib-accordion-header></span></a><div ng-transclude></div></div>');
element = $compile('<uib-accordion><div uib-accordion-group template-url="foo/bar.html"><uib-accordion-heading>baz</uib-accordion-heading></div></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(findGroupLink(0).text()).toBe('baz');
}));
});
});
});
-299
View File
@@ -1,299 +0,0 @@
describe('accordion', function () {
var $scope;
beforeEach(module('ui.bootstrap.accordion'));
beforeEach(module('template/accordion/accordion.html'));
beforeEach(module('template/accordion/accordion-group.html'));
beforeEach(inject(function ($rootScope) {
$scope = $rootScope;
}));
describe('controller', function () {
var ctrl, $element, $attrs;
beforeEach(inject(function($controller) {
$attrs = {}; $element = {};
ctrl = $controller('AccordionController', { $scope: $scope, $element: $element, $attrs: $attrs });
}));
describe('addGroup', function() {
it('adds a the specified group to the collection', function() {
var group1, group2;
ctrl.addGroup(group1 = $scope.$new());
ctrl.addGroup(group2 = $scope.$new());
expect(ctrl.groups.length).toBe(2);
expect(ctrl.groups[0]).toBe(group1);
expect(ctrl.groups[1]).toBe(group2);
});
});
describe('closeOthers', function() {
var group1, group2, group3;
beforeEach(function() {
ctrl.addGroup(group1 = { isOpen: true, $on : angular.noop });
ctrl.addGroup(group2 = { isOpen: true, $on : angular.noop });
ctrl.addGroup(group3 = { isOpen: true, $on : angular.noop });
});
it('should close other groups if close-others attribute is not defined', function() {
delete $attrs.closeOthers;
ctrl.closeOthers(group2);
expect(group1.isOpen).toBe(false);
expect(group2.isOpen).toBe(true);
expect(group3.isOpen).toBe(false);
});
it('should close other groups if close-others attribute is true', function() {
$attrs.closeOthers = 'true';
ctrl.closeOthers(group3);
expect(group1.isOpen).toBe(false);
expect(group2.isOpen).toBe(false);
expect(group3.isOpen).toBe(true);
});
it('should not close other groups if close-others attribute is false', function() {
$attrs.closeOthers = 'false';
ctrl.closeOthers(group2);
expect(group1.isOpen).toBe(true);
expect(group2.isOpen).toBe(true);
expect(group3.isOpen).toBe(true);
});
describe('setting accordionConfig', function() {
var originalCloseOthers;
beforeEach(inject(function(accordionConfig) {
originalCloseOthers = accordionConfig.closeOthers;
accordionConfig.closeOthers = false;
}));
afterEach(inject(function(accordionConfig) {
// return it to the original value
accordionConfig.closeOthers = originalCloseOthers;
}));
it('should not close other groups if accordionConfig.closeOthers is false', function() {
ctrl.closeOthers(group2);
expect(group1.isOpen).toBe(true);
expect(group2.isOpen).toBe(true);
expect(group3.isOpen).toBe(true);
});
});
});
describe('removeGroup', function() {
it('should remove the specified group', function () {
var group1, group2, group3;
ctrl.addGroup(group1 = $scope.$new());
ctrl.addGroup(group2 = $scope.$new());
ctrl.addGroup(group3 = $scope.$new());
ctrl.removeGroup(group2);
expect(ctrl.groups.length).toBe(2);
expect(ctrl.groups[0]).toBe(group1);
expect(ctrl.groups[1]).toBe(group3);
});
it('should ignore remove of non-existing group', function () {
var group1, group2;
ctrl.addGroup(group1 = $scope.$new());
ctrl.addGroup(group2 = $scope.$new());
expect(ctrl.groups.length).toBe(2);
ctrl.removeGroup({});
expect(ctrl.groups.length).toBe(2);
});
});
});
describe('accordion-group', function () {
var scope, $compile;
var element, groups;
var findGroupLink = function (index) {
return groups.eq(index).find('a').eq(0);
};
var findGroupBody = function (index) {
return groups.eq(index).find('.accordion-body').eq(0);
};
beforeEach(inject(function(_$rootScope_, _$compile_) {
scope = _$rootScope_;
$compile = _$compile_;
}));
afterEach(function () {
element = groups = scope = $compile = undefined;
});
describe('with static groups', function () {
beforeEach(function () {
var tpl =
"<accordion>" +
"<accordion-group heading=\"title 1\">Content 1</accordion-group>" +
"<accordion-group heading=\"title 2\">Content 2</accordion-group>" +
"</accordion>";
element = angular.element(tpl);
angular.element(document.body).append(element);
$compile(element)(scope);
scope.$digest();
groups = element.find('.accordion-group');
});
afterEach(function() {
element.remove();
});
it('should create accordion groups with content', function () {
expect(groups.length).toEqual(2);
expect(findGroupLink(0).text()).toEqual('title 1');
expect(findGroupBody(0).text().trim()).toEqual('Content 1');
expect(findGroupLink(1).text()).toEqual('title 2');
expect(findGroupBody(1).text().trim()).toEqual('Content 2');
});
it('should change selected element on click', function () {
findGroupLink(0).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(true);
findGroupLink(1).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(false);
expect(findGroupBody(1).scope().isOpen).toBe(true);
});
it('should toggle element on click', function() {
findGroupLink(0).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(true);
findGroupLink(0).click();
scope.$digest();
expect(findGroupBody(0).scope().isOpen).toBe(false);
});
});
describe('with dynamic groups', function () {
var model;
beforeEach(function () {
var tpl =
"<accordion>" +
"<accordion-group ng-repeat='group in groups' heading='{{group.name}}'>{{group.content}}</accordion-group>" +
"</accordion>";
element = angular.element(tpl);
model = [
{name: 'title 1', content: 'Content 1'},
{name: 'title 2', content: 'Content 2'}
];
$compile(element)(scope);
scope.$digest();
});
it('should have no groups initially', function () {
groups = element.find('.accordion-group');
expect(groups.length).toEqual(0);
});
it('should have a group for each model item', function() {
scope.groups = model;
scope.$digest();
groups = element.find('.accordion-group');
expect(groups.length).toEqual(2);
expect(findGroupLink(0).text()).toEqual('title 1');
expect(findGroupBody(0).text().trim()).toEqual('Content 1');
expect(findGroupLink(1).text()).toEqual('title 2');
expect(findGroupBody(1).text().trim()).toEqual('Content 2');
});
it('should react properly on removing items from the model', function () {
scope.groups = model;
scope.$digest();
groups = element.find('.accordion-group');
expect(groups.length).toEqual(2);
scope.groups.splice(0,1);
scope.$digest();
groups = element.find('.accordion-group');
expect(groups.length).toEqual(1);
});
});
describe('is-open attribute', function() {
beforeEach(function () {
var tpl =
"<accordion>" +
"<accordion-group heading=\"title 1\" is-open=\"open1\">Content 1</accordion-group>" +
"<accordion-group heading=\"title 2\" is-open=\"open2\">Content 2</accordion-group>" +
"</accordion>";
element = angular.element(tpl);
scope.open1 = false;
scope.open2 = true;
$compile(element)(scope);
scope.$digest();
groups = element.find('.accordion-group');
});
it('should open the group with isOpen set to true', function () {
expect(findGroupBody(0).scope().isOpen).toBe(false);
expect(findGroupBody(1).scope().isOpen).toBe(true);
});
});
describe('is-open attribute with dynamic content', function() {
beforeEach(function () {
var tpl =
"<accordion>" +
"<accordion-group heading=\"title 1\" is-open=\"open1\"><div ng-repeat='item in items'>{{item}}</div></accordion-group>" +
"<accordion-group heading=\"title 2\" is-open=\"open2\">Static content</accordion-group>" +
"</accordion>";
element = angular.element(tpl);
scope.items = ['Item 1', 'Item 2', 'Item 3'];
scope.open1 = true;
scope.open2 = false;
angular.element(document.body).append(element);
$compile(element)(scope);
scope.$digest();
groups = element.find('.accordion-group');
});
afterEach(function() {
element.remove();
});
it('should have visible group body when the group with isOpen set to true', function () {
expect(findGroupBody(0)[0].clientHeight).not.toBe(0);
expect(findGroupBody(1)[0].clientHeight).toBe(0);
});
});
describe('accordion-heading element', function() {
beforeEach(function() {
var tpl =
'<accordion ng-init="a = [1,2,3]">' +
'<accordion-group heading="I get overridden">' +
'<accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </accordion-heading>' +
'Body' +
'</accordion-group>' +
'</accordion>';
element = $compile(tpl)(scope);
scope.$digest();
groups = element.find('.accordion-group');
});
it('transcludes the <accordion-heading> content into the heading link', function() {
expect(findGroupLink(0).text()).toBe('Heading Element 123 ');
});
it('attaches the same scope to the transcluded heading and body', function() {
expect(findGroupLink(0).find('span').scope().$id).toBe(findGroupBody(0).find('span').scope().$id);
});
});
describe('accordion-heading, with repeating accordion-groups', function() {
it('should clone the accordion-heading for each group', function() {
element = $compile('<accordion><accordion-group ng-repeat="x in [1,2,3]"><accordion-heading>{{x}}</accordion-heading></accordion-group></accordion>')(scope);
scope.$digest();
groups = element.find('.accordion-group');
expect(groups.length).toBe(3);
expect(findGroupLink(0).text()).toBe('1');
expect(findGroupLink(1).text()).toBe('2');
expect(findGroupLink(2).text()).toBe('3');
});
});
});
});
+29 -10
View File
@@ -1,15 +1,34 @@
angular.module("ui.bootstrap.alert", []).directive('alert', function () {
angular.module('ui.bootstrap.alert', [])
.controller('UibAlertController', ['$scope', '$element', '$attrs', '$interpolate', '$timeout', function($scope, $element, $attrs, $interpolate, $timeout) {
$scope.closeable = !!$attrs.close;
$element.addClass('alert');
$attrs.$set('role', 'alert');
if ($scope.closeable) {
$element.addClass('alert-dismissible');
}
var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?
$interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;
if (dismissOnTimeout) {
$timeout(function() {
$scope.close();
}, parseInt(dismissOnTimeout, 10));
}
}])
.directive('uibAlert', function() {
return {
restrict:'EA',
templateUrl:'template/alert/alert.html',
transclude:true,
replace:true,
scope: {
type: '=',
close: '&'
controller: 'UibAlertController',
controllerAs: 'alert',
restrict: 'A',
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/alert/alert.html';
},
link: function(scope, iElement, iAttrs, controller) {
scope.closeable = "close" in iAttrs;
transclude: true,
scope: {
close: '&'
}
};
});
+7 -2
View File
@@ -1,4 +1,9 @@
<div ng-controller="AlertDemoCtrl">
<alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
<button class='btn' ng-click="addAlert()">Add Alert</button>
<script type="text/ng-template" id="alert.html">
<div ng-transclude></div>
</script>
<div uib-alert ng-repeat="alert in alerts" ng-class="'alert-' + (alert.type || 'warning')" close="closeAlert($index)">{{alert.msg}}</div>
<div uib-alert template-url="alert.html" style="background-color:#fa39c3;color:white">A happy alert!</div>
<button type="button" class='btn btn-default' ng-click="addAlert()">Add Alert</button>
</div>
+4 -5
View File
@@ -1,15 +1,14 @@
function AlertDemoCtrl($scope) {
angular.module('ui.bootstrap.demo').controller('AlertDemoCtrl', function ($scope) {
$scope.alerts = [
{ type: 'error', msg: 'Oh snap! Change a few things up and try submitting again.' },
{ type: 'danger', msg: 'Oh snap! Change a few things up and try submitting again.' },
{ type: 'success', msg: 'Well done! You successfully read this important alert message.' }
];
$scope.addAlert = function() {
$scope.alerts.push({msg: "Another alert!"});
$scope.alerts.push({msg: 'Another alert!'});
};
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
}
});
+13 -3
View File
@@ -1,5 +1,15 @@
Alert is an AngularJS-version of bootstrap's alert.
This directive can be used both to generate alerts from static and dynamic model data (using the `ng-repeat` directive).
This directive can be used to generate alerts from the dynamic model data (using the ng-repeat directive);
### uib-alert settings
The presence of the "close" attribute determines if a close button is displayed
* `close()`
<small class="badge">$</small> -
A callback function that gets fired when an `alert` is closed. If the attribute exists, a close button is displayed as well.
* `dismiss-on-timeout`
_(Default: `none`)_ -
Takes the number of milliseconds that specify the timeout duration, after which the alert will be closed. This attribute requires the presence of the `close` attribute.
* `template-url`
_(Default: `uib/template/alert/alert.html`)_ -
Add the ability to override the template used in the component.
+8
View File
@@ -0,0 +1,8 @@
require('../../template/alert/alert.html.js');
require('./alert');
var MODULE_NAME = 'ui.bootstrap.module.alert';
angular.module(MODULE_NAME, ['ui.bootstrap.alert', 'uib/template/alert/alert.html']);
module.exports = MODULE_NAME;
+81 -31
View File
@@ -1,22 +1,22 @@
describe("alert", function () {
var scope, ctrl, model, $compile;
var element;
describe('uib-alert', function() {
var element, scope, $compile, $templateCache, $timeout;
beforeEach(module('ui.bootstrap.alert'));
beforeEach(module('template/alert/alert.html'));
beforeEach(inject(function ($rootScope, _$compile_, $controller) {
beforeEach(module('uib/template/alert/alert.html'));
beforeEach(inject(function($rootScope, _$compile_, _$templateCache_, _$timeout_) {
scope = $rootScope;
$compile = _$compile_;
$templateCache = _$templateCache_;
$timeout = _$timeout_;
element = angular.element(
"<div>" +
"<alert ng-repeat='alert in alerts' type='alert.type'" +
"close='removeAlert($index)'>{{alert.msg}}" +
"</alert>" +
"</div>");
'<div>' +
'<div uib-alert ng-repeat="alert in alerts" ' +
'ng-class="\'alert-\' + (alert.type || \'warning\')" ' +
'close="removeAlert($index)">{{alert.msg}}' +
'</div>' +
'</div>');
scope.alerts = [
{ msg:'foo', type:'success'},
@@ -32,48 +32,98 @@ describe("alert", function () {
}
function findCloseButton(index) {
return element.find('.alert button').eq(index);
return element.find('.close').eq(index);
}
it("should generate alerts using ng-repeat", function () {
function findContent(index) {
return element.find('div[ng-transclude]').eq(index);
}
it('should expose the controller to the view', function() {
$templateCache.put('uib/template/alert/alert.html', '<div>{{alert.text}}</div>');
element = $compile('<div uib-alert></div>')(scope);
scope.$digest();
var ctrl = element.controller('uib-alert');
expect(ctrl).toBeDefined();
ctrl.text = 'foo';
scope.$digest();
expect(element.html()).toBe('<div class="ng-binding">foo</div>');
});
it('should support custom templates', function() {
$templateCache.put('foo/bar.html', '<div>baz</div>');
element = $compile('<div uib-alert template-url="foo/bar.html"></div>')(scope);
scope.$digest();
expect(element.html()).toBe('<div>baz</div>');
});
it('should generate alerts using ng-repeat', function() {
var alerts = createAlerts();
expect(alerts.length).toEqual(3);
});
it("should use correct classes for different alert types", function () {
it('should show the alert content', function() {
var alerts = createAlerts();
expect(alerts.eq(0)).toHaveClass('alert-success');
expect(alerts.eq(1)).toHaveClass('alert-error');
//defaults
expect(alerts.eq(2)).toHaveClass('alert');
expect(alerts.eq(2)).not.toHaveClass('alert-info');
expect(alerts.eq(2)).not.toHaveClass('alert-block');
for (var i = 0, n = alerts.length; i < n; i++) {
expect(findContent(i).text()).toBe(scope.alerts[i].msg);
}
});
it("should fire callback when closed", function () {
it('should show close buttons and have the dismissible class', function() {
var alerts = createAlerts();
scope.$apply(function () {
for (var i = 0, n = alerts.length; i < n; i++) {
expect(findCloseButton(i).css('display')).not.toBe('none');
expect(alerts.eq(i)).toHaveClass('alert-dismissible');
}
});
it('should fire callback when closed', function() {
var alerts = createAlerts();
scope.$apply(function() {
scope.removeAlert = jasmine.createSpy();
});
expect(findCloseButton(0).css('display')).not.toBe('none');
findCloseButton(1).click();
expect(scope.removeAlert).toHaveBeenCalledWith(1);
});
it('should not show close buttons if no close callback specified', function () {
var element = $compile('<alert>No close</alert>')(scope);
it('should not show close button and have the dismissible class if no close callback specified', function() {
element = $compile('<div uib-alert>No close</div>')(scope);
scope.$digest();
expect(findCloseButton(0).length).toEqual(0);
expect(findCloseButton(0)).toBeHidden();
expect(element).not.toHaveClass('alert-dismissible');
});
it('it should be possible to add additional classes for alert', function () {
var element = $compile('<alert class="alert-block" type="\'info\'">Default alert!</alert>')(scope);
it('should close automatically if dismiss-on-timeout is defined on the element', function() {
scope.removeAlert = jasmine.createSpy();
$compile('<div uib-alert close="removeAlert()" dismiss-on-timeout="500">Default alert!</div>')(scope);
scope.$digest();
expect(element).toHaveClass('alert-block');
expect(element).toHaveClass('alert-info');
$timeout.flush();
expect(scope.removeAlert).toHaveBeenCalled();
});
it('should not close immediately with a dynamic dismiss-on-timeout', function() {
scope.removeAlert = jasmine.createSpy();
scope.dismissTime = 500;
$compile('<div uib-alert close="removeAlert()" dismiss-on-timeout="{{dismissTime}}">Default alert!</div>')(scope);
scope.$digest();
$timeout.flush(100);
expect(scope.removeAlert).not.toHaveBeenCalled();
$timeout.flush(500);
expect(scope.removeAlert).toHaveBeenCalled();
});
});
+94 -76
View File
@@ -1,76 +1,94 @@
angular.module('ui.bootstrap.buttons', [])
.constant('buttonConfig', {
activeClass:'active',
toggleEvent:'click'
})
.directive('btnRadio', ['buttonConfig', function (buttonConfig) {
var activeClass = buttonConfig.activeClass || 'active';
var toggleEvent = buttonConfig.toggleEvent || 'click';
return {
require:'ngModel',
link:function (scope, element, attrs, ngModelCtrl) {
var value = scope.$eval(attrs.btnRadio);
//model -> UI
scope.$watch(function () {
return ngModelCtrl.$modelValue;
}, function (modelValue) {
if (angular.equals(modelValue, value)){
element.addClass(activeClass);
} else {
element.removeClass(activeClass);
}
});
//ui->model
element.bind(toggleEvent, function () {
if (!element.hasClass(activeClass)) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(value);
});
}
});
}
};
}])
.directive('btnCheckbox', ['buttonConfig', function (buttonConfig) {
var activeClass = buttonConfig.activeClass || 'active';
var toggleEvent = buttonConfig.toggleEvent || 'click';
return {
require:'ngModel',
link:function (scope, element, attrs, ngModelCtrl) {
var trueValue = scope.$eval(attrs.btnCheckboxTrue);
var falseValue = scope.$eval(attrs.btnCheckboxFalse);
trueValue = angular.isDefined(trueValue) ? trueValue : true;
falseValue = angular.isDefined(falseValue) ? falseValue : false;
//model -> UI
scope.$watch(function () {
return ngModelCtrl.$modelValue;
}, function (modelValue) {
if (angular.equals(modelValue, trueValue)) {
element.addClass(activeClass);
} else {
element.removeClass(activeClass);
}
});
//ui->model
element.bind(toggleEvent, function () {
scope.$apply(function () {
ngModelCtrl.$setViewValue(element.hasClass(activeClass) ? falseValue : trueValue);
});
});
}
};
}]);
angular.module('ui.bootstrap.buttons', [])
.constant('uibButtonConfig', {
activeClass: 'active',
toggleEvent: 'click'
})
.controller('UibButtonsController', ['uibButtonConfig', function(buttonConfig) {
this.activeClass = buttonConfig.activeClass || 'active';
this.toggleEvent = buttonConfig.toggleEvent || 'click';
}])
.directive('uibBtnRadio', ['$parse', function($parse) {
return {
require: ['uibBtnRadio', 'ngModel'],
controller: 'UibButtonsController',
controllerAs: 'buttons',
link: function(scope, element, attrs, ctrls) {
var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
var uncheckableExpr = $parse(attrs.uibUncheckable);
element.find('input').css({display: 'none'});
//model -> UI
ngModelCtrl.$render = function() {
element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));
};
//ui->model
element.on(buttonsCtrl.toggleEvent, function() {
if (attrs.disabled) {
return;
}
var isActive = element.hasClass(buttonsCtrl.activeClass);
if (!isActive || angular.isDefined(attrs.uncheckable)) {
scope.$apply(function() {
ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.uibBtnRadio));
ngModelCtrl.$render();
});
}
});
if (attrs.uibUncheckable) {
scope.$watch(uncheckableExpr, function(uncheckable) {
attrs.$set('uncheckable', uncheckable ? '' : undefined);
});
}
}
};
}])
.directive('uibBtnCheckbox', function() {
return {
require: ['uibBtnCheckbox', 'ngModel'],
controller: 'UibButtonsController',
controllerAs: 'button',
link: function(scope, element, attrs, ctrls) {
var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
element.find('input').css({display: 'none'});
function getTrueValue() {
return getCheckboxValue(attrs.btnCheckboxTrue, true);
}
function getFalseValue() {
return getCheckboxValue(attrs.btnCheckboxFalse, false);
}
function getCheckboxValue(attribute, defaultValue) {
return angular.isDefined(attribute) ? scope.$eval(attribute) : defaultValue;
}
//model -> UI
ngModelCtrl.$render = function() {
element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
};
//ui->model
element.on(buttonsCtrl.toggleEvent, function() {
if (attrs.disabled) {
return;
}
scope.$apply(function() {
ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
ngModelCtrl.$render();
});
});
}
};
});
+32 -21
View File
@@ -1,21 +1,32 @@
<div ng-controller="ButtonsCtrl">
<h4>Single toggle</h4>
<pre>{{singleModel}}</pre>
<button type="button" class="btn btn-primary" ng-model="singleModel" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
Single Toggle
</button>
<h4>Checkbox</h4>
<pre>{{checkModel}}</pre>
<div class="btn-group">
<button type="button" class="btn btn-primary" ng-model="checkModel.left" btn-checkbox>Left</button>
<button type="button" class="btn btn-primary" ng-model="checkModel.middle" btn-checkbox>Middle</button>
<button type="button" class="btn btn-primary" ng-model="checkModel.right" btn-checkbox>Right</button>
</div>
<h4>Radio</h4>
<pre>{{radioModel}}</pre>
<div class="btn-group">
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Left'">Left</button>
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'">Middle</button>
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'">Right</button>
</div>
</div>
<div ng-controller="ButtonsCtrl">
<h4>Single toggle</h4>
<pre>{{singleModel}}</pre>
<button type="button" class="btn btn-primary" ng-model="singleModel" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
Single Toggle
</button>
<h4>Checkbox</h4>
<pre>Model: {{checkModel}}</pre>
<pre>Results: {{checkResults}}</pre>
<div class="btn-group">
<label class="btn btn-primary" ng-model="checkModel.left" uib-btn-checkbox>Left</label>
<label class="btn btn-primary" ng-model="checkModel.middle" uib-btn-checkbox>Middle</label>
<label class="btn btn-primary" ng-model="checkModel.right" uib-btn-checkbox>Right</label>
</div>
<h4>Radio &amp; Uncheckable Radio</h4>
<pre>{{radioModel || 'null'}}</pre>
<div class="btn-group">
<label class="btn btn-primary" ng-model="radioModel" uib-btn-radio="'Left'">Left</label>
<label class="btn btn-primary" ng-model="radioModel" uib-btn-radio="'Middle'">Middle</label>
<label class="btn btn-primary" ng-model="radioModel" uib-btn-radio="'Right'">Right</label>
</div>
<div class="btn-group">
<label class="btn btn-success" ng-model="radioModel" uib-btn-radio="'Left'" uncheckable>Left</label>
<label class="btn btn-success" ng-model="radioModel" uib-btn-radio="'Middle'" uncheckable>Middle</label>
<label class="btn btn-success" ng-model="radioModel" uib-btn-radio="'Right'" uib-uncheckable="uncheckable">Right</label>
</div>
<div>
<button class="btn btn-default" ng-click="uncheckable = !uncheckable">
Toggle uncheckable
</button>
</div>
</div>
+22 -12
View File
@@ -1,12 +1,22 @@
var ButtonsCtrl = function ($scope) {
$scope.singleModel = 1;
$scope.radioModel = 'Middle';
$scope.checkModel = {
left: false,
middle: true,
right: false
};
};
angular.module('ui.bootstrap.demo').controller('ButtonsCtrl', function ($scope) {
$scope.singleModel = 1;
$scope.radioModel = 'Middle';
$scope.checkModel = {
left: false,
middle: true,
right: false
};
$scope.checkResults = [];
$scope.$watchCollection('checkModel', function () {
$scope.checkResults = [];
angular.forEach($scope.checkModel, function (value, key) {
if (value) {
$scope.checkResults.push(key);
}
});
});
});
+50 -2
View File
@@ -1,2 +1,50 @@
There are 2 directives that can make a group of buttons to behave like a set of checkboxes or radio buttons.
With the buttons directive, we can make a group of buttons behave like a set of checkboxes (`uib-btn-checkbox`) or behave like a set of radio buttons (`uib-btn-radio`).
### uib-btn-checkbox settings
* `btn-checkbox-false`
_(Default: `false`)_ -
Sets the value for the unchecked status.
* `btn-checkbox-true`
_(Default: `true`)_ -
Sets the value for the checked status.
* `ng-model`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i> -
Model where we set the checkbox status. By default `true` or `false`.
### uib-btn-radio settings
* `ng-model`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i> -
Model where we set the radio status. All radio buttons in a group should use the same `ng-model`.
* `uib-btn-radio` -
<small class="badge">$</small>
Value to assign to the `ng-model` if we check this radio button.
* `uib-uncheckable`
<small class="badge">$</small>
_(Default: `null`)_ -
An expression that evaluates to a truthy or falsy value that determines whether the `uncheckable` attribute is present.
* `uncheckable`
<small class="badge">B</small> -
Whether a radio button can be unchecked or not.
### Additional settings `uibButtonConfig`
* `activeClass`
_(Default: `active`)_ -
Class to apply to the checked buttons.
* `toggleEvent`
_(Default: `click`)_ -
Event used to toggle the buttons.
### Known issues
To use tooltips or popovers on elements within a `btn-group`, set the tooltip/popover `appendToBody` option to `true`. This is due to Bootstrap CSS styling. See [here](http://getbootstrap.com/components/#btn-groups) for more information.
+7
View File
@@ -0,0 +1,7 @@
require('./buttons');
var MODULE_NAME = 'ui.bootstrap.module.buttons';
angular.module(MODULE_NAME, ['ui.bootstrap.buttons']);
module.exports = MODULE_NAME;
+366 -94
View File
@@ -1,94 +1,366 @@
describe('buttons', function () {
var $scope, $compile;
beforeEach(module('ui.bootstrap.buttons'));
beforeEach(inject(function (_$rootScope_, _$compile_) {
$scope = _$rootScope_;
$compile = _$compile_;
}));
describe('checkbox', function () {
var compileButton = function (markup, scope) {
var el = $compile(markup)(scope);
scope.$digest();
return el;
};
//model -> UI
it('should work correctly with default model values', function () {
$scope.model = false;
var btn = compileButton('<button ng-model="model" btn-checkbox>click</button>', $scope);
expect(btn).not.toHaveClass('active');
$scope.model = true;
$scope.$digest();
expect(btn).toHaveClass('active');
});
it('should bind custom model values', function () {
$scope.model = 1;
var btn = compileButton('<button ng-model="model" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">click</button>', $scope);
expect(btn).toHaveClass('active');
$scope.model = 0;
$scope.$digest();
expect(btn).not.toHaveClass('active');
});
//UI-> model
it('should toggle default model values on click', function () {
$scope.model = false;
var btn = compileButton('<button ng-model="model" btn-checkbox>click</button>', $scope);
btn.click();
expect($scope.model).toEqual(true);
btn.click();
expect($scope.model).toEqual(false);
});
it('should toggle custom model values on click', function () {
$scope.model = 0;
var btn = compileButton('<button ng-model="model" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">click</button>', $scope);
btn.click();
expect($scope.model).toEqual(1);
btn.click();
expect($scope.model).toEqual(0);
});
});
describe('radio', function () {
var compileButtons = function (markup, scope) {
var el = $compile('<div>'+markup+'</div>')(scope);
scope.$digest();
return el.find('button');
};
//model -> UI
it('should work correctly set active class based on model', function () {
var btns = compileButtons('<button ng-model="model" btn-radio="1">click1</button><button ng-model="model" btn-radio="2">click2</button>', $scope);
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
$scope.model = 2;
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
});
//UI->model
it('should work correctly set active class based on model', function () {
var btns = compileButtons('<button ng-model="model" btn-radio="1">click1</button><button ng-model="model" btn-radio="2">click2</button>', $scope);
expect($scope.model).toBeUndefined();
btns.eq(0).click();
expect($scope.model).toEqual(1);
btns.eq(1).click();
expect($scope.model).toEqual(2);
});
});
});
describe('buttons', function() {
var $scope, $compile;
beforeEach(module('ui.bootstrap.buttons'));
beforeEach(inject(function(_$rootScope_, _$compile_) {
$scope = _$rootScope_;
$compile = _$compile_;
}));
describe('checkbox', function() {
var compileButton = function(markup, scope) {
var el = $compile(markup)(scope);
scope.$digest();
return el;
};
it('should expose the controller to the view', inject(function($templateCache) {
var btn = compileButton('<button ng-model="model" uib-btn-checkbox>{{button.text}}</button>', $scope);
var ctrl = btn.controller('uibBtnCheckbox');
expect(ctrl).toBeDefined();
ctrl.text = 'foo';
$scope.$digest();
expect(btn.html()).toBe('foo');
}));
//model -> UI
it('should work correctly with default model values', function() {
$scope.model = false;
var btn = compileButton('<button ng-model="model" uib-btn-checkbox>click</button>', $scope);
expect(btn).not.toHaveClass('active');
$scope.model = true;
$scope.$digest();
expect(btn).toHaveClass('active');
});
it('should bind custom model values', function() {
$scope.model = 1;
var btn = compileButton('<button ng-model="model" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">click</button>', $scope);
expect(btn).toHaveClass('active');
$scope.model = 0;
$scope.$digest();
expect(btn).not.toHaveClass('active');
});
//UI-> model
it('should toggle default model values on click', function() {
$scope.model = false;
var btn = compileButton('<button ng-model="model" uib-btn-checkbox>click</button>', $scope);
btn.click();
expect($scope.model).toEqual(true);
expect(btn).toHaveClass('active');
btn.click();
expect($scope.model).toEqual(false);
expect(btn).not.toHaveClass('active');
});
it('should toggle custom model values on click', function() {
$scope.model = 0;
var btn = compileButton('<button ng-model="model" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">click</button>', $scope);
btn.click();
expect($scope.model).toEqual(1);
expect(btn).toHaveClass('active');
btn.click();
expect($scope.model).toEqual(0);
expect(btn).not.toHaveClass('active');
});
it('should monitor true / false value changes - issue 666', function() {
$scope.model = 1;
$scope.trueVal = 1;
var btn = compileButton('<button ng-model="model" uib-btn-checkbox btn-checkbox-true="trueVal">click</button>', $scope);
expect(btn).toHaveClass('active');
expect($scope.model).toEqual(1);
$scope.model = 2;
$scope.trueVal = 2;
$scope.$digest();
expect(btn).toHaveClass('active');
expect($scope.model).toEqual(2);
});
it('should not toggle when disabled - issue 4013', function() {
$scope.model = 1;
$scope.falseVal = 0;
var btn = compileButton('<button disabled ng-model="model" uib-btn-checkbox btn-checkbox-true="falseVal">click</button>', $scope);
expect(btn).not.toHaveClass('active');
expect($scope.model).toEqual(1);
btn.click();
expect(btn).not.toHaveClass('active');
$scope.$digest();
expect(btn).not.toHaveClass('active');
});
describe('setting buttonConfig', function() {
var uibButtonConfig, originalActiveClass, originalToggleEvent;
beforeEach(inject(function(_uibButtonConfig_) {
uibButtonConfig = _uibButtonConfig_;
originalActiveClass = uibButtonConfig.activeClass;
originalToggleEvent = uibButtonConfig.toggleEvent;
uibButtonConfig.activeClass = false;
uibButtonConfig.toggleEvent = false;
}));
afterEach(function() {
// return it to the original value
uibButtonConfig.activeClass = originalActiveClass;
uibButtonConfig.toggleEvent = originalToggleEvent;
});
it('should use default config when buttonConfig.activeClass and buttonConfig.toggleEvent is false', function() {
$scope.model = false;
var btn = compileButton('<button ng-model="model" uib-btn-checkbox>click</button>', $scope);
expect(btn).not.toHaveClass('active');
$scope.model = true;
$scope.$digest();
expect(btn).toHaveClass('active');
});
it('should be able to use a different active class', function() {
uibButtonConfig.activeClass = 'foo';
$scope.model = false;
var btn = compileButton('<button ng-model="model" uib-btn-checkbox>click</button>', $scope);
expect(btn).not.toHaveClass('foo');
$scope.model = true;
$scope.$digest();
expect(btn).toHaveClass('foo');
});
it('should be able to use a different toggle event', function() {
uibButtonConfig.toggleEvent = 'mouseenter';
$scope.model = false;
var btn = compileButton('<button ng-model="model" uib-btn-checkbox>click</button>', $scope);
expect(btn).not.toHaveClass('active');
btn.trigger('mouseenter');
$scope.$digest();
expect(btn).toHaveClass('active');
});
});
});
describe('radio', function() {
var compileButtons = function(markup, scope) {
var el = $compile('<div>'+markup+'</div>')(scope);
scope.$digest();
return el.find('button');
};
it('should expose the controller to the view', inject(function($templateCache) {
var btn = compileButtons('<button ng-model="model" uib-btn-radio="1">{{buttons.text}}</button>', $scope);
var ctrl = btn.controller('uibBtnRadio');
expect(ctrl).toBeDefined();
ctrl.text = 'foo';
$scope.$digest();
expect(btn.html()).toBe('foo');
}));
//model -> UI
it('should set active class based on model', function() {
var btns = compileButtons('<button ng-model="model" uib-btn-radio="1">click1</button><button ng-model="model" uib-btn-radio="2">click2</button>', $scope);
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
$scope.model = 2;
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
});
//UI->model
it('should set active class via click', function() {
var btns = compileButtons('<button ng-model="model" uib-btn-radio="1">click1</button><button ng-model="model" uib-btn-radio="2">click2</button>', $scope);
expect($scope.model).toBeUndefined();
btns.eq(0).click();
expect($scope.model).toEqual(1);
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
btns.eq(1).click();
expect($scope.model).toEqual(2);
expect(btns.eq(1)).toHaveClass('active');
expect(btns.eq(0)).not.toHaveClass('active');
});
it('should watch uib-btn-radio values and update state accordingly', function() {
$scope.values = ['value1', 'value2'];
var btns = compileButtons('<button ng-model="model" uib-btn-radio="values[0]">click1</button><button ng-model="model" uib-btn-radio="values[1]">click2</button>', $scope);
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
$scope.model = 'value2';
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
$scope.values[1] = 'value3';
$scope.model = 'value3';
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
});
it('should do nothing when clicking an active radio', function() {
$scope.model = 1;
var btns = compileButtons('<button ng-model="model" uib-btn-radio="1">click1</button><button ng-model="model" uib-btn-radio="2">click2</button>', $scope);
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
btns.eq(0).click();
$scope.$digest();
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
});
it('should not toggle when disabled - issue 4013', function() {
$scope.model = 1;
var btns = compileButtons('<button ng-model="model" uib-btn-radio="1">click1</button><button disabled ng-model="model" uib-btn-radio="2">click2</button>', $scope);
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
btns.eq(1).click();
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
$scope.$digest();
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
});
it('should handle string values in uib-btn-radio value', function() {
$scope.model = 'Two';
var btns = compileButtons('<button ng-model="model" uib-btn-radio="\'One\'">click1</button><button ng-model="model" uib-btn-radio="\'Two\'">click2</button>', $scope);
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
btns.eq(0).click();
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
expect($scope.model).toEqual('One');
$scope.$digest();
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
expect($scope.model).toEqual('One');
});
describe('uncheckable', function() {
//model -> UI
it('should set active class based on model', function() {
var btns = compileButtons('<button ng-model="model" uib-btn-radio="1" uncheckable>click1</button><button ng-model="model" uib-btn-radio="2" uncheckable>click2</button>', $scope);
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
$scope.model = 2;
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
});
//UI->model
it('should unset active class via click', function() {
var btns = compileButtons('<button ng-model="model" uib-btn-radio="1" uncheckable>click1</button><button ng-model="model" uib-btn-radio="2" uncheckable>click2</button>', $scope);
expect($scope.model).toBeUndefined();
btns.eq(0).click();
expect($scope.model).toEqual(1);
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
btns.eq(0).click();
expect($scope.model).toBeNull();
expect(btns.eq(1)).not.toHaveClass('active');
expect(btns.eq(0)).not.toHaveClass('active');
});
it('should watch uib-btn-radio values and update state', function() {
$scope.values = ['value1', 'value2'];
var btns = compileButtons('<button ng-model="model" uib-btn-radio="values[0]" uncheckable>click1</button><button ng-model="model" uib-btn-radio="values[1]" uncheckable>click2</button>', $scope);
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
$scope.model = 'value2';
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
$scope.model = undefined;
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
});
});
describe('uibUncheckable', function() {
it('should set uncheckable', function() {
$scope.uncheckable = false;
var btns = compileButtons('<button ng-model="model" uib-btn-radio="1">click1</button><button ng-model="model" uib-btn-radio="2" uib-uncheckable="uncheckable">click2</button>', $scope);
expect(btns.eq(0).attr('uncheckable')).toBeUndefined();
expect(btns.eq(1).attr('uncheckable')).toBeUndefined();
expect($scope.model).toBeUndefined();
btns.eq(0).click();
expect($scope.model).toEqual(1);
btns.eq(0).click();
expect($scope.model).toEqual(1);
btns.eq(1).click();
expect($scope.model).toEqual(2);
btns.eq(1).click();
expect($scope.model).toEqual(2);
$scope.uncheckable = true;
$scope.$digest();
expect(btns.eq(0).attr('uncheckable')).toBeUndefined();
expect(btns.eq(1).attr('uncheckable')).toBeDefined();
btns.eq(0).click();
expect($scope.model).toEqual(1);
btns.eq(0).click();
expect($scope.model).toEqual(1);
btns.eq(1).click();
expect($scope.model).toEqual(2);
btns.eq(1).click();
expect($scope.model).toBeNull();
});
});
});
});
+4
View File
@@ -0,0 +1,4 @@
.ng-animate.item:not(.left):not(.right) {
-webkit-transition: 0s ease-in-out left;
transition: 0s ease-in-out left
}
+303 -143
View File
@@ -1,185 +1,296 @@
/*
*
* AngularJS Bootstrap Carousel
*
* A pure AngularJS carousel.
*
* For no interval set the interval to non-number, or milliseconds of desired interval
* Template: <carousel interval="none"><slide>{{anything}}</slide></carousel>
* To change the carousel's active slide set the active attribute to true
* Template: <carousel interval="none"><slide active="someModel">{{anything}}</slide></carousel>
*/
angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
.controller('CarouselController', ['$scope', '$timeout', '$transition', '$q', function ($scope, $timeout, $transition, $q) {
angular.module('ui.bootstrap.carousel', [])
.controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function($scope, $element, $interval, $timeout, $animate) {
var self = this,
slides = self.slides = [],
currentIndex = -1,
currentTimeout, isPlaying;
self.currentSlide = null;
slides = self.slides = $scope.slides = [],
SLIDE_DIRECTION = 'uib-slideDirection',
currentIndex = $scope.active,
currentInterval, isPlaying;
var destroyed = false;
$element.addClass('carousel');
self.addSlide = function(slide, element) {
slides.push({
slide: slide,
element: element
});
slides.sort(function(a, b) {
return +a.slide.index - +b.slide.index;
});
//if this is the first slide or the slide is set to active, select it
if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) {
if ($scope.$currentTransition) {
$scope.$currentTransition = null;
}
currentIndex = slide.index;
$scope.active = slide.index;
setActive(currentIndex);
self.select(slides[findSlideIndex(slide)]);
if (slides.length === 1) {
$scope.play();
}
}
};
self.getCurrentIndex = function() {
for (var i = 0; i < slides.length; i++) {
if (slides[i].slide.index === currentIndex) {
return i;
}
}
};
self.next = $scope.next = function() {
var newIndex = (self.getCurrentIndex() + 1) % slides.length;
if (newIndex === 0 && $scope.noWrap()) {
$scope.pause();
return;
}
return self.select(slides[newIndex], 'next');
};
self.prev = $scope.prev = function() {
var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;
if ($scope.noWrap() && newIndex === slides.length - 1) {
$scope.pause();
return;
}
return self.select(slides[newIndex], 'prev');
};
self.removeSlide = function(slide) {
var index = findSlideIndex(slide);
//get the index of the slide inside the carousel
slides.splice(index, 1);
if (slides.length > 0 && currentIndex === index) {
if (index >= slides.length) {
currentIndex = slides.length - 1;
$scope.active = currentIndex;
setActive(currentIndex);
self.select(slides[slides.length - 1]);
} else {
currentIndex = index;
$scope.active = currentIndex;
setActive(currentIndex);
self.select(slides[index]);
}
} else if (currentIndex > index) {
currentIndex--;
$scope.active = currentIndex;
}
//clean the active value when no more slide
if (slides.length === 0) {
currentIndex = null;
$scope.active = null;
}
};
/* direction: "prev" or "next" */
self.select = function(nextSlide, direction) {
var nextIndex = slides.indexOf(nextSlide);
self.select = $scope.select = function(nextSlide, direction) {
var nextIndex = findSlideIndex(nextSlide.slide);
//Decide direction if it's not given
if (direction === undefined) {
direction = nextIndex > currentIndex ? "next" : "prev";
direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
}
if (nextSlide && nextSlide !== self.currentSlide) {
if ($scope.$currentTransition) {
$scope.$currentTransition.cancel();
//Timeout so ng-class in template has time to fix classes for finished slide
$timeout(goNext);
} else {
goNext();
}
}
function goNext() {
//If we have a slide to transition from and we have a transition type and we're allowed, go
if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) {
//We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime
nextSlide.$element.addClass(direction);
nextSlide.$element[0].offsetWidth = nextSlide.$element[0].offsetWidth; //force reflow
//Set all other slides to stop doing their stuff for the new transition
angular.forEach(slides, function(slide) {
angular.extend(slide, {direction: '', entering: false, leaving: false, active: false});
});
angular.extend(nextSlide, {direction: direction, active: true, entering: true});
angular.extend(self.currentSlide||{}, {direction: direction, leaving: true});
$scope.$currentTransition = $transition(nextSlide.$element, {});
//We have to create new pointers inside a closure since next & current will change
(function(next,current) {
$scope.$currentTransition.then(
function(){ transitionDone(next, current); },
function(){ transitionDone(next, current); }
);
}(nextSlide, self.currentSlide));
} else {
transitionDone(nextSlide, self.currentSlide);
}
self.currentSlide = nextSlide;
currentIndex = nextIndex;
//every time you change slides, reset the timer
restartTimer();
}
function transitionDone(next, current) {
angular.extend(next, {direction: '', active: true, leaving: false, entering: false});
angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false});
$scope.$currentTransition = null;
//Prevent this user-triggered transition from occurring if there is already one in progress
if (nextSlide.slide.index !== currentIndex &&
!$scope.$currentTransition) {
goNext(nextSlide.slide, nextIndex, direction);
}
};
/* Allow outside people to call indexOf on slides array */
self.indexOfSlide = function(slide) {
return slides.indexOf(slide);
};
$scope.next = function() {
var newIndex = (currentIndex + 1) % slides.length;
return self.select(slides[newIndex], 'next');
};
$scope.prev = function() {
var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1;
return self.select(slides[newIndex], 'prev');
};
$scope.select = function(slide) {
self.select(slide);
$scope.indexOfSlide = function(slide) {
return +slide.slide.index;
};
$scope.isActive = function(slide) {
return self.currentSlide === slide;
return $scope.active === slide.slide.index;
};
$scope.slides = function() {
return slides;
$scope.isPrevDisabled = function() {
return $scope.active === 0 && $scope.noWrap();
};
$scope.$watch('interval', restartTimer);
function restartTimer() {
if (currentTimeout) {
$timeout.cancel(currentTimeout);
$scope.isNextDisabled = function() {
return $scope.active === slides.length - 1 && $scope.noWrap();
};
$scope.pause = function() {
if (!$scope.noPause) {
isPlaying = false;
resetTimer();
}
function go() {
if (isPlaying) {
$scope.next();
restartTimer();
} else {
$scope.pause();
}
}
var interval = +$scope.interval;
if (!isNaN(interval) && interval>=0) {
currentTimeout = $timeout(go, interval);
}
}
};
$scope.play = function() {
if (!isPlaying) {
isPlaying = true;
restartTimer();
}
};
$scope.pause = function() {
isPlaying = false;
if (currentTimeout) {
$timeout.cancel(currentTimeout);
}
};
self.addSlide = function(slide, element) {
slide.$element = element;
slides.push(slide);
//if this is the first slide or the slide is set to active, select it
if(slides.length === 1 || slide.active) {
self.select(slides[slides.length-1]);
if (slides.length == 1) {
$scope.play();
$element.on('mouseenter', $scope.pause);
$element.on('mouseleave', $scope.play);
$scope.$on('$destroy', function() {
destroyed = true;
resetTimer();
});
$scope.$watch('noTransition', function(noTransition) {
$animate.enabled($element, !noTransition);
});
$scope.$watch('interval', restartTimer);
$scope.$watchCollection('slides', resetTransition);
$scope.$watch('active', function(index) {
if (angular.isNumber(index) && currentIndex !== index) {
for (var i = 0; i < slides.length; i++) {
if (slides[i].slide.index === index) {
index = i;
break;
}
}
} else {
slide.active = false;
}
};
self.removeSlide = function(slide) {
//get the index of the slide inside the carousel
var index = slides.indexOf(slide);
slides.splice(index, 1);
if (slides.length > 0 && slide.active) {
if (index >= slides.length) {
self.select(slides[index-1]);
} else {
var slide = slides[index];
if (slide) {
setActive(index);
self.select(slides[index]);
currentIndex = index;
}
}
};
});
function getSlideByIndex(index) {
for (var i = 0, l = slides.length; i < l; ++i) {
if (slides[i].index === index) {
return slides[i];
}
}
}
function setActive(index) {
for (var i = 0; i < slides.length; i++) {
slides[i].slide.active = i === index;
}
}
function goNext(slide, index, direction) {
if (destroyed) {
return;
}
angular.extend(slide, {direction: direction});
angular.extend(slides[currentIndex].slide || {}, {direction: direction});
if ($animate.enabled($element) && !$scope.$currentTransition &&
slides[index].element && self.slides.length > 1) {
slides[index].element.data(SLIDE_DIRECTION, slide.direction);
var currentIdx = self.getCurrentIndex();
if (angular.isNumber(currentIdx) && slides[currentIdx].element) {
slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction);
}
$scope.$currentTransition = true;
$animate.on('addClass', slides[index].element, function(element, phase) {
if (phase === 'close') {
$scope.$currentTransition = null;
$animate.off('addClass', element);
}
});
}
$scope.active = slide.index;
currentIndex = slide.index;
setActive(index);
//every time you change slides, reset the timer
restartTimer();
}
function findSlideIndex(slide) {
for (var i = 0; i < slides.length; i++) {
if (slides[i].slide === slide) {
return i;
}
}
}
function resetTimer() {
if (currentInterval) {
$interval.cancel(currentInterval);
currentInterval = null;
}
}
function resetTransition(slides) {
if (!slides.length) {
$scope.$currentTransition = null;
}
}
function restartTimer() {
resetTimer();
var interval = +$scope.interval;
if (!isNaN(interval) && interval > 0) {
currentInterval = $interval(timerFn, interval);
}
}
function timerFn() {
var interval = +$scope.interval;
if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {
$scope.next();
} else {
$scope.pause();
}
}
}])
.directive('carousel', [function() {
.directive('uibCarousel', function() {
return {
restrict: 'EA',
transclude: true,
replace: true,
controller: 'CarouselController',
require: 'carousel',
templateUrl: 'template/carousel/carousel.html',
controller: 'UibCarouselController',
controllerAs: 'carousel',
restrict: 'A',
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/carousel/carousel.html';
},
scope: {
active: '=',
interval: '=',
noTransition: '='
noTransition: '=',
noPause: '=',
noWrap: '&'
}
};
}])
.directive('slide', [function() {
})
.directive('uibSlide', ['$animate', function($animate) {
return {
require: '^carousel',
restrict: 'EA',
require: '^uibCarousel',
restrict: 'A',
transclude: true,
replace: true,
templateUrl: 'template/carousel/slide.html',
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/carousel/slide.html';
},
scope: {
active: '='
actual: '=?',
index: '=?'
},
link: function (scope, element, attrs, carouselCtrl) {
element.addClass('item');
carouselCtrl.addSlide(scope, element);
//when the scope is destroyed then remove the slide from the current slides array
scope.$on('$destroy', function() {
@@ -187,10 +298,59 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
});
scope.$watch('active', function(active) {
if (active) {
carouselCtrl.select(scope);
}
$animate[active ? 'addClass' : 'removeClass'](element, 'active');
});
}
};
}])
.animation('.item', ['$animateCss',
function($animateCss) {
var SLIDE_DIRECTION = 'uib-slideDirection';
function removeClass(element, className, callback) {
element.removeClass(className);
if (callback) {
callback();
}
}
return {
beforeAddClass: function(element, className, done) {
if (className === 'active') {
var stopped = false;
var direction = element.data(SLIDE_DIRECTION);
var directionClass = direction === 'next' ? 'left' : 'right';
var removeClassFn = removeClass.bind(this, element,
directionClass + ' ' + direction, done);
element.addClass(direction);
$animateCss(element, {addClass: directionClass})
.start()
.done(removeClassFn);
return function() {
stopped = true;
};
}
done();
},
beforeRemoveClass: function (element, className, done) {
if (className === 'active') {
var stopped = false;
var direction = element.data(SLIDE_DIRECTION);
var directionClass = direction === 'next' ? 'left' : 'right';
var removeClassFn = removeClass.bind(this, element, directionClass, done);
$animateCss(element, {addClass: directionClass})
.start()
.done(removeClassFn);
return function() {
stopped = true;
};
}
done();
}
};
}]);
+55 -1
View File
@@ -1,3 +1,57 @@
Carousel creates a carousel similar to bootstrap's image carousel.
Use a `<carousel>` element with `<slide>` elements inside it. It will automatically cycle through the slides at a given rate, and a current-index variable will be kept in sync with the currently visible slide.
The carousel also offers support for touchscreen devices in the form of swiping. To enable swiping, load the `ngTouch` module as a dependency.
Use a `<uib-carousel>` element with `<uib-slide>` elements inside it.
### uib-carousel settings
* `active`
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `Index of first slide`)_ -
Index of current active slide.
* `interval`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `none`)_ -
Sets an interval to cycle through the slides. You need a number bigger than 0 to make the interval work.
* `no-pause`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `false`)_ -
The interval pauses on mouseover. Setting this to truthy, disables this pause.
* `no-transition`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `false`)_ -
Whether to disable the transition animation between slides. Setting this to truthy, disables this transition.
* `no-wrap`
<small class="badge">$</small>
_(Default: `false`)_ -
Disables the looping of slides. Setting `no-wrap` to an expression which evaluates to a truthy value will prevent looping.
* `template-url`
_(Default: `uib/template/carousel/carousel.html`)_ -
Add the ability to override the template used on the component.
### uib-slide settings
* `actual`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `none`)_ -
Use this attribute to bind the slide model (or any object of interest) onto the slide scope, which makes it available for customization in the carousel template.
* `index`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `none`)_ -
The index of the slide. Must be unique.
* `template-url`
_(Default: `uib/template/carousel/slide.html`)_ -
Add the ability to override the template used on the component.
+23 -20
View File
@@ -1,26 +1,29 @@
<div ng-controller="CarouselDemoCtrl">
<carousel interval="myInterval">
<slide ng-repeat="slide in slides" active="slide.active">
<img ng-src="{{slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{$index}}</h4>
<p>{{slide.text}}</p>
<div style="height: 305px">
<div uib-carousel active="active" interval="myInterval" no-wrap="noWrapSlides">
<div uib-slide ng-repeat="slide in slides track by slide.id" index="slide.id">
<img ng-src="{{slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{slide.id}}</h4>
<p>{{slide.text}}</p>
</div>
</div>
</slide>
</carousel>
<div class="row-fluid">
<div class="span6">
<ul>
<li ng-repeat="slide in slides">
<button class="btn btn-mini" ng-class="{'btn-info': !slide.active, 'btn-success': slide.active}" ng-disabled="slide.active" ng-click="slide.active = true">select</button>
{{$index}}: {{slide.text}}
</li>
</ul>
<a class="btn" ng-click="addSlide()">Add Slide</a>
</div>
<div class="span6">
Interval, in milliseconds: <input type="number" ng-model="myInterval">
<br />Enter a negative number to stop the interval.
</div>
<div class="row">
<div class="col-md-6">
<button type="button" class="btn btn-info" ng-click="addSlide()">Add Slide</button>
<button type="button" class="btn btn-info" ng-click="randomize()">Randomize slides</button>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="noWrapSlides">
Disable Slide Looping
</label>
</div>
</div>
<div class="col-md-6">
Interval, in milliseconds: <input type="number" class="form-control" ng-model="myInterval">
<br />Enter a negative number or 0 to stop the interval.
</div>
</div>
</div>
+53 -12
View File
@@ -1,16 +1,57 @@
function CarouselDemoCtrl($scope) {
angular.module('ui.bootstrap.demo').controller('CarouselDemoCtrl', function ($scope) {
$scope.myInterval = 5000;
$scope.slides = [
{image: 'http://placekitten.com/200/200',text: 'Kitten.'},
{image: 'http://placekitten.com/225/200',text: 'Kitty!'},
{image: 'http://placekitten.com/250/200',text: 'Cat.'},
{image: 'http://placekitten.com/275/200',text: 'Feline!'}
];
$scope.noWrapSlides = false;
$scope.active = 0;
var slides = $scope.slides = [];
var currIndex = 0;
$scope.addSlide = function() {
$scope.slides.push({
image: 'http://placekitten.com/'+(200+25*Math.floor(Math.random()*4))+'/200',
text: ['More','Extra','Lots of','Surplus'][Math.floor(Math.random()*4)] + ' ' +
['Cats', 'Kittys', 'Felines', 'Cutes'][Math.floor(Math.random()*4)]
var newWidth = 600 + slides.length + 1;
slides.push({
image: '//unsplash.it/' + newWidth + '/300',
text: ['Nice image','Awesome photograph','That is so cool','I love that'][slides.length % 4],
id: currIndex++
});
};
}
$scope.randomize = function() {
var indexes = generateIndexesArray();
assignNewIndexesToSlides(indexes);
};
for (var i = 0; i < 4; i++) {
$scope.addSlide();
}
// Randomize logic below
function assignNewIndexesToSlides(indexes) {
for (var i = 0, l = slides.length; i < l; i++) {
slides[i].id = indexes.pop();
}
}
function generateIndexesArray() {
var indexes = [];
for (var i = 0; i < currIndex; ++i) {
indexes[i] = i;
}
return shuffle(indexes);
}
// http://stackoverflow.com/questions/962802#962890
function shuffle(array) {
var tmp, current, top = array.length;
if (top) {
while (--top) {
current = Math.floor(Math.random() * (top + 1));
tmp = array[current];
array[current] = array[top];
array[top] = tmp;
}
}
return array;
}
});
+9
View File
@@ -0,0 +1,9 @@
require('../../template/carousel/carousel.html.js');
require('../../template/carousel/slide.html.js');
require('./carousel');
var MODULE_NAME = 'ui.bootstrap.module.carousel';
angular.module(MODULE_NAME, ['ui.bootstrap.carousel', 'uib/template/carousel/carousel.html', 'uib/template/carousel/slide.html']);
module.exports = MODULE_NAME;
+2
View File
@@ -0,0 +1,2 @@
require('./carousel.css');
module.exports = require('./index-nocss.js');
+428 -102
View File
@@ -1,53 +1,76 @@
describe('carousel', function() {
beforeEach(module('ui.bootstrap.carousel'));
beforeEach(module('template/carousel/carousel.html', 'template/carousel/slide.html'));
var $rootScope, elm, $compile, $controller, $timeout;
beforeEach(inject(function(_$rootScope_, _$compile_, _$controller_, _$timeout_) {
beforeEach(module('ngAnimateMock'));
beforeEach(module('uib/template/carousel/carousel.html', 'uib/template/carousel/slide.html'));
var $rootScope, $compile, $controller, $interval, $templateCache, $timeout, $animate;
beforeEach(inject(function(_$rootScope_, _$compile_, _$controller_, _$interval_, _$templateCache_, _$timeout_, _$animate_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
$controller = _$controller_;
$interval = _$interval_;
$templateCache = _$templateCache_;
$timeout = _$timeout_;
$animate = _$animate_;
}));
describe('basics', function() {
var elm, scope, carouselScope;
var elm, scope;
beforeEach(function() {
scope = $rootScope.$new();
scope.slides = [
{active:false,content:'one'},
{active:false,content:'two'},
{active:false,content:'three'}
{content: 'one', index: 0},
{content: 'two', index: 1},
{content: 'three', index: 2}
];
elm = $compile(
'<carousel interval="interval" no-transition="true">' +
'<slide ng-repeat="slide in slides" active="slide.active">' +
'<div uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
'<div uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
'{{slide.content}}' +
'</slide>' +
'</carousel>'
'</div>' +
'</div>'
)(scope);
carouselScope = elm.scope();
scope.interval = 5000;
scope.nopause = undefined;
scope.$apply();
});
afterEach(function() {
scope.$destroy();
});
function testSlideActive(slideIndex) {
for (var i=0; i<scope.slides.length; i++) {
if (i == slideIndex) {
expect(scope.slides[i].active).toBe(true);
for (var i = 0; i < scope.slides.length; i++) {
if (i === slideIndex) {
expect(scope.active).toBe(scope.slides[i].index);
} else {
expect(scope.slides[i].active).not.toBe(true);
expect(scope.active).not.toBe(scope.slides[i].index);
}
}
}
it('should set the selected slide to active = true', function() {
expect(scope.slides[0].content).toBe('one');
it('should allow overriding of the carousel template', function() {
$templateCache.put('foo/bar.html', '<div>foo</div>');
elm = $compile('<div uib-carousel template-url="foo/bar.html"></div>')(scope);
$rootScope.$digest();
expect(elm.html()).toBe('<div>foo</div>');
});
it('should allow overriding of the slide template', function() {
$templateCache.put('foo/bar.html', '<div class="slide">bar</div>');
elm = $compile(
'<div uib-carousel interval="interval" no-transition="true" no-pause="nopause">' +
'<div uib-slide template-url="foo/bar.html"></div>' +
'</div>'
)(scope);
$rootScope.$digest();
var slide = elm.find('.slide');
expect(slide.html()).toBe('bar');
});
it('should be able to select a slide via model changes', function() {
testSlideActive(0);
scope.$apply('slides[1].active=true');
scope.$apply('active=1');
testSlideActive(1);
});
@@ -63,34 +86,110 @@ describe('carousel', function() {
var indicators = elm.find('ol.carousel-indicators > li');
expect(indicators.length).toBe(3);
});
it('should stop cycling slides forward when noWrap is truthy', function () {
elm = $compile(
'<div uib-carousel active="active" interval="interval" no-wrap="noWrap">' +
'<div uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
'{{slide.content}}' +
'</div>' +
'</div>'
)(scope);
scope.noWrap = true;
scope.$apply();
var $scope = elm.isolateScope();
spyOn($scope, 'pause');
scope.active = $scope.slides.length - 1;
scope.$apply();
testSlideActive($scope.slides.length - 1);
$scope.next();
testSlideActive($scope.slides.length - 1);
expect($scope.pause).toHaveBeenCalled();
});
it('should stop cycling slides backward when noWrap is truthy', function () {
elm = $compile(
'<div uib-carousel active="active" interval="interval" no-wrap="noWrap">' +
'<div uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
'{{slide.content}}' +
'</div>' +
'</div>'
)(scope);
scope.noWrap = true;
scope.$apply();
var $scope = elm.isolateScope();
spyOn($scope, 'pause');
testSlideActive(0);
$scope.prev();
testSlideActive(0);
expect($scope.pause).toHaveBeenCalled();
});
it('should hide navigation when only one slide', function () {
scope.slides=[{active:false,content:'one'}];
scope.slides = [{active:false,content:'one'}];
scope.$apply();
elm = $compile(
'<carousel interval="interval" no-transition="true">' +
'<slide ng-repeat="slide in slides" active="slide.active">' +
'{{slide.content}}' +
'</slide>' +
'</carousel>'
)(scope);
'<div uib-carousel active="active" interval="interval" no-transition="true">' +
'<div uib-slide ng-repeat="slide in slides" index="$index">' +
'{{slide.content}}' +
'</div>' +
'</div>'
)(scope);
var indicators = elm.find('ol.carousel-indicators > li');
expect(indicators.length).toBe(0);
var navNext = elm.find('a.right');
expect(navNext.length).toBe(0);
var navPrev = elm.find('a.left');
expect(navPrev.length).toBe(0);
});
it('should show navigation when there are 3 slides', function () {
it('should disable prev button when slide index is 0 and noWrap is truthy', function() {
scope.$apply();
var $scope = elm.isolateScope();
$scope.noWrap = function() {return true;};
$scope.isPrevDisabled();
scope.$apply();
var navPrev = elm.find('a.left');
expect(navPrev.hasClass('disabled')).toBe(true);
});
it('should disable next button when last slide is active and noWrap is truthy', function() {
scope.slides = [
{content: 'one', index: 0},
{content: 'two', index: 1}
];
scope.$apply();
var $scope = elm.isolateScope();
$scope.noWrap = function() {return true;};
$scope.next();
$scope.isNextDisabled();
scope.$apply();
var navNext = elm.find('a.right');
expect(navNext.hasClass('disabled')).toBe(true);
});
it('should show navigation when there are 3 slides', function () {
var indicators = elm.find('ol.carousel-indicators > li');
expect(indicators.length).not.toBe(0);
var navNext = elm.find('a.right');
expect(navNext.length).not.toBe(0);
var navPrev = elm.find('a.left');
expect(navPrev.length).not.toBe(0);
});
@@ -123,23 +222,28 @@ describe('carousel', function() {
testSlideActive(1);
});
it('shouldnt go forward if interval is NaN or negative', function() {
it('shouldnt go forward if interval is NaN or negative or has no slides', function() {
testSlideActive(0);
var previousInterval = scope.interval;
scope.$apply('interval = -1');
//no timeout to flush, interval watch doesn't make a new one when interval is invalid
$interval.flush(previousInterval);
testSlideActive(0);
scope.$apply('interval = 1000');
$timeout.flush();
$interval.flush(1000);
testSlideActive(1);
scope.$apply('interval = false');
$interval.flush(1000);
testSlideActive(1);
scope.$apply('interval = 1000');
$timeout.flush();
$interval.flush(1000);
testSlideActive(2);
scope.$apply('slides = []');
$interval.flush(1000);
testSlideActive(2);
});
it('should bind the content to slides', function() {
var contents = elm.find('div.item');
var contents = elm.find('div.item [ng-transclude]');
expect(contents.length).toBe(3);
expect(contents.eq(0).text()).toBe('one');
@@ -159,112 +263,334 @@ describe('carousel', function() {
it('should be playing by default and cycle through slides', function() {
testSlideActive(0);
$timeout.flush();
$interval.flush(scope.interval);
testSlideActive(1);
$timeout.flush();
$interval.flush(scope.interval);
testSlideActive(2);
$timeout.flush();
$interval.flush(scope.interval);
testSlideActive(0);
});
it('should pause and play on mouseover', function() {
testSlideActive(0);
$timeout.flush();
$interval.flush(scope.interval);
testSlideActive(1);
elm.trigger('mouseenter');
expect($timeout.flush).toThrow();//pause should cancel current timeout
testSlideActive(1);
$interval.flush(scope.interval);
testSlideActive(1);
elm.trigger('mouseleave');
$timeout.flush();
$interval.flush(scope.interval);
testSlideActive(2);
});
it('should not pause on mouseover if noPause', function() {
scope.$apply('nopause = true');
testSlideActive(0);
elm.trigger('mouseenter');
$interval.flush(scope.interval);
testSlideActive(1);
elm.trigger('mouseleave');
$interval.flush(scope.interval);
testSlideActive(2);
});
it('should remove slide from dom and change active slide', function() {
scope.$apply('slides[1].active = true');
testSlideActive(1);
scope.$apply('slides.splice(1,1)');
scope.$apply('active = 2');
testSlideActive(2);
scope.$apply('slides.splice(2,1)');
$timeout.flush(0);
expect(elm.find('div.item').length).toBe(2);
testSlideActive(1);
$interval.flush(scope.interval);
testSlideActive(0);
scope.$apply('slides.splice(1,1)');
$timeout.flush(0);
expect(elm.find('div.item').length).toBe(1);
testSlideActive(0);
});
it('should change dom when you reassign ng-repeat slides array', function() {
scope.slides=[{content:'new1'},{content:'new2'},{content:'new3'}];
scope.slides = [
{content:'new1', index: 4},
{content:'new2', index: 5},
{content:'new3', index: 6}
];
scope.$apply();
var contents = elm.find('div.item');
var contents = elm.find('div.item [ng-transclude]');
expect(contents.length).toBe(3);
expect(contents.eq(0).text()).toBe('new1');
expect(contents.eq(1).text()).toBe('new2');
expect(contents.eq(2).text()).toBe('new3');
scope.$apply('slides.splice(0,1)');
contents = elm.find('div.item');
});
it('should not change if next is clicked while transitioning', function() {
var carouselScope = elm.children().scope();
var next = elm.find('a.right');
testSlideActive(0);
carouselScope.$currentTransition = true;
next.click();
testSlideActive(0);
carouselScope.$currentTransition = null;
next.click();
testSlideActive(1);
});
it('should buffer the slides if transition is clicked and only transition to the last requested', function() {
var carouselScope = elm.children().scope();
testSlideActive(0);
carouselScope.$currentTransition = null;
carouselScope.select(carouselScope.slides[1]);
$animate.flush();
testSlideActive(1);
carouselScope.$currentTransition = true;
carouselScope.select(carouselScope.slides[2]);
scope.$apply();
testSlideActive(1);
carouselScope.select(carouselScope.slides[0]);
scope.$apply();
testSlideActive(1);
carouselScope.$currentTransition = null;
$interval.flush(scope.interval);
$animate.flush();
testSlideActive(2);
$interval.flush(scope.interval);
$animate.flush();
testSlideActive(0);
});
it('issue 1414 - should not continue running timers after scope is destroyed', function() {
testSlideActive(0);
$interval.flush(scope.interval);
testSlideActive(1);
$interval.flush(scope.interval);
testSlideActive(2);
$interval.flush(scope.interval);
testSlideActive(0);
spyOn($interval, 'cancel').and.callThrough();
scope.$destroy();
expect($interval.cancel).toHaveBeenCalled();
});
it('issue 4390 - should reset the currentTransition if there are no slides', function() {
var carouselScope = elm.children().scope();
var next = elm.find('a.right');
scope.slides = [
{content:'new1', index: 1},
{content:'new2', index: 2},
{content:'new3', index: 3}
];
scope.$apply();
testSlideActive(0);
carouselScope.$currentTransition = true;
scope.slides = [];
scope.$apply();
expect(carouselScope.$currentTransition).toBe(null);
});
});
describe('slide order', function() {
var elm, scope;
beforeEach(function() {
scope = $rootScope.$new();
scope.slides = [
{content: 'one', id: 3},
{content: 'two', id: 1},
{content: 'three', id: 2}
];
elm = $compile(
'<div uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
'<div uib-slide ng-repeat="slide in slides | orderBy: \'id\' track by slide.id" index="slide.id">' +
'{{slide.content}}' +
'</div>' +
'</div>'
)(scope);
scope.$apply();
});
function testSlideActive(slideIndex) {
for (var i = 0; i < scope.slides.length; i++) {
if (i === slideIndex) {
expect(scope.active).toBe(scope.slides[i].id);
} else {
expect(scope.active).not.toBe(scope.slides[i].id);
}
}
}
it('should change dom when the order of the slides changes', function() {
scope.slides[0].id = 3;
scope.slides[1].id = 2;
scope.slides[2].id = 1;
scope.$apply();
var contents = elm.find('div.item [ng-transclude]');
expect(contents.length).toBe(3);
expect(contents.eq(0).text()).toBe('three');
expect(contents.eq(1).text()).toBe('two');
expect(contents.eq(2).text()).toBe('one');
});
it('should select next after order change', function() {
testSlideActive(1);
var next = elm.find('a.right');
next.click();
testSlideActive(2);
});
it('should select prev after order change', function() {
testSlideActive(1);
var prev = elm.find('a.left');
prev.click();
testSlideActive(0);
});
it('should add slide in the specified position', function() {
testSlideActive(1);
scope.slides[2].id = 4;
scope.slides.push({content:'four', id: 5});
scope.$apply();
var contents = elm.find('div.item [ng-transclude]');
expect(contents.length).toBe(4);
expect(contents.eq(0).text()).toBe('two');
expect(contents.eq(1).text()).toBe('one');
expect(contents.eq(2).text()).toBe('three');
expect(contents.eq(3).text()).toBe('four');
});
it('should remove slide after order change', function() {
testSlideActive(1);
scope.slides.splice(1, 1);
scope.$apply();
var contents = elm.find('div.item [ng-transclude]');
expect(contents.length).toBe(2);
expect(contents.eq(0).text()).toBe('new2');
expect(contents.eq(0)).toHaveClass('active');
expect(contents.eq(1).text()).toBe('new3');
expect(contents.eq(0).text()).toBe('three');
expect(contents.eq(1).text()).toBe('one');
});
});
describe('controller', function() {
var scope, ctrl;
//create an array of slides and add to the scope
var slides = [{'content': 1},{'content': 2},{'content':3},{'content':4}];
var slides = [
{'content': 1, index: 0},
{'content': 2, index: 1},
{'content': 3, index: 2},
{'content': 4, index: 3}
];
beforeEach(function() {
scope = $rootScope.$new();
ctrl = $controller('CarouselController', {$scope: scope, $element: null});
for(var i = 0;i < slides.length;i++){
scope.noWrap = angular.noop;
ctrl = $controller('UibCarouselController', {$scope: scope, $element: angular.element('<div></div>')});
for (var i = 0; i < slides.length; i++) {
ctrl.addSlide(slides[i]);
}
});
afterEach(function() {
it('should set first slide to active = true and the rest to false', function() {
angular.forEach(ctrl.slides, function(slide, i) {
if (i !== 0) {
expect(slide.slide.active).not.toBe(true);
} else {
expect(slide.slide.active).toBe(true);
}
});
});
it('should add a new slide and not change the active slide', function() {
var newSlide = {active: false, index: 4};
expect(ctrl.slides.length).toBe(4);
ctrl.addSlide(newSlide);
expect(ctrl.slides.length).toBe(5);
expect(ctrl.slides[4].slide.active).toBe(false);
expect(ctrl.slides[0].slide.active).toBe(true);
});
it('should remove slide and change active slide if needed', function() {
expect(ctrl.slides.length).toBe(4);
ctrl.removeSlide(ctrl.slides[0].slide);
$timeout.flush(0);
expect(ctrl.slides.length).toBe(3);
expect(scope.active).toBe(1);
ctrl.select(ctrl.slides[2]);
ctrl.removeSlide(ctrl.slides[2].slide);
$timeout.flush(0);
expect(ctrl.slides.length).toBe(2);
expect(scope.active).toBe(2);
ctrl.removeSlide(ctrl.slides[0].slide);
$timeout.flush(0);
expect(ctrl.slides.length).toBe(1);
expect(scope.active).toBe(1);
});
it('issue 1414 - should not continue running timers after scope is destroyed', function() {
spyOn(scope, 'next');
scope.interval = 2000;
scope.$digest();
$interval.flush(scope.interval);
expect(scope.next.calls.count()).toBe(1);
scope.$destroy();
$interval.flush(scope.interval);
expect(scope.next.calls.count()).toBe(1);
});
describe('addSlide', function() {
it('should set first slide to active = true and the rest to false', function() {
angular.forEach(ctrl.slides, function(slide, i) {
if (i !== 0) {
expect(slide.active).not.toBe(true);
} else {
expect(slide.active).toBe(true);
}
});
});
it('should be exposed in the template', inject(function($templateCache) {
$templateCache.put('uib/template/carousel/carousel.html', '<div>{{carousel.text}}</div>');
it('should add new slide and change active to true if active is true on the added slide', function() {
var newSlide = {active: true};
expect(ctrl.slides.length).toBe(4);
ctrl.addSlide(newSlide);
expect(ctrl.slides.length).toBe(5);
expect(ctrl.slides[4].active).toBe(true);
expect(ctrl.slides[0].active).toBe(false);
});
var scope = $rootScope.$new();
var elm = $compile('<div uib-carousel interval="bar" no-transition="false" no-pause="true"></div>')(scope);
$rootScope.$digest();
it('should add a new slide and not change the active slide', function() {
var newSlide = {active: false};
expect(ctrl.slides.length).toBe(4);
ctrl.addSlide(newSlide);
expect(ctrl.slides.length).toBe(5);
expect(ctrl.slides[4].active).toBe(false);
expect(ctrl.slides[0].active).toBe(true);
});
var ctrl = elm.controller('uibCarousel');
it('should remove slide and change active slide if needed', function() {
expect(ctrl.slides.length).toBe(4);
ctrl.removeSlide(ctrl.slides[0]);
expect(ctrl.slides.length).toBe(3);
expect(ctrl.currentSlide).toBe(ctrl.slides[0]);
ctrl.select(ctrl.slides[2]);
ctrl.removeSlide(ctrl.slides[2]);
expect(ctrl.slides.length).toBe(2);
expect(ctrl.currentSlide).toBe(ctrl.slides[1]);
ctrl.removeSlide(ctrl.slides[0]);
expect(ctrl.slides.length).toBe(1);
expect(ctrl.currentSlide).toBe(ctrl.slides[0]);
});
});
expect(ctrl).toBeDefined();
ctrl.text = 'foo';
$rootScope.$digest();
expect(elm.html()).toBe('<div class="ng-binding">foo</div>');
}));
});
it('should expose a custom model in the carousel slide', function() {
var scope = $rootScope.$new();
scope.slides = [
{active:false,content:'one'},
{active:false,content:'two'},
{active:false,content:'three'}
];
var elm = $compile(
'<div uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
'<div uib-slide ng-repeat="slide in slides" index="$index" actual="slide">' +
'{{slide.content}}' +
'</div>' +
'</div>'
)(scope);
$rootScope.$digest();
var ctrl = elm.controller('uibCarousel');
expect(angular.equals(ctrl.slides.map(function(slide) {
return slide.slide.actual;
}), scope.slides)).toBe(true);
});
});
+124 -86
View File
@@ -1,95 +1,133 @@
angular.module('ui.bootstrap.collapse',['ui.bootstrap.transition'])
angular.module('ui.bootstrap.collapse', [])
// The collapsible directive indicates a block of html that will expand and collapse
.directive('collapse', ['$transition', function($transition) {
// CSS transitions don't work with height: auto, so we have to manually change the height to a
// specific value and then once the animation completes, we can reset the height to auto.
// Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class
// "collapse") then you trigger a change to height 0 in between.
// The fix is to remove the "collapse" CSS class while changing the height back to auto - phew!
var fixUpHeight = function(scope, element, height) {
// We remove the collapse CSS class to prevent a transition when we change to height: auto
element.removeClass('collapse');
element.css({ height: height });
// It appears that reading offsetWidth makes the browser realise that we have changed the
// height already :-/
var x = element[0].offsetWidth;
element.addClass('collapse');
};
.directive('uibCollapse', ['$animate', '$q', '$parse', '$injector', function($animate, $q, $parse, $injector) {
var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;
return {
link: function(scope, element, attrs) {
var expandingExpr = $parse(attrs.expanding),
expandedExpr = $parse(attrs.expanded),
collapsingExpr = $parse(attrs.collapsing),
collapsedExpr = $parse(attrs.collapsed),
horizontal = false,
css = {},
cssTo = {};
return {
link: function(scope, element, attrs) {
init();
var isCollapsed;
var initialAnimSkip = true;
scope.$watch(function (){ return element[0].scrollHeight; }, function (value) {
//The listener is called when scollHeight changes
//It actually does on 2 scenarios:
// 1. Parent is set to display none
// 2. angular bindings inside are resolved
//When we have a change of scrollHeight we are setting again the correct height if the group is opened
if (element[0].scrollHeight !== 0) {
if (!isCollapsed) {
if (initialAnimSkip) {
fixUpHeight(scope, element, element[0].scrollHeight + 'px');
} else {
fixUpHeight(scope, element, 'auto');
}
function init() {
horizontal = !!('horizontal' in attrs);
if (horizontal) {
css = {
width: ''
};
cssTo = {width: '0'};
} else {
css = {
height: ''
};
cssTo = {height: '0'};
}
if (!scope.$eval(attrs.uibCollapse)) {
element.addClass('in')
.addClass('collapse')
.attr('aria-expanded', true)
.attr('aria-hidden', false)
.css(css);
}
}
});
scope.$watch(attrs.collapse, function(value) {
if (value) {
collapse();
} else {
expand();
}
});
var currentTransition;
var doTransition = function(change) {
if ( currentTransition ) {
currentTransition.cancel();
}
currentTransition = $transition(element,change);
currentTransition.then(
function() { currentTransition = undefined; },
function() { currentTransition = undefined; }
);
return currentTransition;
};
var expand = function() {
if (initialAnimSkip) {
initialAnimSkip = false;
if ( !isCollapsed ) {
fixUpHeight(scope, element, 'auto');
function getScrollFromElement(element) {
if (horizontal) {
return {width: element.scrollWidth + 'px'};
}
} else {
doTransition({ height : element[0].scrollHeight + 'px' })
.then(function() {
// This check ensures that we don't accidentally update the height if the user has closed
// the group while the animation was still running
if ( !isCollapsed ) {
fixUpHeight(scope, element, 'auto');
}
});
return {height: element.scrollHeight + 'px'};
}
isCollapsed = false;
};
var collapse = function() {
isCollapsed = true;
if (initialAnimSkip) {
initialAnimSkip = false;
fixUpHeight(scope, element, 0);
} else {
fixUpHeight(scope, element, element[0].scrollHeight + 'px');
doTransition({'height':'0'});
function expand() {
if (element.hasClass('collapse') && element.hasClass('in')) {
return;
}
$q.resolve(expandingExpr(scope))
.then(function() {
element.removeClass('collapse')
.addClass('collapsing')
.attr('aria-expanded', true)
.attr('aria-hidden', false);
if ($animateCss) {
$animateCss(element, {
addClass: 'in',
easing: 'ease',
css: {
overflow: 'hidden'
},
to: getScrollFromElement(element[0])
}).start()['finally'](expandDone);
} else {
$animate.addClass(element, 'in', {
css: {
overflow: 'hidden'
},
to: getScrollFromElement(element[0])
}).then(expandDone);
}
}, angular.noop);
}
};
}
};
}]);
function expandDone() {
element.removeClass('collapsing')
.addClass('collapse')
.css(css);
expandedExpr(scope);
}
function collapse() {
if (!element.hasClass('collapse') && !element.hasClass('in')) {
return collapseDone();
}
$q.resolve(collapsingExpr(scope))
.then(function() {
element
// IMPORTANT: The width must be set before adding "collapsing" class.
// Otherwise, the browser attempts to animate from width 0 (in
// collapsing class) to the given width here.
.css(getScrollFromElement(element[0]))
// initially all panel collapse have the collapse class, this removal
// prevents the animation from jumping to collapsed state
.removeClass('collapse')
.addClass('collapsing')
.attr('aria-expanded', false)
.attr('aria-hidden', true);
if ($animateCss) {
$animateCss(element, {
removeClass: 'in',
to: cssTo
}).start()['finally'](collapseDone);
} else {
$animate.removeClass(element, 'in', {
to: cssTo
}).then(collapseDone);
}
}, angular.noop);
}
function collapseDone() {
element.css(cssTo); // Required so that collapse works when animation is disabled
element.removeClass('collapsing')
.addClass('collapse');
collapsedExpr(scope);
}
scope.$watch(attrs.uibCollapse, function(shouldCollapse) {
if (shouldCollapse) {
collapse();
} else {
expand();
}
});
}
};
}]);
+37 -4
View File
@@ -1,7 +1,40 @@
<style>
.horizontal-collapse {
height: 70px;
}
.navbar-collapse.in {
overflow-y: hidden;
}
</style>
<div ng-controller="CollapseDemoCtrl">
<button class="btn" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button>
<p>Resize window to less than 768 pixels to display mobile menu toggle button.</p>
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" ng-click="isNavCollapsed = !isNavCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">A menu</a>
</div>
<div class="collapse navbar-collapse" uib-collapse="isNavCollapsed">
<ul class="nav navbar-nav">
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
</ul>
</div>
</nav>
<hr>
<div collapse="isCollapsed">
<div class="well well-large">Some content</div>
<button type="button" class="btn btn-default" ng-click="isCollapsed = !isCollapsed">Toggle collapse Vertically</button>
<hr>
<div uib-collapse="isCollapsed">
<div class="well well-lg">Some content</div>
</div>
</div>
<button type="button" class="btn btn-default" ng-click="isCollapsedHorizontal = !isCollapsedHorizontal">Toggle collapse Horizontally</button>
<hr>
<div class="horizontal-collapse" uib-collapse="isCollapsedHorizontal" horizontal>
<div class="well well-lg">Some content</div>
</div>
</div>
+4 -2
View File
@@ -1,3 +1,5 @@
function CollapseDemoCtrl($scope) {
angular.module('ui.bootstrap.demo').controller('CollapseDemoCtrl', function ($scope) {
$scope.isNavCollapsed = true;
$scope.isCollapsed = false;
}
$scope.isCollapsedHorizontal = false;
});
+37 -2
View File
@@ -1,2 +1,37 @@
AngularJS version of twitter's collapse plugin.
Provides a simple way to hide and show an element with a css transition
**uib-collapse** provides a simple way to hide and show an element with a css transition
### uib-collapse settings
* `collapsed()`
<small class="badge">$</small> -
An optional expression called after the element finished collapsing.
* `collapsing()`
<small class="badge">$</small> -
An optional expression called before the element begins collapsing.
If the expression returns a promise, animation won't start until the promise resolves.
If the returned promise is rejected, collapsing will be cancelled.
* `expanded()`
<small class="badge">$</small> -
An optional expression called after the element finished expanding.
* `expanding()`
<small class="badge">$</small> -
An optional expression called before the element begins expanding.
If the expression returns a promise, animation won't start until the promise resolves.
If the returned promise is rejected, expanding will be cancelled.
* `uib-collapse`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `false`)_ -
Whether the element should be collapsed or not.
* `horizontal`
<small class="badge">$</small> -
An optional attribute that permit to collapse horizontally.
### Known Issues
When using the `horizontal` attribute with this directive, CSS can reflow as the collapse element goes from `0px` to its desired end width, which can result in height changes. This can cause animations to not appear to run. The best way around this is to set a fixed height via CSS on the horizontal collapse element so that this situation does not occur, and so the animation can run as expected.
+7
View File
@@ -0,0 +1,7 @@
require('./collapse');
var MODULE_NAME = 'ui.bootstrap.module.collapse';
angular.module(MODULE_NAME, ['ui.bootstrap.collapse']);
module.exports = MODULE_NAME;
+211 -29
View File
@@ -1,19 +1,24 @@
describe('collapse directive', function () {
var scope, $compile, $timeout, $transition;
describe('collapse directive', function() {
var element, compileFn, scope, $compile, $animate, $q;
beforeEach(module('ui.bootstrap.collapse'));
beforeEach(inject(function(_$rootScope_, _$compile_, _$timeout_, _$transition_) {
beforeEach(module('ngAnimateMock'));
beforeEach(inject(function(_$rootScope_, _$compile_, _$animate_, _$q_) {
scope = _$rootScope_;
$compile = _$compile_;
$timeout = _$timeout_;
$transition = _$transition_;
$animate = _$animate_;
$q = _$q_;
}));
var element;
beforeEach(function() {
element = $compile('<div collapse="isCollapsed">Some Content</div>')(scope);
element = angular.element(
'<div uib-collapse="isCollapsed" '
+ 'expanding="expanding()" '
+ 'expanded="expanded()" '
+ 'collapsing="collapsing()" '
+ 'collapsed="collapsed()">'
+ 'Some Content</div>');
compileFn = $compile(element);
angular.element(document.body).append(element);
});
@@ -21,43 +26,146 @@ describe('collapse directive', function () {
element.remove();
});
it('should be hidden on initialization if isCollapsed = true without transition', function() {
function initCallbacks() {
scope.collapsing = jasmine.createSpy('scope.collapsing');
scope.collapsed = jasmine.createSpy('scope.collapsed');
scope.expanding = jasmine.createSpy('scope.expanding');
scope.expanded = jasmine.createSpy('scope.expanded');
}
function assertCallbacks(expected) {
['collapsing', 'collapsed', 'expanding', 'expanded'].forEach(function(cbName) {
if (expected[cbName]) {
expect(scope[cbName]).toHaveBeenCalled();
} else {
expect(scope[cbName]).not.toHaveBeenCalled();
}
});
}
it('should be hidden on initialization if isCollapsed = true', function() {
initCallbacks();
scope.isCollapsed = true;
compileFn(scope);
scope.$digest();
//No animation timeout here
expect(element.height()).toBe(0);
assertCallbacks({ collapsed: true });
});
it('should collapse if isCollapsed = true with animation on subsequent use', function() {
scope.isCollapsed = false;
it('should not trigger any animation on initialization if isCollapsed = true', function() {
var wrapperFn = function() {
$animate.flush();
};
scope.isCollapsed = true;
compileFn(scope);
scope.$digest();
expect(wrapperFn).toThrowError(/No pending animations ready to be closed or flushed/);
});
it('should collapse if isCollapsed = true on subsequent use', function() {
scope.isCollapsed = false;
compileFn(scope);
scope.$digest();
initCallbacks();
scope.isCollapsed = true;
scope.$digest();
$timeout.flush();
$animate.flush();
expect(element.height()).toBe(0);
assertCallbacks({ collapsing: true, collapsed: true });
});
it('should be shown on initialization if isCollapsed = false without transition', function() {
it('should show after toggled from collapsed', function() {
initCallbacks();
scope.isCollapsed = true;
compileFn(scope);
scope.$digest();
expect(element.height()).toBe(0);
assertCallbacks({ collapsed: true });
scope.collapsed.calls.reset();
scope.isCollapsed = false;
scope.$digest();
//No animation timeout here
$animate.flush();
expect(element.height()).not.toBe(0);
assertCallbacks({ expanding: true, expanded: true });
});
it('should expand if isCollapsed = false with animation on subsequent use', function() {
it('should not trigger any animation on initialization if isCollapsed = false', function() {
var wrapperFn = function() {
$animate.flush();
};
scope.isCollapsed = false;
compileFn(scope);
scope.$digest();
expect(wrapperFn).toThrowError(/No pending animations ready to be closed or flushed/);
});
it('should expand if isCollapsed = false on subsequent use', function() {
scope.isCollapsed = false;
compileFn(scope);
scope.$digest();
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
initCallbacks();
scope.isCollapsed = false;
scope.$digest();
$timeout.flush();
$animate.flush();
expect(element.height()).not.toBe(0);
assertCallbacks({ expanding: true, expanded: true });
});
it('should collapse if isCollapsed = true on subsequent uses', function() {
scope.isCollapsed = false;
compileFn(scope);
scope.$digest();
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
scope.isCollapsed = false;
scope.$digest();
$animate.flush();
initCallbacks();
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
expect(element.height()).toBe(0);
assertCallbacks({ collapsing: true, collapsed: true });
});
it('should change aria-expanded attribute', function() {
scope.isCollapsed = false;
compileFn(scope);
scope.$digest();
expect(element.attr('aria-expanded')).toBe('true');
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
expect(element.attr('aria-expanded')).toBe('false');
});
it('should change aria-hidden attribute', function() {
scope.isCollapsed = false;
compileFn(scope);
scope.$digest();
expect(element.attr('aria-hidden')).toBe('false');
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
expect(element.attr('aria-hidden')).toBe('true');
});
describe('dynamic content', function() {
var element;
beforeEach(function() {
element = angular.element('<div collapse="isCollapsed"><p>Initial content</p><div ng-show="exp">Additional content</div></div>');
element = angular.element('<div uib-collapse="isCollapsed"><p>Initial content</p><div ng-show="exp">Additional content</div></div>');
$compile(element)(scope);
angular.element(document.body).append(element);
});
@@ -85,22 +193,96 @@ describe('collapse directive', function () {
scope.$digest();
expect(element.height()).toBeLessThan(collapseHeight);
});
});
describe('expanding callback returning a promise', function() {
var defer, collapsedHeight;
beforeEach(function() {
defer = $q.defer();
it('should shrink accordingly when content size inside collapse decreases on subsequent use', function() {
scope.isCollapsed = false;
scope.exp = false;
scope.$digest();
scope.isCollapsed = true;
scope.expanding = function() {
return defer.promise;
};
compileFn(scope);
scope.$digest();
collapsedHeight = element.height();
// set flag to expand ...
scope.isCollapsed = false;
scope.$digest();
$timeout.flush();
scope.exp = true;
// ... shouldn't expand yet ...
expect(element.attr('aria-expanded')).not.toBe('true');
expect(element.height()).toBe(collapsedHeight);
});
it('should wait for it to resolve before animating', function() {
defer.resolve();
// should now expand
scope.$digest();
var collapseHeight = element.height();
scope.exp = false;
$animate.flush();
expect(element.attr('aria-expanded')).toBe('true');
expect(element.height()).toBeGreaterThan(collapsedHeight);
});
it('should not animate if it rejects', function() {
defer.reject();
// should NOT expand
scope.$digest();
expect(element.height()).toBeLessThan(collapseHeight);
expect(element.attr('aria-expanded')).not.toBe('true');
expect(element.height()).toBe(collapsedHeight);
});
});
});
describe('collapsing callback returning a promise', function() {
var defer, expandedHeight;
beforeEach(function() {
defer = $q.defer();
scope.isCollapsed = false;
scope.collapsing = function() {
return defer.promise;
};
compileFn(scope);
scope.$digest();
expandedHeight = element.height();
// set flag to collapse ...
scope.isCollapsed = true;
scope.$digest();
// ... but it shouldn't collapse yet ...
expect(element.attr('aria-expanded')).not.toBe('false');
expect(element.height()).toBe(expandedHeight);
});
it('should wait for it to resolve before animating', function() {
defer.resolve();
// should now collapse
scope.$digest();
$animate.flush();
expect(element.attr('aria-expanded')).toBe('false');
expect(element.height()).toBeLessThan(expandedHeight);
});
it('should not animate if it rejects', function() {
defer.reject();
// should NOT collapse
scope.$digest();
expect(element.attr('aria-expanded')).not.toBe('false');
expect(element.height()).toBe(expandedHeight);
});
});
});
@@ -0,0 +1,255 @@
describe('collapse directive', function() {
var elementH, compileFnH, scope, $compile, $animate, $q;
beforeEach(module('ui.bootstrap.collapse'));
beforeEach(module('ngAnimateMock'));
beforeEach(inject(function(_$rootScope_, _$compile_, _$animate_, _$q_) {
scope = _$rootScope_;
$compile = _$compile_;
$animate = _$animate_;
$q = _$q_;
}));
beforeEach(function() {
elementH = angular.element(
'<div uib-collapse="isCollapsed" '
+ 'expanding="expanding()" '
+ 'expanded="expanded()" '
+ 'collapsing="collapsing()" '
+ 'collapsed="collapsed()" '
+ 'horizontal>'
+ 'Some Content</div>');
compileFnH = $compile(elementH);
angular.element(document.body).append(elementH);
});
afterEach(function() {
elementH.remove();
});
function initCallbacks() {
scope.collapsing = jasmine.createSpy('scope.collapsing');
scope.collapsed = jasmine.createSpy('scope.collapsed');
scope.expanding = jasmine.createSpy('scope.expanding');
scope.expanded = jasmine.createSpy('scope.expanded');
}
function assertCallbacks(expected) {
['collapsing', 'collapsed', 'expanding', 'expanded'].forEach(function(cbName) {
if (expected[cbName]) {
expect(scope[cbName]).toHaveBeenCalled();
} else {
expect(scope[cbName]).not.toHaveBeenCalled();
}
});
}
it('should be hidden on initialization if isCollapsed = true', function() {
initCallbacks();
scope.isCollapsed = true;
compileFnH(scope);
scope.$digest();
expect(elementH.width()).toBe(0);
assertCallbacks({ collapsed: true });
});
it('should not trigger any animation on initialization if isCollapsed = true', function() {
var wrapperFn = function() {
$animate.flush();
};
scope.isCollapsed = true;
compileFnH(scope);
scope.$digest();
expect(wrapperFn).toThrowError(/No pending animations ready to be closed or flushed/);
});
it('should collapse if isCollapsed = true on subsequent use', function() {
scope.isCollapsed = false;
compileFnH(scope);
scope.$digest();
initCallbacks();
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
expect(elementH.width()).toBe(0);
assertCallbacks({ collapsing: true, collapsed: true });
});
it('should show after toggled from collapsed', function() {
initCallbacks();
scope.isCollapsed = true;
compileFnH(scope);
scope.$digest();
expect(elementH.width()).toBe(0);
assertCallbacks({ collapsed: true });
scope.collapsed.calls.reset();
scope.isCollapsed = false;
scope.$digest();
$animate.flush();
expect(elementH.width()).not.toBe(0);
assertCallbacks({ expanding: true, expanded: true });
});
it('should not trigger any animation on initialization if isCollapsed = false', function() {
var wrapperFn = function() {
$animate.flush();
};
scope.isCollapsed = false;
compileFnH(scope);
scope.$digest();
expect(wrapperFn).toThrowError(/No pending animations ready to be closed or flushed/);
});
it('should expand if isCollapsed = false on subsequent use', function() {
scope.isCollapsed = false;
compileFnH(scope);
scope.$digest();
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
initCallbacks();
scope.isCollapsed = false;
scope.$digest();
$animate.flush();
expect(elementH.width()).not.toBe(0);
assertCallbacks({ expanding: true, expanded: true });
});
it('should collapse if isCollapsed = true on subsequent uses', function() {
scope.isCollapsed = false;
compileFnH(scope);
scope.$digest();
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
scope.isCollapsed = false;
scope.$digest();
$animate.flush();
initCallbacks();
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
expect(elementH.width()).toBe(0);
assertCallbacks({ collapsing: true, collapsed: true });
});
it('should change aria-expanded attribute', function() {
scope.isCollapsed = false;
compileFnH(scope);
scope.$digest();
expect(elementH.attr('aria-expanded')).toBe('true');
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
expect(elementH.attr('aria-expanded')).toBe('false');
});
it('should change aria-hidden attribute', function() {
scope.isCollapsed = false;
compileFnH(scope);
scope.$digest();
expect(elementH.attr('aria-hidden')).toBe('false');
scope.isCollapsed = true;
scope.$digest();
$animate.flush();
expect(elementH.attr('aria-hidden')).toBe('true');
});
describe('expanding callback returning a promise', function() {
var defer, collapsedWidth;
beforeEach(function() {
defer = $q.defer();
scope.isCollapsed = true;
scope.expanding = function() {
return defer.promise;
};
compileFnH(scope);
scope.$digest();
collapsedWidth = elementH.width();
// set flag to expand ...
scope.isCollapsed = false;
scope.$digest();
// ... shouldn't expand yet ...
expect(elementH.attr('aria-expanded')).not.toBe('true');
expect(elementH.width()).toBe(collapsedWidth);
});
it('should wait for it to resolve before animating', function() {
defer.resolve();
// should now expand
scope.$digest();
$animate.flush();
expect(elementH.attr('aria-expanded')).toBe('true');
expect(elementH.width()).toBeGreaterThan(collapsedWidth);
});
it('should not animate if it rejects', function() {
defer.reject();
// should NOT expand
scope.$digest();
expect(elementH.attr('aria-expanded')).not.toBe('true');
expect(elementH.width()).toBe(collapsedWidth);
});
});
describe('collapsing callback returning a promise', function() {
var defer, expandedWidth;
beforeEach(function() {
defer = $q.defer();
scope.isCollapsed = false;
scope.collapsing = function() {
return defer.promise;
};
compileFnH(scope);
scope.$digest();
expandedWidth = elementH.width();
// set flag to collapse ...
scope.isCollapsed = true;
scope.$digest();
// ... but it shouldn't collapse yet ...
expect(elementH.attr('aria-expanded')).not.toBe('false');
expect(elementH.width()).toBe(expandedWidth);
});
it('should wait for it to resolve before animating', function() {
defer.resolve();
// should now collapse
scope.$digest();
$animate.flush();
expect(elementH.attr('aria-expanded')).toBe('false');
expect(elementH.width()).toBeLessThan(expandedWidth);
});
it('should not animate if it rejects', function() {
defer.reject();
// should NOT collapse
scope.$digest();
expect(elementH.attr('aria-expanded')).not.toBe('false');
expect(elementH.width()).toBe(expandedWidth);
});
});
});
+539
View File
@@ -0,0 +1,539 @@
angular.module('ui.bootstrap.dateparser', [])
.service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', 'filterFilter', function($log, $locale, dateFilter, orderByFilter, filterFilter) {
// Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js
var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
var localeId;
var formatCodeToRegex;
this.init = function() {
localeId = $locale.id;
this.parsers = {};
this.formatters = {};
formatCodeToRegex = [
{
key: 'yyyy',
regex: '\\d{4}',
apply: function(value) { this.year = +value; },
formatter: function(date) {
var _date = new Date();
_date.setFullYear(Math.abs(date.getFullYear()));
return dateFilter(_date, 'yyyy');
}
},
{
key: 'yy',
regex: '\\d{2}',
apply: function(value) { value = +value; this.year = value < 69 ? value + 2000 : value + 1900; },
formatter: function(date) {
var _date = new Date();
_date.setFullYear(Math.abs(date.getFullYear()));
return dateFilter(_date, 'yy');
}
},
{
key: 'y',
regex: '\\d{1,4}',
apply: function(value) { this.year = +value; },
formatter: function(date) {
var _date = new Date();
_date.setFullYear(Math.abs(date.getFullYear()));
return dateFilter(_date, 'y');
}
},
{
key: 'M!',
regex: '0?[1-9]|1[0-2]',
apply: function(value) { this.month = value - 1; },
formatter: function(date) {
var value = date.getMonth();
if (/^[0-9]$/.test(value)) {
return dateFilter(date, 'MM');
}
return dateFilter(date, 'M');
}
},
{
key: 'MMMM',
regex: $locale.DATETIME_FORMATS.MONTH.join('|'),
apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); },
formatter: function(date) { return dateFilter(date, 'MMMM'); }
},
{
key: 'MMM',
regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); },
formatter: function(date) { return dateFilter(date, 'MMM'); }
},
{
key: 'MM',
regex: '0[1-9]|1[0-2]',
apply: function(value) { this.month = value - 1; },
formatter: function(date) { return dateFilter(date, 'MM'); }
},
{
key: 'M',
regex: '[1-9]|1[0-2]',
apply: function(value) { this.month = value - 1; },
formatter: function(date) { return dateFilter(date, 'M'); }
},
{
key: 'd!',
regex: '[0-2]?[0-9]{1}|3[0-1]{1}',
apply: function(value) { this.date = +value; },
formatter: function(date) {
var value = date.getDate();
if (/^[1-9]$/.test(value)) {
return dateFilter(date, 'dd');
}
return dateFilter(date, 'd');
}
},
{
key: 'dd',
regex: '[0-2][0-9]{1}|3[0-1]{1}',
apply: function(value) { this.date = +value; },
formatter: function(date) { return dateFilter(date, 'dd'); }
},
{
key: 'd',
regex: '[1-2]?[0-9]{1}|3[0-1]{1}',
apply: function(value) { this.date = +value; },
formatter: function(date) { return dateFilter(date, 'd'); }
},
{
key: 'EEEE',
regex: $locale.DATETIME_FORMATS.DAY.join('|'),
formatter: function(date) { return dateFilter(date, 'EEEE'); }
},
{
key: 'EEE',
regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|'),
formatter: function(date) { return dateFilter(date, 'EEE'); }
},
{
key: 'HH',
regex: '(?:0|1)[0-9]|2[0-3]',
apply: function(value) { this.hours = +value; },
formatter: function(date) { return dateFilter(date, 'HH'); }
},
{
key: 'hh',
regex: '0[0-9]|1[0-2]',
apply: function(value) { this.hours = +value; },
formatter: function(date) { return dateFilter(date, 'hh'); }
},
{
key: 'H',
regex: '1?[0-9]|2[0-3]',
apply: function(value) { this.hours = +value; },
formatter: function(date) { return dateFilter(date, 'H'); }
},
{
key: 'h',
regex: '[0-9]|1[0-2]',
apply: function(value) { this.hours = +value; },
formatter: function(date) { return dateFilter(date, 'h'); }
},
{
key: 'mm',
regex: '[0-5][0-9]',
apply: function(value) { this.minutes = +value; },
formatter: function(date) { return dateFilter(date, 'mm'); }
},
{
key: 'm',
regex: '[0-9]|[1-5][0-9]',
apply: function(value) { this.minutes = +value; },
formatter: function(date) { return dateFilter(date, 'm'); }
},
{
key: 'sss',
regex: '[0-9][0-9][0-9]',
apply: function(value) { this.milliseconds = +value; },
formatter: function(date) { return dateFilter(date, 'sss'); }
},
{
key: 'ss',
regex: '[0-5][0-9]',
apply: function(value) { this.seconds = +value; },
formatter: function(date) { return dateFilter(date, 'ss'); }
},
{
key: 's',
regex: '[0-9]|[1-5][0-9]',
apply: function(value) { this.seconds = +value; },
formatter: function(date) { return dateFilter(date, 's'); }
},
{
key: 'a',
regex: $locale.DATETIME_FORMATS.AMPMS.join('|'),
apply: function(value) {
if (this.hours === 12) {
this.hours = 0;
}
if (value === 'PM') {
this.hours += 12;
}
},
formatter: function(date) { return dateFilter(date, 'a'); }
},
{
key: 'Z',
regex: '[+-]\\d{4}',
apply: function(value) {
var matches = value.match(/([+-])(\d{2})(\d{2})/),
sign = matches[1],
hours = matches[2],
minutes = matches[3];
this.hours += toInt(sign + hours);
this.minutes += toInt(sign + minutes);
},
formatter: function(date) {
return dateFilter(date, 'Z');
}
},
{
key: 'ww',
regex: '[0-4][0-9]|5[0-3]',
formatter: function(date) { return dateFilter(date, 'ww'); }
},
{
key: 'w',
regex: '[0-9]|[1-4][0-9]|5[0-3]',
formatter: function(date) { return dateFilter(date, 'w'); }
},
{
key: 'GGGG',
regex: $locale.DATETIME_FORMATS.ERANAMES.join('|').replace(/\s/g, '\\s'),
formatter: function(date) { return dateFilter(date, 'GGGG'); }
},
{
key: 'GGG',
regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
formatter: function(date) { return dateFilter(date, 'GGG'); }
},
{
key: 'GG',
regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
formatter: function(date) { return dateFilter(date, 'GG'); }
},
{
key: 'G',
regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
formatter: function(date) { return dateFilter(date, 'G'); }
}
];
if (angular.version.major >= 1 && angular.version.minor > 4) {
formatCodeToRegex.push({
key: 'LLLL',
regex: $locale.DATETIME_FORMATS.STANDALONEMONTH.join('|'),
apply: function(value) { this.month = $locale.DATETIME_FORMATS.STANDALONEMONTH.indexOf(value); },
formatter: function(date) { return dateFilter(date, 'LLLL'); }
});
}
};
this.init();
function getFormatCodeToRegex(key) {
return filterFilter(formatCodeToRegex, {key: key}, true)[0];
}
this.getParser = function (key) {
var f = getFormatCodeToRegex(key);
return f && f.apply || null;
};
this.overrideParser = function (key, parser) {
var f = getFormatCodeToRegex(key);
if (f && angular.isFunction(parser)) {
this.parsers = {};
f.apply = parser;
}
}.bind(this);
function createParser(format) {
var map = [], regex = format.split('');
// check for literal values
var quoteIndex = format.indexOf('\'');
if (quoteIndex > -1) {
var inLiteral = false;
format = format.split('');
for (var i = quoteIndex; i < format.length; i++) {
if (inLiteral) {
if (format[i] === '\'') {
if (i + 1 < format.length && format[i+1] === '\'') { // escaped single quote
format[i+1] = '$';
regex[i+1] = '';
} else { // end of literal
regex[i] = '';
inLiteral = false;
}
}
format[i] = '$';
} else {
if (format[i] === '\'') { // start of literal
format[i] = '$';
regex[i] = '';
inLiteral = true;
}
}
}
format = format.join('');
}
angular.forEach(formatCodeToRegex, function(data) {
var index = format.indexOf(data.key);
if (index > -1) {
format = format.split('');
regex[index] = '(' + data.regex + ')';
format[index] = '$'; // Custom symbol to define consumed part of format
for (var i = index + 1, n = index + data.key.length; i < n; i++) {
regex[i] = '';
format[i] = '$';
}
format = format.join('');
map.push({
index: index,
key: data.key,
apply: data.apply,
matcher: data.regex
});
}
});
return {
regex: new RegExp('^' + regex.join('') + '$'),
map: orderByFilter(map, 'index')
};
}
function createFormatter(format) {
var formatters = [];
var i = 0;
var formatter, literalIdx;
while (i < format.length) {
if (angular.isNumber(literalIdx)) {
if (format.charAt(i) === '\'') {
if (i + 1 >= format.length || format.charAt(i + 1) !== '\'') {
formatters.push(constructLiteralFormatter(format, literalIdx, i));
literalIdx = null;
}
} else if (i === format.length) {
while (literalIdx < format.length) {
formatter = constructFormatterFromIdx(format, literalIdx);
formatters.push(formatter);
literalIdx = formatter.endIdx;
}
}
i++;
continue;
}
if (format.charAt(i) === '\'') {
literalIdx = i;
i++;
continue;
}
formatter = constructFormatterFromIdx(format, i);
formatters.push(formatter.parser);
i = formatter.endIdx;
}
return formatters;
}
function constructLiteralFormatter(format, literalIdx, endIdx) {
return function() {
return format.substr(literalIdx + 1, endIdx - literalIdx - 1);
};
}
function constructFormatterFromIdx(format, i) {
var currentPosStr = format.substr(i);
for (var j = 0; j < formatCodeToRegex.length; j++) {
if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) {
var data = formatCodeToRegex[j];
return {
endIdx: i + data.key.length,
parser: data.formatter
};
}
}
return {
endIdx: i + 1,
parser: function() {
return currentPosStr.charAt(0);
}
};
}
this.filter = function(date, format) {
if (!angular.isDate(date) || isNaN(date) || !format) {
return '';
}
format = $locale.DATETIME_FORMATS[format] || format;
if ($locale.id !== localeId) {
this.init();
}
if (!this.formatters[format]) {
this.formatters[format] = createFormatter(format);
}
var formatters = this.formatters[format];
return formatters.reduce(function(str, formatter) {
return str + formatter(date);
}, '');
};
this.parse = function(input, format, baseDate) {
if (!angular.isString(input) || !format) {
return input;
}
format = $locale.DATETIME_FORMATS[format] || format;
format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&');
if ($locale.id !== localeId) {
this.init();
}
if (!this.parsers[format]) {
this.parsers[format] = createParser(format, 'apply');
}
var parser = this.parsers[format],
regex = parser.regex,
map = parser.map,
results = input.match(regex),
tzOffset = false;
if (results && results.length) {
var fields, dt;
if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {
fields = {
year: baseDate.getFullYear(),
month: baseDate.getMonth(),
date: baseDate.getDate(),
hours: baseDate.getHours(),
minutes: baseDate.getMinutes(),
seconds: baseDate.getSeconds(),
milliseconds: baseDate.getMilliseconds()
};
} else {
if (baseDate) {
$log.warn('dateparser:', 'baseDate is not a valid date');
}
fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
}
for (var i = 1, n = results.length; i < n; i++) {
var mapper = map[i - 1];
if (mapper.matcher === 'Z') {
tzOffset = true;
}
if (mapper.apply) {
mapper.apply.call(fields, results[i]);
}
}
var datesetter = tzOffset ? Date.prototype.setUTCFullYear :
Date.prototype.setFullYear;
var timesetter = tzOffset ? Date.prototype.setUTCHours :
Date.prototype.setHours;
if (isValid(fields.year, fields.month, fields.date)) {
if (angular.isDate(baseDate) && !isNaN(baseDate.getTime()) && !tzOffset) {
dt = new Date(baseDate);
datesetter.call(dt, fields.year, fields.month, fields.date);
timesetter.call(dt, fields.hours, fields.minutes,
fields.seconds, fields.milliseconds);
} else {
dt = new Date(0);
datesetter.call(dt, fields.year, fields.month, fields.date);
timesetter.call(dt, fields.hours || 0, fields.minutes || 0,
fields.seconds || 0, fields.milliseconds || 0);
}
}
return dt;
}
};
// Check if date is valid for specific month (and year for February).
// Month: 0 = Jan, 1 = Feb, etc
function isValid(year, month, date) {
if (date < 1) {
return false;
}
if (month === 1 && date > 28) {
return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0);
}
if (month === 3 || month === 5 || month === 8 || month === 10) {
return date < 31;
}
return true;
}
function toInt(str) {
return parseInt(str, 10);
}
this.toTimezone = toTimezone;
this.fromTimezone = fromTimezone;
this.timezoneToOffset = timezoneToOffset;
this.addDateMinutes = addDateMinutes;
this.convertTimezoneToLocal = convertTimezoneToLocal;
function toTimezone(date, timezone) {
return date && timezone ? convertTimezoneToLocal(date, timezone) : date;
}
function fromTimezone(date, timezone) {
return date && timezone ? convertTimezoneToLocal(date, timezone, true) : date;
}
//https://github.com/angular/angular.js/blob/622c42169699ec07fc6daaa19fe6d224e5d2f70e/src/Angular.js#L1207
function timezoneToOffset(timezone, fallback) {
timezone = timezone.replace(/:/g, '');
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
}
function addDateMinutes(date, minutes) {
date = new Date(date.getTime());
date.setMinutes(date.getMinutes() + minutes);
return date;
}
function convertTimezoneToLocal(date, timezone, reverse) {
reverse = reverse ? -1 : 1;
var dateTimezoneOffset = date.getTimezoneOffset();
var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
}
}]);
+147
View File
@@ -0,0 +1,147 @@
The `uibDateParser` is what the `uib-datepicker` uses internally to parse the dates. You can use it standalone by injecting the `uibDateParser` service where you need it.
The public API for the dateParser is a single method called `parse`.
Certain format codes support i18n. Check this [guide](https://docs.angularjs.org/guide/i18n) for more information.
### uibDateParser's parse function
##### parameters
* `input`
_(Type: `string`, Example: `2004/Sep/4`)_ -
The input date to parse.
* `format`
_(Type: `string`, Example: `yyyy/MMM/d`)_ -
The format we want to use. Check all the supported formats below.
* `baseDate`
_(Type: `Date`, Example: `new Date()`)_ -
If you want to parse a date but maintain the timezone, you can pass an existing date here.
##### return
* If the specified input matches the format, a new date with the input will be returned, otherwise, it will return undefined.
### uibDateParser's format codes
* `yyyy`
_(Example: `2015`)_ -
Parses a 4 digits year.
* `yy`
_(Example: `15`)_ -
Parses a 2 digits year.
* `y`
_(Example: `15`)_ -
Parses a year with 1, 2, 3, or 4 digits.
* `MMMM`
_(Example: `February`, i18n support)_ -
Parses the full name of a month.
* `MMM`
_(Example: `Feb`, i18n support)_ -
Parses the short name of a month.
* `MM`
_(Example: `12`, Leading 0)_ -
Parses a numeric month.
* `M`
_(Example: `3`)_ -
Parses a numeric month.
* `M!`
_(Example: `3` or `03`)_ -
Parses a numeric month, but allowing an optional leading zero
* `LLLL`
_(Example: `February`, i18n support)_ - Stand-alone month in year (January-December). Requires Angular version 1.5.1 or higher.
* `dd`
_(Example: `05`, Leading 0)_ -
Parses a numeric day.
* `d`
_(Example: `5`)_ -
Parses a numeric day.
* `d!`
_(Example: `3` or `03`)_ -
Parses a numeric day, but allowing an optional leading zero
* `EEEE`
_(Example: `Sunday`, i18n support)_ -
Parses the full name of a day.
* `EEE`
_(Example: `Mon`, i18n support)_ -
Parses the short name of a day.
* `HH`
_(Example: `14`, Leading 0)_ -
Parses a 24 hours time.
* `H`
_(Example: `3`)_ -
Parses a 24 hours time.
* `hh`
_(Example: `11`, Leading 0)_ -
Parses a 12 hours time.
* `h`
_(Example: `3`)_ -
Parses a 12 hours time.
* `mm`
_(Example: `09`, Leading 0)_ -
Parses the minutes.
* `m`
_(Example: `3`)_ -
Parses the minutes.
* `sss`
_(Example: `094`, Leading 0)_ -
Parses the milliseconds.
* `ss`
_(Example: `08`, Leading 0)_ -
Parses the seconds.
* `s`
_(Example: `22`)_ -
Parses the seconds.
* `a`
_(Example: `10AM`)_ -
Parses a 12 hours time with AM/PM.
* `Z`
_(Example: `-0800`)_ -
Parses the timezone offset in a signed 4 digit representation
* `ww`
_(Example: `03`, Leading 0)_ -
Parses the week number
* `w`
_(Example: `03`)_ -
Parses the week number
* `G`, `GG`, `GGG`
_(Example: `AD`)_ -
Parses the era (`AD` or `BC`)
* `GGGG`
_(Example: `Anno Domini`)_ -
Parses the long form of the era (`Anno Domini` or `Before Christ`)
\* The ones marked with `Leading 0`, needs a leading 0 for values less than 10. Exception being milliseconds which needs it for values under 100.
\** It also supports `fullDate|longDate|medium|mediumDate|mediumTime|short|shortDate|shortTime` as the format for parsing.
\*** It supports template literals as a string between the single quote `'` character, i.e. `'The Date is' MM/DD/YYYY`. If one wants the literal single quote character, one must use `''''`.
+11
View File
@@ -0,0 +1,11 @@
<div ng-controller="DateParserDemoCtrl">
<h4>Formatting codes playground</h4>
<p class="form-group">
<label>Define your format</label>
<input type="text" ng-model="format" class="form-control">
</p>
<p class="form-group">
<label>Result</label>
<input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="date" />
</p>
</div>
+4
View File
@@ -0,0 +1,4 @@
angular.module('ui.bootstrap.demo').controller('DateParserDemoCtrl', function ($scope, uibDateParser) {
$scope.format = 'yyyy/MM/dd';
$scope.date = new Date();
});
+7
View File
@@ -0,0 +1,7 @@
require('./dateparser');
var MODULE_NAME = 'ui.bootstrap.module.dateparser';
angular.module(MODULE_NAME, ['ui.bootstrap.dateparser']);
module.exports = MODULE_NAME;
+818
View File
@@ -0,0 +1,818 @@
describe('date parser', function() {
var dateParser, oldDate;
beforeEach(module('ui.bootstrap.dateparser'));
beforeEach(inject(function (uibDateParser) {
dateParser = uibDateParser;
oldDate = new Date(1, 2, 6);
oldDate.setFullYear(1);
}));
function expectFilter(date, format, display) {
expect(dateParser.filter(date, format)).toEqual(display);
}
function expectParse(input, format, date) {
expect(dateParser.parse(input, format)).toEqual(date);
}
function expectBaseParse(input, format, baseDate, date) {
expect(dateParser.parse(input, format, baseDate)).toEqual(date);
}
describe('filter', function() {
it('should work correctly for `dd`, `MM`, `yyyy`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'dd.MM.yyyy', '17.11.2013');
expectFilter(new Date(2013, 11, 31, 0), 'dd.MM.yyyy', '31.12.2013');
expectFilter(new Date(1991, 2, 8, 0), 'dd-MM-yyyy', '08-03-1991');
expectFilter(new Date(1980, 2, 5, 0), 'MM/dd/yyyy', '03/05/1980');
expectFilter(new Date(1983, 0, 10, 0), 'dd.MM/yyyy', '10.01/1983');
expectFilter(new Date(1980, 10, 9, 0), 'MM-dd-yyyy', '11-09-1980');
expectFilter(new Date(2011, 1, 5, 0), 'yyyy/MM/dd', '2011/02/05');
expectFilter(oldDate, 'yyyy/MM/dd', '0001/03/06');
});
it('should work correctly for `yy`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'dd.MM.yy', '17.11.13');
expectFilter(new Date(2011, 4, 2, 0), 'dd-MM-yy', '02-05-11');
expectFilter(new Date(2080, 1, 5, 0), 'MM/dd/yy', '02/05/80');
expectFilter(new Date(2055, 1, 5, 0), 'yy/MM/dd', '55/02/05');
expectFilter(new Date(2013, 7, 11, 0), 'dd-MM-yy', '11-08-13');
});
it('should work correctly for `y`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'dd.MM.y', '17.11.2013');
expectFilter(new Date(2013, 11, 31, 0), 'dd.MM.y', '31.12.2013');
expectFilter(new Date(1991, 2, 8, 0), 'dd-MM-y', '08-03-1991');
expectFilter(new Date(1980, 2, 5, 0), 'MM/dd/y', '03/05/1980');
expectFilter(new Date(1983, 0, 10, 0), 'dd.MM/y', '10.01/1983');
expectFilter(new Date(1980, 10, 9, 0), 'MM-dd-y', '11-09-1980');
expectFilter(new Date(2011, 1, 5, 0), 'y/MM/dd', '2011/02/05');
});
it('should work correctly for `MMMM`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'dd.MMMM.yy', '17.November.13');
expectFilter(new Date(1980, 2, 5, 0), 'dd-MMMM-yyyy', '05-March-1980');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/dd/yyyy', 'February/05/1980');
expectFilter(new Date(1949, 11, 20, 0), 'yyyy/MMMM/dd', '1949/December/20');
expectFilter(oldDate, 'yyyy/MMMM/dd', '0001/March/06');
});
it('should work correctly for `MMM`', function() {
expectFilter(new Date(2010, 8, 30, 0), 'dd.MMM.yy', '30.Sep.10');
expectFilter(new Date(2011, 4, 2, 0), 'dd-MMM-yy', '02-May-11');
expectFilter(new Date(1980, 1, 5, 0), 'MMM/dd/yyyy', 'Feb/05/1980');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/MMM/dd', '1955/Feb/05');
expectFilter(oldDate, 'yyyy/MMM/dd', '0001/Mar/06');
});
it('should work correctly for `M`', function() {
expectFilter(new Date(2013, 7, 11, 0), 'M/dd/yyyy', '8/11/2013');
expectFilter(new Date(2005, 10, 7, 0), 'dd.M.yy', '07.11.05');
expectFilter(new Date(2011, 4, 2, 0), 'dd-M-yy', '02-5-11');
expectFilter(new Date(1980, 1, 5, 0), 'M/dd/yyyy', '2/05/1980');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/M/dd', '1955/2/05');
expectFilter(new Date(2011, 4, 2, 0), 'dd-M-yy', '02-5-11');
});
it('should work correctly for `M!`', function() {
expectFilter(new Date(2013, 7, 11, 0), 'M!/dd/yyyy', '08/11/2013');
expectFilter(new Date(2005, 10, 7, 0), 'dd.M!.yy', '07.11.05');
expectFilter(new Date(2011, 4, 2, 0), 'dd-M!-yy', '02-05-11');
expectFilter(new Date(1980, 1, 5, 0), 'M!/dd/yyyy', '02/05/1980');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/M!/dd', '1955/02/05');
expectFilter(new Date(2011, 4, 2, 0), 'dd-M!-yy', '02-05-11');
expectFilter(oldDate, 'yyyy/M!/dd', '0001/03/06');
});
it('should work correctly for `LLLL`', function() {
expectFilter(new Date(2013, 7, 24, 0), 'LLLL/dd/yyyy', 'August/24/2013');
expectFilter(new Date(2004, 10, 7, 0), 'dd.LLLL.yy', '07.November.04');
expectFilter(new Date(2011, 4, 18, 0), 'dd-LLLL-yy', '18-May-11');
expectFilter(new Date(1980, 1, 5, 0), 'LLLL/dd/yyyy', 'February/05/1980');
expectFilter(new Date(1955, 2, 5, 0), 'yyyy/LLLL/dd', '1955/March/05');
expectFilter(new Date(2011, 5, 2, 0), 'dd-LLLL-yy', '02-June-11');
expectFilter(oldDate, 'yyyy/LLLL/dd', '0001/March/06');
});
it('should work correctly for `d`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'd.MMMM.yy', '17.November.13');
expectFilter(new Date(1991, 2, 8, 0), 'd-MMMM-yyyy', '8-March-1991');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy', 'February/5/1980');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/MMMM/d', '1955/February/5');
expectFilter(new Date(2013, 7, 11, 0), 'd-MM-yy', '11-08-13');
expectFilter(oldDate, 'yyyy/MM/d', '0001/03/6');
});
it('should work correctly for `d!`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'd!.MMMM.yy', '17.November.13');
expectFilter(new Date(1991, 2, 8, 0), 'd!-MMMM-yyyy', '08-March-1991');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d!/yyyy', 'February/05/1980');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/MMMM/d!', '1955/February/05');
expectFilter(new Date(2013, 7, 11, 0), 'd!-MM-yy', '11-08-13');
expectFilter(oldDate, 'yyyy/MM/d!', '0001/03/06');
});
it('should work correctly for `EEEE`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'EEEE.d.MMMM.yy', 'Sunday.17.November.13');
expectFilter(new Date(1991, 2, 8, 0), 'd-EEEE-MMMM-yyyy', '8-Friday-March-1991');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/EEEE', 'February/5/1980/Tuesday');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/EEEE/MMMM/d', '1955/Saturday/February/5');
});
it('should work correctly for `EEE`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'EEE.d.MMMM.yy', 'Sun.17.November.13');
expectFilter(new Date(1991, 2, 8, 0), 'd-EEE-MMMM-yyyy', '8-Fri-March-1991');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/EEE', 'February/5/1980/Tue');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/EEE/MMMM/d', '1955/Sat/February/5');
});
it('should work correctly for `HH`', function() {
expectFilter(new Date(2015, 2, 22, 22), 'd.MMMM.yy.HH', '22.March.15.22');
expectFilter(new Date(1991, 2, 8, 11), 'd-MMMM-yyyy-HH', '8-March-1991-11');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/HH', 'February/5/1980/00');
expectFilter(new Date(1955, 1, 5, 3), 'yyyy/MMMM/d HH', '1955/February/5 03');
expectFilter(new Date(2013, 7, 11, 23), 'd-MM-yy HH', '11-08-13 23');
});
it('should work correctly for `H`', function() {
expectFilter(new Date(2015, 2, 22, 22), 'd.MMMM.yy.H', '22.March.15.22');
expectFilter(new Date(1991, 2, 8, 11), 'd-MMMM-yyyy-H', '8-March-1991-11');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/H', 'February/5/1980/0');
expectFilter(new Date(1955, 1, 5, 3), 'yyyy/MMMM/d H', '1955/February/5 3');
expectFilter(new Date(2013, 7, 11, 23), 'd-MM-yy H', '11-08-13 23');
});
it('should work correctly for `hh`', function() {
expectFilter(new Date(2015, 2, 22, 12), 'd.MMMM.yy.hh', '22.March.15.12');
expectFilter(new Date(1991, 2, 8, 11), 'd-MMMM-yyyy-hh', '8-March-1991-11');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/hh', 'February/5/1980/12');
expectFilter(new Date(1955, 1, 5, 3), 'yyyy/MMMM/d hh', '1955/February/5 03');
expectFilter(new Date(2013, 7, 11, 9), 'd-MM-yy hh', '11-08-13 09');
});
it('should work correctly for `h`', function() {
expectFilter(new Date(2015, 2, 22, 12), 'd.MMMM.yy.h', '22.March.15.12');
expectFilter(new Date(1991, 2, 8, 11), 'd-MMMM-yyyy-h', '8-March-1991-11');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/h', 'February/5/1980/12');
expectFilter(new Date(1955, 1, 5, 3), 'yyyy/MMMM/d h', '1955/February/5 3');
expectFilter(new Date(2013, 7, 11, 3), 'd-MM-yy h', '11-08-13 3');
});
it('should work correctly for `mm`', function() {
expectFilter(new Date(2015, 2, 22, 0, 22), 'd.MMMM.yy.mm', '22.March.15.22');
expectFilter(new Date(1991, 2, 8, 0, 59), 'd-MMMM-yyyy-mm', '8-March-1991-59');
expectFilter(new Date(1980, 1, 5, 0, 0), 'MMMM/d/yyyy/mm', 'February/5/1980/00');
expectFilter(new Date(1955, 1, 5, 0, 3), 'yyyy/MMMM/d mm', '1955/February/5 03');
expectFilter(new Date(2013, 7, 11, 0, 46), 'd-MM-yy mm', '11-08-13 46');
expectFilter(new Date(2015, 2, 22, 22, 33), 'd.MMMM.yy.HH:mm', '22.March.15.22:33');
expectFilter(new Date(2015, 2, 22, 2, 1), 'd.MMMM.yy.H:mm', '22.March.15.2:01');
});
it('should work correctly for `m`', function() {
expectFilter(new Date(2015, 2, 22, 0, 22), 'd.MMMM.yy.m', '22.March.15.22');
expectFilter(new Date(1991, 2, 8, 0, 59), 'd-MMMM-yyyy-m', '8-March-1991-59');
expectFilter(new Date(1980, 1, 5, 0, 0), 'MMMM/d/yyyy/m', 'February/5/1980/0');
expectFilter(new Date(1955, 1, 5, 0, 3), 'yyyy/MMMM/d m', '1955/February/5 3');
expectFilter(new Date(2013, 7, 11, 0, 46), 'd-MM-yy m', '11-08-13 46');
expectFilter(new Date(2015, 2, 22, 22, 3), 'd.MMMM.yy.HH:m', '22.March.15.22:3');
expectFilter(new Date(2015, 2, 22, 2, 1), 'd.MMMM.yy.H:m', '22.March.15.2:1');
});
it('should work correctly for `sss`', function() {
expectFilter(new Date(2015, 2, 22, 0, 0, 0, 123), 'd.MMMM.yy.sss', '22.March.15.123');
expectFilter(new Date(1991, 2, 8, 0, 0, 0, 59), 'd-MMMM-yyyy-sss', '8-March-1991-059');
expectFilter(new Date(1980, 1, 5, 0, 0, 0), 'MMMM/d/yyyy/sss', 'February/5/1980/000');
expectFilter(new Date(1955, 1, 5, 0, 0, 0, 3), 'yyyy/MMMM/d sss', '1955/February/5 003');
expectFilter(new Date(2013, 7, 11, 0, 0, 0, 46), 'd-MM-yy sss', '11-08-13 046');
expectFilter(new Date(2015, 2, 22, 22, 33, 0, 44), 'd.MMMM.yy.HH:mm:sss', '22.March.15.22:33:044');
expectFilter(new Date(2015, 2, 22, 0, 0, 0, 1), 'd.MMMM.yy.H:m:sss', '22.March.15.0:0:001');
});
it('should work correctly for `ss`', function() {
expectFilter(new Date(2015, 2, 22, 0, 0, 22), 'd.MMMM.yy.ss', '22.March.15.22');
expectFilter(new Date(1991, 2, 8, 0, 0, 59), 'd-MMMM-yyyy-ss', '8-March-1991-59');
expectFilter(new Date(1980, 1, 5, 0, 0, 0), 'MMMM/d/yyyy/ss', 'February/5/1980/00');
expectFilter(new Date(1955, 1, 5, 0, 0, 3), 'yyyy/MMMM/d ss', '1955/February/5 03');
expectFilter(new Date(2013, 7, 11, 0, 0, 46), 'd-MM-yy ss', '11-08-13 46');
expectFilter(new Date(2015, 2, 22, 22, 33, 44), 'd.MMMM.yy.HH:mm:ss', '22.March.15.22:33:44');
expectFilter(new Date(2015, 2, 22, 0, 0, 1), 'd.MMMM.yy.H:m:ss', '22.March.15.0:0:01');
});
it('should work correctly for `s`', function() {
expectFilter(new Date(2015, 2, 22, 0, 0, 22), 'd.MMMM.yy.s', '22.March.15.22');
expectFilter(new Date(1991, 2, 8, 0, 0, 59), 'd-MMMM-yyyy-s', '8-March-1991-59');
expectFilter(new Date(1980, 1, 5, 0, 0, 0), 'MMMM/d/yyyy/s', 'February/5/1980/0');
expectFilter(new Date(1955, 1, 5, 0, 0, 3), 'yyyy/MMMM/d s', '1955/February/5 3');
expectFilter(new Date(2013, 7, 11, 0, 0, 46), 'd-MM-yy s', '11-08-13 46');
expectFilter(new Date(2015, 2, 22, 22, 33, 4), 'd.MMMM.yy.HH:mm:s', '22.March.15.22:33:4');
expectFilter(new Date(2015, 2, 22, 22, 3, 4), 'd.MMMM.yy.HH:m:s', '22.March.15.22:3:4');
});
it('should work correctly for `a`', function() {
expectFilter(new Date(2015, 2, 22, 10), 'd.MMMM.yy.hha', '22.March.15.10AM');
expectFilter(new Date(2015, 2, 22, 22), 'd.MMMM.yy.hha', '22.March.15.10PM');
expectFilter(new Date(1991, 2, 8, 11), 'd-MMMM-yyyy-hha', '8-March-1991-11AM');
expectFilter(new Date(1991, 2, 8, 23), 'd-MMMM-yyyy-hha', '8-March-1991-11PM');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/hha', 'February/5/1980/12AM');
expectFilter(new Date(1980, 1, 5, 12), 'MMMM/d/yyyy/hha', 'February/5/1980/12PM');
expectFilter(new Date(1955, 1, 5, 3), 'yyyy/MMMM/d hha', '1955/February/5 03AM');
expectFilter(new Date(1955, 1, 5, 15), 'yyyy/MMMM/d hha', '1955/February/5 03PM');
expectFilter(new Date(2013, 7, 11, 9), 'd-MM-yy hha', '11-08-13 09AM');
expectFilter(new Date(2013, 7, 11, 21), 'd-MM-yy hha', '11-08-13 09PM');
});
it('should work correctly for `ww`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'd.MMMM.yy.ww', '17.November.13.47');
expectFilter(new Date(1991, 2, 8, 0), 'd-MMMM-yyyy-ww', '8-March-1991-10');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/ww', 'February/5/1980/06');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/MMMM/d/ww', '1955/February/5/05');
expectFilter(new Date(2013, 7, 11, 0), 'd-MM-yy ww', '11-08-13 33');
expectFilter(oldDate, 'yyyy/MM/d ww', '0001/03/6 10');
});
it('should work correctly for `w`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'd.MMMM.yy.w', '17.November.13.47');
expectFilter(new Date(1991, 2, 8, 0), 'd-MMMM-yyyy-w', '8-March-1991-10');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/w', 'February/5/1980/6');
expectFilter(new Date(1955, 1, 5, 0), 'yyyy/MMMM/d/w', '1955/February/5/5');
expectFilter(new Date(2013, 7, 11, 0), 'd-MM-yy w', '11-08-13 33');
expectFilter(oldDate, 'yyyy/MM/d w', '0001/03/6 10');
});
it('should work correctly for `G`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'd.MMMM.yy.G', '17.November.13.AD');
expectFilter(new Date(-1991, 2, 8, 0), 'd-MMMM-yyyy-G', '8-March-1991-BC');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/G', 'February/5/1980/AD');
expectFilter(new Date(-1955, 1, 5, 0), 'yyyy/MMMM/d/G', '1955/February/5/BC');
expectFilter(new Date(2013, 7, 11, 0), 'd-MM-yy G', '11-08-13 AD');
});
it('should work correctly for `GG`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'd.MMMM.yy.GG', '17.November.13.AD');
expectFilter(new Date(-1991, 2, 8, 0), 'd-MMMM-yyyy-GG', '8-March-1991-BC');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/GG', 'February/5/1980/AD');
expectFilter(new Date(-1955, 1, 5, 0), 'yyyy/MMMM/d/GG', '1955/February/5/BC');
expectFilter(new Date(2013, 7, 11, 0), 'd-MM-yy GG', '11-08-13 AD');
});
it('should work correctly for `GGG`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'd.MMMM.yy.GGG', '17.November.13.AD');
expectFilter(new Date(-1991, 2, 8, 0), 'd-MMMM-yyyy-GGG', '8-March-1991-BC');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/GGG', 'February/5/1980/AD');
expectFilter(new Date(-1955, 1, 5, 0), 'yyyy/MMMM/d/GGG', '1955/February/5/BC');
expectFilter(new Date(2013, 7, 11, 0), 'd-MM-yy GGG', '11-08-13 AD');
});
it('should work correctly for `GGGG`', function() {
expectFilter(new Date(2013, 10, 17, 0), 'd.MMMM.yy.GGGG', '17.November.13.Anno Domini');
expectFilter(new Date(-1991, 2, 8, 0), 'd-MMMM-yyyy-GGGG', '8-March-1991-Before Christ');
expectFilter(new Date(1980, 1, 5, 0), 'MMMM/d/yyyy/GGGG', 'February/5/1980/Anno Domini');
expectFilter(new Date(-1955, 1, 5, 0), 'yyyy/MMMM/d/GGGG', '1955/February/5/Before Christ');
expectFilter(new Date(2013, 7, 11, 0), 'd-MM-yy GGGG', '11-08-13 Anno Domini');
});
it('should work correctly for literal text', function() {
expectFilter(new Date(2013, 10, 17, 0), 'dd.MM.yyyy foo', '17.11.2013 foo');
});
});
describe('with custom formats', function() {
it('should work correctly for `dd`, `MM`, `yyyy`', function() {
expectParse('17.11.2013', 'dd.MM.yyyy', new Date(2013, 10, 17, 0));
expectParse('31.12.2013', 'dd.MM.yyyy', new Date(2013, 11, 31, 0));
expectParse('08-03-1991', 'dd-MM-yyyy', new Date(1991, 2, 8, 0));
expectParse('03/05/1980', 'MM/dd/yyyy', new Date(1980, 2, 5, 0));
expectParse('10.01/1983', 'dd.MM/yyyy', new Date(1983, 0, 10, 0));
expectParse('11-09-1980', 'MM-dd-yyyy', new Date(1980, 10, 9, 0));
expectParse('2011/02/05', 'yyyy/MM/dd', new Date(2011, 1, 5, 0));
expectParse('0001/03/06', 'yyyy/MM/dd', oldDate);
});
it('should work correctly for `yy`', function() {
expectParse('17.11.13', 'dd.MM.yy', new Date(2013, 10, 17, 0));
expectParse('02-05-11', 'dd-MM-yy', new Date(2011, 4, 2, 0));
expectParse('02/05/80', 'MM/dd/yy', new Date(1980, 1, 5, 0));
expectParse('55/02/05', 'yy/MM/dd', new Date(2055, 1, 5, 0));
expectParse('11-08-13', 'dd-MM-yy', new Date(2013, 7, 11, 0));
});
it('should use `68` as the pivot year for `yy`', function() {
expectParse('17.11.68', 'dd.MM.yy', new Date(2068, 10, 17, 0));
expectParse('17.11.69', 'dd.MM.yy', new Date(1969, 10, 17, 0));
});
it('should work correctly for `y`', function() {
expectParse('17.11.2013', 'dd.MM.y', new Date(2013, 10, 17, 0));
expectParse('31.12.2013', 'dd.MM.y', new Date(2013, 11, 31, 0));
expectParse('08-03-1991', 'dd-MM-y', new Date(1991, 2, 8, 0));
expectParse('03/05/1980', 'MM/dd/y', new Date(1980, 2, 5, 0));
expectParse('10.01/1983', 'dd.MM/y', new Date(1983, 0, 10, 0));
expectParse('11-09-1980', 'MM-dd-y', new Date(1980, 10, 9, 0));
expectParse('2011/02/05', 'y/MM/dd', new Date(2011, 1, 5, 0));
});
it('should work correctly for `MMMM`', function() {
expectParse('17.November.13', 'dd.MMMM.yy', new Date(2013, 10, 17, 0));
expectParse('05-March-1980', 'dd-MMMM-yyyy', new Date(1980, 2, 5, 0));
expectParse('February/05/1980', 'MMMM/dd/yyyy', new Date(1980, 1, 5, 0));
expectParse('1949/December/20', 'yyyy/MMMM/dd', new Date(1949, 11, 20, 0));
expectParse('0001/March/06', 'yyyy/MMMM/dd', oldDate);
});
it('should work correctly for `MMM`', function() {
expectParse('30.Sep.10', 'dd.MMM.yy', new Date(2010, 8, 30, 0));
expectParse('02-May-11', 'dd-MMM-yy', new Date(2011, 4, 2, 0));
expectParse('Feb/05/1980', 'MMM/dd/yyyy', new Date(1980, 1, 5, 0));
expectParse('1955/Feb/05', 'yyyy/MMM/dd', new Date(1955, 1, 5, 0));
expectParse('0001/Mar/06', 'yyyy/MMM/dd', oldDate);
});
it('should work correctly for `M`', function() {
expectParse('8/11/2013', 'M/dd/yyyy', new Date(2013, 7, 11, 0));
expectParse('07.11.05', 'dd.M.yy', new Date(2005, 10, 7, 0));
expectParse('02-5-11', 'dd-M-yy', new Date(2011, 4, 2, 0));
expectParse('2/05/1980', 'M/dd/yyyy', new Date(1980, 1, 5, 0));
expectParse('1955/2/05', 'yyyy/M/dd', new Date(1955, 1, 5, 0));
expectParse('02-5-11', 'dd-M-yy', new Date(2011, 4, 2, 0));
});
it('should work correctly for `M!`', function() {
expectParse('8/11/2013', 'M!/dd/yyyy', new Date(2013, 7, 11, 0));
expectParse('07.11.05', 'dd.M!.yy', new Date(2005, 10, 7, 0));
expectParse('02-5-11', 'dd-M!-yy', new Date(2011, 4, 2, 0));
expectParse('2/05/1980', 'M!/dd/yyyy', new Date(1980, 1, 5, 0));
expectParse('1955/2/05', 'yyyy/M!/dd', new Date(1955, 1, 5, 0));
expectParse('02-5-11', 'dd-M!-yy', new Date(2011, 4, 2, 0));
expectParse('0001/3/06', 'yyyy/M!/dd', oldDate);
expectParse('08/11/2013', 'M!/dd/yyyy', new Date(2013, 7, 11, 0));
expectParse('07.11.05', 'dd.M!.yy', new Date(2005, 10, 7, 0));
expectParse('02-05-11', 'dd-M!-yy', new Date(2011, 4, 2, 0));
expectParse('02/05/1980', 'M!/dd/yyyy', new Date(1980, 1, 5, 0));
expectParse('1955/02/05', 'yyyy/M!/dd', new Date(1955, 1, 5, 0));
expectParse('02-05-11', 'dd-M!-yy', new Date(2011, 4, 2, 0));
expectParse('0001/03/06', 'yyyy/M!/dd', oldDate);
});
it('should work correctly for `d`', function() {
expectParse('17.November.13', 'd.MMMM.yy', new Date(2013, 10, 17, 0));
expectParse('8-March-1991', 'd-MMMM-yyyy', new Date(1991, 2, 8, 0));
expectParse('February/5/1980', 'MMMM/d/yyyy', new Date(1980, 1, 5, 0));
expectParse('1955/February/5', 'yyyy/MMMM/d', new Date(1955, 1, 5, 0));
expectParse('11-08-13', 'd-MM-yy', new Date(2013, 7, 11, 0));
expectParse('0001/03/6', 'yyyy/MM/d', oldDate);
});
it('should work correctly for `d!`', function() {
expectParse('17.November.13', 'd!.MMMM.yy', new Date(2013, 10, 17, 0));
expectParse('8-March-1991', 'd!-MMMM-yyyy', new Date(1991, 2, 8, 0));
expectParse('February/5/1980', 'MMMM/d!/yyyy', new Date(1980, 1, 5, 0));
expectParse('1955/February/5', 'yyyy/MMMM/d!', new Date(1955, 1, 5, 0));
expectParse('11-08-13', 'd!-MM-yy', new Date(2013, 7, 11, 0));
expectParse('0001/03/6', 'yyyy/MM/d!', oldDate);
expectParse('17.November.13', 'd!.MMMM.yy', new Date(2013, 10, 17, 0));
expectParse('08-March-1991', 'd!-MMMM-yyyy', new Date(1991, 2, 8, 0));
expectParse('February/05/1980', 'MMMM/d!/yyyy', new Date(1980, 1, 5, 0));
expectParse('1955/February/05', 'yyyy/MMMM/d!', new Date(1955, 1, 5, 0));
expectParse('11-08-13', 'd!-MM-yy', new Date(2013, 7, 11, 0));
expectParse('0001/03/06', 'yyyy/MM/d!', oldDate);
});
it('should work correctly for `EEEE`', function() {
expectParse('Sunday.17.November.13', 'EEEE.d.MMMM.yy', new Date(2013, 10, 17, 0));
expectParse('8-Friday-March-1991', 'd-EEEE-MMMM-yyyy', new Date(1991, 2, 8, 0));
expectParse('February/5/1980/Tuesday', 'MMMM/d/yyyy/EEEE', new Date(1980, 1, 5, 0));
expectParse('1955/Saturday/February/5', 'yyyy/EEEE/MMMM/d', new Date(1955, 1, 5, 0));
});
it('should work correctly for `EEE`', function() {
expectParse('Sun.17.November.13', 'EEE.d.MMMM.yy', new Date(2013, 10, 17, 0));
expectParse('8-Fri-March-1991', 'd-EEE-MMMM-yyyy', new Date(1991, 2, 8, 0));
expectParse('February/5/1980/Tue', 'MMMM/d/yyyy/EEE', new Date(1980, 1, 5, 0));
expectParse('1955/Sat/February/5', 'yyyy/EEE/MMMM/d', new Date(1955, 1, 5, 0));
});
it('should work correctly for `HH`', function() {
expectParse('22.March.15.22', 'd.MMMM.yy.HH', new Date(2015, 2, 22, 22));
expectParse('8-March-1991-11', 'd-MMMM-yyyy-HH', new Date(1991, 2, 8, 11));
expectParse('February/5/1980/00', 'MMMM/d/yyyy/HH', new Date(1980, 1, 5, 0));
expectParse('1955/February/5 03', 'yyyy/MMMM/d HH', new Date(1955, 1, 5, 3));
expectParse('11-08-13 23', 'd-MM-yy HH', new Date(2013, 7, 11, 23));
});
it('should work correctly for `H`', function() {
expectParse('22.March.15.22', 'd.MMMM.yy.H', new Date(2015, 2, 22, 22));
expectParse('8-March-1991-11', 'd-MMMM-yyyy-H', new Date(1991, 2, 8, 11));
expectParse('February/5/1980/0', 'MMMM/d/yyyy/H', new Date(1980, 1, 5, 0));
expectParse('1955/February/5 3', 'yyyy/MMMM/d H', new Date(1955, 1, 5, 3));
expectParse('11-08-13 23', 'd-MM-yy H', new Date(2013, 7, 11, 23));
});
it('should work correctly for `hh`', function() {
expectParse('22.March.15.22', 'd.MMMM.yy.hh', undefined);
expectParse('22.March.15.12', 'd.MMMM.yy.hh', new Date(2015, 2, 22, 12));
expectParse('8-March-1991-11', 'd-MMMM-yyyy-hh', new Date(1991, 2, 8, 11));
expectParse('February/5/1980/00', 'MMMM/d/yyyy/hh', new Date(1980, 1, 5, 0));
expectParse('1955/February/5 03', 'yyyy/MMMM/d hh', new Date(1955, 1, 5, 3));
expectParse('11-08-13 23', 'd-MM-yy hh', undefined);
expectParse('11-08-13 09', 'd-MM-yy hh', new Date(2013, 7, 11, 9));
});
it('should work correctly for `h`', function() {
expectParse('22.March.15.12', 'd.MMMM.yy.h', new Date(2015, 2, 22, 12));
expectParse('8-March-1991-11', 'd-MMMM-yyyy-h', new Date(1991, 2, 8, 11));
expectParse('February/5/1980/0', 'MMMM/d/yyyy/h', new Date(1980, 1, 5, 0));
expectParse('1955/February/5 3', 'yyyy/MMMM/d h', new Date(1955, 1, 5, 3));
expectParse('11-08-13 3', 'd-MM-yy h', new Date(2013, 7, 11, 3));
});
it('should work correctly for `mm`', function() {
expectParse('22.March.15.22', 'd.MMMM.yy.mm', new Date(2015, 2, 22, 0, 22));
expectParse('8-March-1991-59', 'd-MMMM-yyyy-mm', new Date(1991, 2, 8, 0, 59));
expectParse('February/5/1980/00', 'MMMM/d/yyyy/mm', new Date(1980, 1, 5, 0, 0));
expectParse('1955/February/5 03', 'yyyy/MMMM/d mm', new Date(1955, 1, 5, 0, 3));
expectParse('11-08-13 46', 'd-MM-yy mm', new Date(2013, 7, 11, 0, 46));
expectParse('22.March.15.22:33', 'd.MMMM.yy.HH:mm', new Date(2015, 2, 22, 22, 33));
expectParse('22.March.15.2:01', 'd.MMMM.yy.H:mm', new Date(2015, 2, 22, 2, 1));
});
it('should work correctly for `m`', function() {
expectParse('22.March.15.22', 'd.MMMM.yy.m', new Date(2015, 2, 22, 0, 22));
expectParse('8-March-1991-59', 'd-MMMM-yyyy-m', new Date(1991, 2, 8, 0, 59));
expectParse('February/5/1980/0', 'MMMM/d/yyyy/m', new Date(1980, 1, 5, 0, 0));
expectParse('1955/February/5 3', 'yyyy/MMMM/d m', new Date(1955, 1, 5, 0, 3));
expectParse('11-08-13 46', 'd-MM-yy m', new Date(2013, 7, 11, 0, 46));
expectParse('22.March.15.22:3', 'd.MMMM.yy.HH:m', new Date(2015, 2, 22, 22, 3));
expectParse('22.March.15.2:1', 'd.MMMM.yy.H:m', new Date(2015, 2, 22, 2, 1));
});
it('should work correctly for `sss`', function() {
expectParse('22.March.15.123', 'd.MMMM.yy.sss', new Date(2015, 2, 22, 0, 0, 0, 123));
expectParse('8-March-1991-059', 'd-MMMM-yyyy-sss', new Date(1991, 2, 8, 0, 0, 0, 59));
expectParse('February/5/1980/000', 'MMMM/d/yyyy/sss', new Date(1980, 1, 5, 0, 0, 0));
expectParse('1955/February/5 003', 'yyyy/MMMM/d sss', new Date(1955, 1, 5, 0, 0, 0, 3));
expectParse('11-08-13 046', 'd-MM-yy sss', new Date(2013, 7, 11, 0, 0, 0, 46));
expectParse('22.March.15.22:33:044', 'd.MMMM.yy.HH:mm:sss', new Date(2015, 2, 22, 22, 33, 0, 44));
expectParse('22.March.15.0:0:001', 'd.MMMM.yy.H:m:sss', new Date(2015, 2, 22, 0, 0, 0, 1));
});
it('should work correctly for `ss`', function() {
expectParse('22.March.15.22', 'd.MMMM.yy.ss', new Date(2015, 2, 22, 0, 0, 22));
expectParse('8-March-1991-59', 'd-MMMM-yyyy-ss', new Date(1991, 2, 8, 0, 0, 59));
expectParse('February/5/1980/00', 'MMMM/d/yyyy/ss', new Date(1980, 1, 5, 0, 0, 0));
expectParse('1955/February/5 03', 'yyyy/MMMM/d ss', new Date(1955, 1, 5, 0, 0, 3));
expectParse('11-08-13 46', 'd-MM-yy ss', new Date(2013, 7, 11, 0, 0, 46));
expectParse('22.March.15.22:33:44', 'd.MMMM.yy.HH:mm:ss', new Date(2015, 2, 22, 22, 33, 44));
expectParse('22.March.15.0:0:01', 'd.MMMM.yy.H:m:ss', new Date(2015, 2, 22, 0, 0, 1));
});
it('should work correctly for `s`', function() {
expectParse('22.March.15.22', 'd.MMMM.yy.s', new Date(2015, 2, 22, 0, 0, 22));
expectParse('8-March-1991-59', 'd-MMMM-yyyy-s', new Date(1991, 2, 8, 0, 0, 59));
expectParse('February/5/1980/0', 'MMMM/d/yyyy/s', new Date(1980, 1, 5, 0, 0, 0));
expectParse('1955/February/5 3', 'yyyy/MMMM/d s', new Date(1955, 1, 5, 0, 0, 3));
expectParse('11-08-13 46', 'd-MM-yy s', new Date(2013, 7, 11, 0, 0, 46));
expectParse('22.March.15.22:33:4', 'd.MMMM.yy.HH:mm:s', new Date(2015, 2, 22, 22, 33, 4));
expectParse('22.March.15.22:3:4', 'd.MMMM.yy.HH:m:s', new Date(2015, 2, 22, 22, 3, 4));
});
it('should work correctly for `a`', function() {
expectParse('22.March.15.10AM', 'd.MMMM.yy.hha', new Date(2015, 2, 22, 10));
expectParse('22.March.15.10PM', 'd.MMMM.yy.hha', new Date(2015, 2, 22, 22));
expectParse('8-March-1991-11AM', 'd-MMMM-yyyy-hha', new Date(1991, 2, 8, 11));
expectParse('8-March-1991-11PM', 'd-MMMM-yyyy-hha', new Date(1991, 2, 8, 23));
expectParse('February/5/1980/12AM', 'MMMM/d/yyyy/hha', new Date(1980, 1, 5, 0));
expectParse('February/5/1980/12PM', 'MMMM/d/yyyy/hha', new Date(1980, 1, 5, 12));
expectParse('1955/February/5 03AM', 'yyyy/MMMM/d hha', new Date(1955, 1, 5, 3));
expectParse('1955/February/5 03PM', 'yyyy/MMMM/d hha', new Date(1955, 1, 5, 15));
expectParse('11-08-13 09AM', 'd-MM-yy hha', new Date(2013, 7, 11, 9));
expectParse('11-08-13 09PM', 'd-MM-yy hha', new Date(2013, 7, 11, 21));
});
it('should work correctly for `Z`', function() {
expectParse('22.March.15 -0700', 'd.MMMM.yy Z', new Date(2015, 2, 21, 17, 0, 0));
expectParse('8-March-1991 +0800', 'd-MMMM-yyyy Z', new Date(1991, 2, 8, 8, 0, 0));
expectParse('February/5/1980 -0200', 'MMMM/d/yyyy Z', new Date(1980, 1, 4, 22, 0, 0));
expectParse('1955/February/5 +0400', 'yyyy/MMMM/d Z', new Date(1955, 1, 5, 4, 0, 0));
expectParse('11-08-13 -1234', 'd-MM-yy Z', new Date(2013, 7, 10, 11, 26, 0));
expectParse('22.March.15.22:33:4 -1200', 'd.MMMM.yy.HH:mm:s Z', new Date(2015, 2, 22, 10, 33, 4));
expectParse('22.March.15.22:3:4 +1500', 'd.MMMM.yy.HH:m:s Z', new Date(2015, 2, 23, 13, 3, 4));
});
it('should work correctly for `ww`', function() {
expectParse('17.November.13.45', 'd.MMMM.yy.ww', new Date(2013, 10, 17, 0));
expectParse('8-March-1991-09', 'd-MMMM-yyyy-ww', new Date(1991, 2, 8, 0));
expectParse('February/5/1980/05', 'MMMM/d/yyyy/ww', new Date(1980, 1, 5, 0));
expectParse('1955/February/5/04', 'yyyy/MMMM/d/ww', new Date(1955, 1, 5, 0));
expectParse('11-08-13 44', 'd-MM-yy ww', new Date(2013, 7, 11, 0));
expectParse('0001/03/6 10', 'yyyy/MM/d ww', oldDate);
});
it('should work correctly for `w`', function() {
expectParse('17.November.13.45', 'd.MMMM.yy.w', new Date(2013, 10, 17, 0));
expectParse('8-March-1991-9', 'd-MMMM-yyyy-w', new Date(1991, 2, 8, 0));
expectParse('February/5/1980/5', 'MMMM/d/yyyy/w', new Date(1980, 1, 5, 0));
expectParse('1955/February/5/4', 'yyyy/MMMM/d/w', new Date(1955, 1, 5, 0));
expectParse('11-08-13 44', 'd-MM-yy w', new Date(2013, 7, 11, 0));
expectParse('0001/03/6 10', 'yyyy/MM/d w', oldDate);
});
it('should work correctly for `G`', function() {
expectParse('17.November.13.AD', 'd.MMMM.yy.G', new Date(2013, 10, 17, 0));
expectParse('8-March-1991-BC', 'd-MMMM-yyyy-G', new Date(1991, 2, 8, 0));
expectParse('February/5/1980/AD', 'MMMM/d/yyyy/G', new Date(1980, 1, 5, 0));
expectParse('1955/February/5/BC', 'yyyy/MMMM/d/G', new Date(1955, 1, 5, 0));
expectParse('11-08-13 AD', 'd-MM-yy G', new Date(2013, 7, 11, 0));
expectParse('0001/03/6 BC', 'yyyy/MM/d G', oldDate);
});
it('should work correctly for `GG`', function() {
expectParse('17.November.13.AD', 'd.MMMM.yy.GG', new Date(2013, 10, 17, 0));
expectParse('8-March-1991-BC', 'd-MMMM-yyyy-GG', new Date(1991, 2, 8, 0));
expectParse('February/5/1980/AD', 'MMMM/d/yyyy/GG', new Date(1980, 1, 5, 0));
expectParse('1955/February/5/BC', 'yyyy/MMMM/d/GG', new Date(1955, 1, 5, 0));
expectParse('11-08-13 AD', 'd-MM-yy GG', new Date(2013, 7, 11, 0));
expectParse('0001/03/6 BC', 'yyyy/MM/d GG', oldDate);
});
it('should work correctly for `GGG`', function() {
expectParse('17.November.13.AD', 'd.MMMM.yy.GGG', new Date(2013, 10, 17, 0));
expectParse('8-March-1991-BC', 'd-MMMM-yyyy-GGG', new Date(1991, 2, 8, 0));
expectParse('February/5/1980/AD', 'MMMM/d/yyyy/GGG', new Date(1980, 1, 5, 0));
expectParse('1955/February/5/BC', 'yyyy/MMMM/d/GGG', new Date(1955, 1, 5, 0));
expectParse('11-08-13 AD', 'd-MM-yy GGG', new Date(2013, 7, 11, 0));
expectParse('0001/03/6 BC', 'yyyy/MM/d GGG', oldDate);
});
it('should work correctly for `GGGG`', function() {
expectParse('17.November.13.Anno Domini', 'd.MMMM.yy.GGGG', new Date(2013, 10, 17, 0));
expectParse('8-March-1991-Before Christ', 'd-MMMM-yyyy-GGGG', new Date(1991, 2, 8, 0));
expectParse('February/5/1980/Anno Domini', 'MMMM/d/yyyy/GGGG', new Date(1980, 1, 5, 0));
expectParse('1955/February/5/Before Christ', 'yyyy/MMMM/d/GGGG', new Date(1955, 1, 5, 0));
expectParse('11-08-13 Anno Domini', 'd-MM-yy GGGG', new Date(2013, 7, 11, 0));
expectParse('0001/03/6 Before Christ', 'yyyy/MM/d GGGG', oldDate);
});
});
describe('with predefined formats', function() {
it('should work correctly for `shortDate`', function() {
expectParse('9/3/10', 'shortDate', new Date(2010, 8, 3, 0));
});
it('should work correctly for `mediumDate`', function() {
expectParse('Sep 3, 2010', 'mediumDate', new Date(2010, 8, 3, 0));
});
it('should work correctly for `longDate`', function() {
expectParse('September 3, 2010', 'longDate', new Date(2010, 8, 3, 0));
});
it('should work correctly for `fullDate`', function() {
expectParse('Friday, September 3, 2010', 'fullDate', new Date(2010, 8, 3, 0));
});
});
describe('with value literals', function() {
describe('filter', function() {
it('should work with multiple literals', function() {
expect(dateParser.filter(new Date(2013, 0, 29), 'd \'de\' MMMM \'de\' y')).toEqual('29 de January de 2013');
});
it('should work with escaped single quote', function() {
expect(dateParser.filter(new Date(2015, 2, 22, 12), 'd.MMMM.yy h \'o\'\'clock\'')).toEqual('22.March.15 12 o\'clock');
});
it('should work with only a single quote', function() {
expect(dateParser.filter(new Date(2015, 2, 22), 'd.MMMM.yy \'\'\'')).toEqual('22.March.15 \'');
});
it('should work with trailing literal', function() {
expect(dateParser.filter(new Date(2013, 0, 1), '\'year\' y')).toEqual('year 2013');
});
it('should work without whitespace', function() {
expect(dateParser.filter(new Date(2013, 0, 1), '\'year:\'y')).toEqual('year:2013');
});
});
describe('parse', function() {
it('should work with multiple literals', function() {
expect(dateParser.parse('29 de January de 2013', 'd \'de\' MMMM \'de\' y')).toEqual(new Date(2013, 0, 29));
});
it('should work with escaped single quote', function() {
expect(dateParser.parse('22.March.15 12 o\'clock', 'd.MMMM.yy h \'o\'\'clock\'')).toEqual(new Date(2015, 2, 22, 12));
});
it('should work with only a single quote', function() {
expect(dateParser.parse('22.March.15 \'', 'd.MMMM.yy \'\'\'')).toEqual(new Date(2015, 2, 22));
});
it('should work with trailing literal', function() {
expect(dateParser.parse('year 2013', '\'year\' y')).toEqual(new Date(2013, 0, 1));
});
it('should work without whitespace', function() {
expect(dateParser.parse('year:2013', '\'year:\'y')).toEqual(new Date(2013, 0, 1));
});
});
});
describe('with edge case', function() {
it('should not work for invalid number of days in February', function() {
expectParse('29.02.2013', 'dd.MM.yyyy', undefined);
});
it('should not work for 0 number of days', function() {
expectParse('00.02.2013', 'dd.MM.yyyy', undefined);
});
it('should work for 29 days in February for leap years', function() {
expectParse('29.02.2000', 'dd.MM.yyyy', new Date(2000, 1, 29, 0));
});
it('should not work for 31 days for some months', function() {
expectParse('31-04-2013', 'dd-MM-yyyy', undefined);
expectParse('November 31, 2013', 'MMMM d, yyyy', undefined);
});
});
describe('base date', function() {
var baseDate;
beforeEach(function() {
baseDate = new Date(2010, 10, 10);
});
it('should pre-initialize our date with a base date', function() {
expect(expectBaseParse('2015', 'yyyy', baseDate, new Date(2015, 10, 10)));
expect(expectBaseParse('1', 'M', baseDate, new Date(2010, 0, 10)));
expect(expectBaseParse('1', 'd', baseDate, new Date(2010, 10, 1)));
});
it('should ignore the base date when it is an invalid date', inject(function($log) {
spyOn($log, 'warn');
expect(expectBaseParse('30-12', 'dd-MM', new Date('foo'), new Date(1900, 11, 30)));
expect(expectBaseParse('30-2015', 'dd-yyyy', 'I am a cat', new Date(2015, 0, 30)));
expect($log.warn).toHaveBeenCalledWith('dateparser:', 'baseDate is not a valid date');
}));
});
it('should not parse non-string inputs', function() {
expectParse(123456, 'dd.MM.yyyy', 123456);
var date = new Date();
expectParse(date, 'dd.MM.yyyy', date);
});
it('should not parse if no format is specified', function() {
expectParse('21.08.1951', '', '21.08.1951');
});
it('should reinitialize when locale changes', inject(function($locale) {
spyOn(dateParser, 'init').and.callThrough();
expect($locale.id).toBe('en-us');
$locale.id = 'en-uk';
dateParser.parse('22.March.15.22', 'd.MMMM.yy.s');
expect(dateParser.init).toHaveBeenCalled();
}));
describe('timezone functions', function() {
describe('toTimezone', function() {
it('adjusts date: PST - EST', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var toWestDate = dateParser.toTimezone(date, 'PST');
var toEastDate = dateParser.toTimezone(date, 'EST');
expect(toWestDate.getTime() - toEastDate.getTime()).toEqual(1000 * 60 * 60 * 3);
});
it('adjusts date: GMT-0500 - GMT+0500', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var toWestDate = dateParser.toTimezone(date, 'GMT-0500');
var toEastDate = dateParser.toTimezone(date, 'GMT+0500');
expect(toWestDate.getTime() - toEastDate.getTime()).toEqual(1000 * 60 * 60 * 10);
});
it('adjusts date: -600 - +600', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var toWestDate = dateParser.toTimezone(date, '-600');
var toEastDate = dateParser.toTimezone(date, '+600');
expect(toWestDate.getTime() - toEastDate.getTime()).toEqual(1000 * 60 * 60 * 12);
});
it('tolerates null date', function() {
var date = null;
var toNullDate = dateParser.toTimezone(date, '-600');
expect(toNullDate).toEqual(date);
});
it('tolerates null timezone', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var toNullTimezoneDate = dateParser.toTimezone(date, null);
expect(toNullTimezoneDate).toEqual(date);
});
});
describe('fromTimezone', function() {
it('adjusts date: PST - EST', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var fromWestDate = dateParser.fromTimezone(date, 'PST');
var fromEastDate = dateParser.fromTimezone(date, 'EST');
expect(fromWestDate.getTime() - fromEastDate.getTime()).toEqual(1000 * 60 * 60 * -3);
});
it('adjusts date: GMT-0500 - GMT+0500', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var fromWestDate = dateParser.fromTimezone(date, 'GMT-0500');
var fromEastDate = dateParser.fromTimezone(date, 'GMT+0500');
expect(fromWestDate.getTime() - fromEastDate.getTime()).toEqual(1000 * 60 * 60 * -10);
});
it('adjusts date: -600 - +600', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var fromWestDate = dateParser.fromTimezone(date, '-600');
var fromEastDate = dateParser.fromTimezone(date, '+600');
expect(fromWestDate.getTime() - fromEastDate.getTime()).toEqual(1000 * 60 * 60 * -12);
});
it('tolerates null date', function() {
var date = null;
var toNullDate = dateParser.fromTimezone(date, '-600');
expect(toNullDate).toEqual(date);
});
it('tolerates null timezone', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var toNullTimezoneDate = dateParser.fromTimezone(date, null);
expect(toNullTimezoneDate).toEqual(date);
});
});
describe('timezoneToOffset', function() {
it('calculates minutes off from current timezone', function() {
var offsetMinutesUtc = dateParser.timezoneToOffset('UTC');
var offsetMinutesUtcPlus1 = dateParser.timezoneToOffset('GMT+0100');
expect(offsetMinutesUtc - offsetMinutesUtcPlus1).toEqual(60);
});
});
describe('addDateMinutes', function() {
it('adds minutes to a date', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var oneHourMore = dateParser.addDateMinutes(date, 60);
expect(oneHourMore).toEqual(new Date('2008-01-01T01:00:00.000Z'));
});
});
describe('convertTimezoneToLocal', function() {
it('adjusts date: PST - EST', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var toWestDate = dateParser.convertTimezoneToLocal(date, 'PST');
var toEastDate = dateParser.convertTimezoneToLocal(date, 'EST');
expect(toWestDate.getTime() - toEastDate.getTime()).toEqual(1000 * 60 * 60 * 3);
});
it('adjusts date: GMT-0500 - GMT+0500', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var toWestDate = dateParser.convertTimezoneToLocal(date, 'GMT-0500');
var toEastDate = dateParser.convertTimezoneToLocal(date, 'GMT+0500');
expect(toWestDate.getTime() - toEastDate.getTime()).toEqual(1000 * 60 * 60 * 10);
});
it('adjusts date: -600 - +600', function() {
var date = new Date('2008-01-01T00:00:00.000Z');
var toWestDate = dateParser.convertTimezoneToLocal(date, '-600');
var toEastDate = dateParser.convertTimezoneToLocal(date, '+600');
expect(toWestDate.getTime() - toEastDate.getTime()).toEqual(1000 * 60 * 60 * 12);
});
});
});
describe('overrideParser', function() {
var twoDigitYearParser = function (value) {
this.year = +value + (+value > 30 ? 1900 : 2000);
};
it('should get the current parser', function() {
expect(dateParser.getParser('yy')).toBeTruthy();
});
it('should override the parser', function() {
dateParser.overrideParser('yy', twoDigitYearParser);
expect(dateParser.parse('68', 'yy').getFullYear()).toEqual(1968);
expect(dateParser.parse('67', 'yy').getFullYear()).toEqual(1967);
expect(dateParser.parse('31', 'yy').getFullYear()).toEqual(1931);
expect(dateParser.parse('30', 'yy').getFullYear()).toEqual(2030);
});
it('should clear cached parsers', function() {
expect(dateParser.parse('68', 'yy').getFullYear()).toEqual(2068);
dateParser.overrideParser('yy', twoDigitYearParser);
expect(dateParser.parse('68', 'yy').getFullYear()).toEqual(1968);
});
});
});
+11
View File
@@ -0,0 +1,11 @@
.uib-datepicker .uib-title {
width: 100%;
}
.uib-day button, .uib-month button, .uib-year button {
min-width: 100%;
}
.uib-left, .uib-right {
width: 100%
}
+685
View File
@@ -0,0 +1,685 @@
angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.isClass'])
.value('$datepickerSuppressError', false)
.value('$datepickerLiteralWarning', true)
.constant('uibDatepickerConfig', {
datepickerMode: 'day',
formatDay: 'dd',
formatMonth: 'MMMM',
formatYear: 'yyyy',
formatDayHeader: 'EEE',
formatDayTitle: 'MMMM yyyy',
formatMonthTitle: 'yyyy',
maxDate: null,
maxMode: 'year',
minDate: null,
minMode: 'day',
monthColumns: 3,
ngModelOptions: {},
shortcutPropagation: false,
showWeeks: true,
yearColumns: 5,
yearRows: 4
})
.controller('UibDatepickerController', ['$scope', '$element', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',
function($scope, $element, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {
var self = this,
ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;
ngModelOptions = {},
watchListeners = [];
$element.addClass('uib-datepicker');
$attrs.$set('role', 'application');
if (!$scope.datepickerOptions) {
$scope.datepickerOptions = {};
}
// Modes chain
this.modes = ['day', 'month', 'year'];
[
'customClass',
'dateDisabled',
'datepickerMode',
'formatDay',
'formatDayHeader',
'formatDayTitle',
'formatMonth',
'formatMonthTitle',
'formatYear',
'maxDate',
'maxMode',
'minDate',
'minMode',
'monthColumns',
'showWeeks',
'shortcutPropagation',
'startingDay',
'yearColumns',
'yearRows'
].forEach(function(key) {
switch (key) {
case 'customClass':
case 'dateDisabled':
$scope[key] = $scope.datepickerOptions[key] || angular.noop;
break;
case 'datepickerMode':
$scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ?
$scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode;
break;
case 'formatDay':
case 'formatDayHeader':
case 'formatDayTitle':
case 'formatMonth':
case 'formatMonthTitle':
case 'formatYear':
self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
$interpolate($scope.datepickerOptions[key])($scope.$parent) :
datepickerConfig[key];
break;
case 'monthColumns':
case 'showWeeks':
case 'shortcutPropagation':
case 'yearColumns':
case 'yearRows':
self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
$scope.datepickerOptions[key] : datepickerConfig[key];
break;
case 'startingDay':
if (angular.isDefined($scope.datepickerOptions.startingDay)) {
self.startingDay = $scope.datepickerOptions.startingDay;
} else if (angular.isNumber(datepickerConfig.startingDay)) {
self.startingDay = datepickerConfig.startingDay;
} else {
self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
}
break;
case 'maxDate':
case 'minDate':
$scope.$watch('datepickerOptions.' + key, function(value) {
if (value) {
if (angular.isDate(value)) {
self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.getOption('timezone'));
} else {
if ($datepickerLiteralWarning) {
$log.warn('Literal date support has been deprecated, please switch to date object usage');
}
self[key] = new Date(dateFilter(value, 'medium'));
}
} else {
self[key] = datepickerConfig[key] ?
dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.getOption('timezone')) :
null;
}
self.refreshView();
});
break;
case 'maxMode':
case 'minMode':
if ($scope.datepickerOptions[key]) {
$scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) {
self[key] = $scope[key] = angular.isDefined(value) ? value : $scope.datepickerOptions[key];
if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) ||
key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) {
$scope.datepickerMode = self[key];
$scope.datepickerOptions.datepickerMode = self[key];
}
});
} else {
self[key] = $scope[key] = datepickerConfig[key] || null;
}
break;
}
});
$scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
$scope.disabled = angular.isDefined($attrs.disabled) || false;
if (angular.isDefined($attrs.ngDisabled)) {
watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) {
$scope.disabled = disabled;
self.refreshView();
}));
}
$scope.isActive = function(dateObject) {
if (self.compare(dateObject.date, self.activeDate) === 0) {
$scope.activeDateId = dateObject.uid;
return true;
}
return false;
};
this.init = function(ngModelCtrl_) {
ngModelCtrl = ngModelCtrl_;
ngModelOptions = extractOptions(ngModelCtrl);
if ($scope.datepickerOptions.initDate) {
self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.getOption('timezone')) || new Date();
$scope.$watch('datepickerOptions.initDate', function(initDate) {
if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.getOption('timezone'));
self.refreshView();
}
});
} else {
self.activeDate = new Date();
}
var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();
this.activeDate = !isNaN(date) ?
dateParser.fromTimezone(date, ngModelOptions.getOption('timezone')) :
dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));
ngModelCtrl.$render = function() {
self.render();
};
};
this.render = function() {
if (ngModelCtrl.$viewValue) {
var date = new Date(ngModelCtrl.$viewValue),
isValid = !isNaN(date);
if (isValid) {
this.activeDate = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));
} else if (!$datepickerSuppressError) {
$log.error('Datepicker directive: "ng-model" value must be a Date object');
}
}
this.refreshView();
};
this.refreshView = function() {
if (this.element) {
$scope.selectedDt = null;
this._refreshView();
if ($scope.activeDt) {
$scope.activeDateId = $scope.activeDt.uid;
}
var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
date = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));
ngModelCtrl.$setValidity('dateDisabled', !date ||
this.element && !this.isDisabled(date));
}
};
this.createDateObject = function(date, format) {
var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
model = dateParser.fromTimezone(model, ngModelOptions.getOption('timezone'));
var today = new Date();
today = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));
var time = this.compare(date, today);
var dt = {
date: date,
label: dateParser.filter(date, format),
selected: model && this.compare(date, model) === 0,
disabled: this.isDisabled(date),
past: time < 0,
current: time === 0,
future: time > 0,
customClass: this.customClass(date) || null
};
if (model && this.compare(date, model) === 0) {
$scope.selectedDt = dt;
}
if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) {
$scope.activeDt = dt;
}
return dt;
};
this.isDisabled = function(date) {
return $scope.disabled ||
this.minDate && this.compare(date, this.minDate) < 0 ||
this.maxDate && this.compare(date, this.maxDate) > 0 ||
$scope.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode});
};
this.customClass = function(date) {
return $scope.customClass({date: date, mode: $scope.datepickerMode});
};
// Split array into smaller arrays
this.split = function(arr, size) {
var arrays = [];
while (arr.length > 0) {
arrays.push(arr.splice(0, size));
}
return arrays;
};
$scope.select = function(date) {
if ($scope.datepickerMode === self.minMode) {
var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.getOption('timezone')) : new Date(0, 0, 0, 0, 0, 0, 0);
dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
dt = dateParser.toTimezone(dt, ngModelOptions.getOption('timezone'));
ngModelCtrl.$setViewValue(dt);
ngModelCtrl.$render();
} else {
self.activeDate = date;
setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);
$scope.$emit('uib:datepicker.mode');
}
$scope.$broadcast('uib:datepicker.focus');
};
$scope.move = function(direction) {
var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),
month = self.activeDate.getMonth() + direction * (self.step.months || 0);
self.activeDate.setFullYear(year, month, 1);
self.refreshView();
};
$scope.toggleMode = function(direction) {
direction = direction || 1;
if ($scope.datepickerMode === self.maxMode && direction === 1 ||
$scope.datepickerMode === self.minMode && direction === -1) {
return;
}
setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]);
$scope.$emit('uib:datepicker.mode');
};
// Key event mapper
$scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };
var focusElement = function() {
self.element[0].focus();
};
// Listen for focus requests from popup directive
$scope.$on('uib:datepicker.focus', focusElement);
$scope.keydown = function(evt) {
var key = $scope.keys[evt.which];
if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {
return;
}
evt.preventDefault();
if (!self.shortcutPropagation) {
evt.stopPropagation();
}
if (key === 'enter' || key === 'space') {
if (self.isDisabled(self.activeDate)) {
return; // do nothing
}
$scope.select(self.activeDate);
} else if (evt.ctrlKey && (key === 'up' || key === 'down')) {
$scope.toggleMode(key === 'up' ? 1 : -1);
} else {
self.handleKeyDown(key, evt);
self.refreshView();
}
};
$element.on('keydown', function(evt) {
$scope.$apply(function() {
$scope.keydown(evt);
});
});
$scope.$on('$destroy', function() {
//Clear all watch listeners on destroy
while (watchListeners.length) {
watchListeners.shift()();
}
});
function setMode(mode) {
$scope.datepickerMode = mode;
$scope.datepickerOptions.datepickerMode = mode;
}
function extractOptions(ngModelCtrl) {
var ngModelOptions;
if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
// guarantee a value
ngModelOptions = ngModelCtrl.$options ||
$scope.datepickerOptions.ngModelOptions ||
datepickerConfig.ngModelOptions ||
{};
// mimic 1.6+ api
ngModelOptions.getOption = function (key) {
return ngModelOptions[key];
};
} else { // in angular >=1.6 $options is always present
// ng-model-options defaults timezone to null; don't let its precedence squash a non-null value
var timezone = ngModelCtrl.$options.getOption('timezone') ||
($scope.datepickerOptions.ngModelOptions ? $scope.datepickerOptions.ngModelOptions.timezone : null) ||
(datepickerConfig.ngModelOptions ? datepickerConfig.ngModelOptions.timezone : null);
// values passed to createChild override existing values
ngModelOptions = ngModelCtrl.$options // start with a ModelOptions instance
.createChild(datepickerConfig.ngModelOptions) // lowest precedence
.createChild($scope.datepickerOptions.ngModelOptions)
.createChild(ngModelCtrl.$options) // highest precedence
.createChild({timezone: timezone}); // to keep from squashing a non-null value
}
return ngModelOptions;
}
}])
.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
this.step = { months: 1 };
this.element = $element;
function getDaysInMonth(year, month) {
return month === 1 && year % 4 === 0 &&
(year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month];
}
this.init = function(ctrl) {
angular.extend(ctrl, this);
scope.showWeeks = ctrl.showWeeks;
ctrl.refreshView();
};
this.getDates = function(startDate, n) {
var dates = new Array(n), current = new Date(startDate), i = 0, date;
while (i < n) {
date = new Date(current);
dates[i++] = date;
current.setDate(current.getDate() + 1);
}
return dates;
};
this._refreshView = function() {
var year = this.activeDate.getFullYear(),
month = this.activeDate.getMonth(),
firstDayOfMonth = new Date(this.activeDate);
firstDayOfMonth.setFullYear(year, month, 1);
var difference = this.startingDay - firstDayOfMonth.getDay(),
numDisplayedFromPreviousMonth = difference > 0 ?
7 - difference : - difference,
firstDate = new Date(firstDayOfMonth);
if (numDisplayedFromPreviousMonth > 0) {
firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
}
// 42 is the number of days on a six-week calendar
var days = this.getDates(firstDate, 42);
for (var i = 0; i < 42; i ++) {
days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), {
secondary: days[i].getMonth() !== month,
uid: scope.uniqueId + '-' + i
});
}
scope.labels = new Array(7);
for (var j = 0; j < 7; j++) {
scope.labels[j] = {
abbr: dateFilter(days[j].date, this.formatDayHeader),
full: dateFilter(days[j].date, 'EEEE')
};
}
scope.title = dateFilter(this.activeDate, this.formatDayTitle);
scope.rows = this.split(days, 7);
if (scope.showWeeks) {
scope.weekNumbers = [];
var thursdayIndex = (4 + 7 - this.startingDay) % 7,
numWeeks = scope.rows.length;
for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
scope.weekNumbers.push(
getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));
}
}
};
this.compare = function(date1, date2) {
var _date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
var _date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
_date1.setFullYear(date1.getFullYear());
_date2.setFullYear(date2.getFullYear());
return _date1 - _date2;
};
function getISO8601WeekNumber(date) {
var checkDate = new Date(date);
checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
var time = checkDate.getTime();
checkDate.setMonth(0); // Compare with Jan 1
checkDate.setDate(1);
return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
}
this.handleKeyDown = function(key, evt) {
var date = this.activeDate.getDate();
if (key === 'left') {
date = date - 1;
} else if (key === 'up') {
date = date - 7;
} else if (key === 'right') {
date = date + 1;
} else if (key === 'down') {
date = date + 7;
} else if (key === 'pageup' || key === 'pagedown') {
var month = this.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);
this.activeDate.setMonth(month, 1);
date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date);
} else if (key === 'home') {
date = 1;
} else if (key === 'end') {
date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth());
}
this.activeDate.setDate(date);
};
}])
.controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
this.step = { years: 1 };
this.element = $element;
this.init = function(ctrl) {
angular.extend(ctrl, this);
ctrl.refreshView();
};
this._refreshView = function() {
var months = new Array(12),
year = this.activeDate.getFullYear(),
date;
for (var i = 0; i < 12; i++) {
date = new Date(this.activeDate);
date.setFullYear(year, i, 1);
months[i] = angular.extend(this.createDateObject(date, this.formatMonth), {
uid: scope.uniqueId + '-' + i
});
}
scope.title = dateFilter(this.activeDate, this.formatMonthTitle);
scope.rows = this.split(months, this.monthColumns);
scope.yearHeaderColspan = this.monthColumns > 3 ? this.monthColumns - 2 : 1;
};
this.compare = function(date1, date2) {
var _date1 = new Date(date1.getFullYear(), date1.getMonth());
var _date2 = new Date(date2.getFullYear(), date2.getMonth());
_date1.setFullYear(date1.getFullYear());
_date2.setFullYear(date2.getFullYear());
return _date1 - _date2;
};
this.handleKeyDown = function(key, evt) {
var date = this.activeDate.getMonth();
if (key === 'left') {
date = date - 1;
} else if (key === 'up') {
date = date - this.monthColumns;
} else if (key === 'right') {
date = date + 1;
} else if (key === 'down') {
date = date + this.monthColumns;
} else if (key === 'pageup' || key === 'pagedown') {
var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);
this.activeDate.setFullYear(year);
} else if (key === 'home') {
date = 0;
} else if (key === 'end') {
date = 11;
}
this.activeDate.setMonth(date);
};
}])
.controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
var columns, range;
this.element = $element;
function getStartingYear(year) {
return parseInt((year - 1) / range, 10) * range + 1;
}
this.yearpickerInit = function() {
columns = this.yearColumns;
range = this.yearRows * columns;
this.step = { years: range };
};
this._refreshView = function() {
var years = new Array(range), date;
for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()); i < range; i++) {
date = new Date(this.activeDate);
date.setFullYear(start + i, 0, 1);
years[i] = angular.extend(this.createDateObject(date, this.formatYear), {
uid: scope.uniqueId + '-' + i
});
}
scope.title = [years[0].label, years[range - 1].label].join(' - ');
scope.rows = this.split(years, columns);
scope.columns = columns;
};
this.compare = function(date1, date2) {
return date1.getFullYear() - date2.getFullYear();
};
this.handleKeyDown = function(key, evt) {
var date = this.activeDate.getFullYear();
if (key === 'left') {
date = date - 1;
} else if (key === 'up') {
date = date - columns;
} else if (key === 'right') {
date = date + 1;
} else if (key === 'down') {
date = date + columns;
} else if (key === 'pageup' || key === 'pagedown') {
date += (key === 'pageup' ? - 1 : 1) * range;
} else if (key === 'home') {
date = getStartingYear(this.activeDate.getFullYear());
} else if (key === 'end') {
date = getStartingYear(this.activeDate.getFullYear()) + range - 1;
}
this.activeDate.setFullYear(date);
};
}])
.directive('uibDatepicker', function() {
return {
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/datepicker/datepicker.html';
},
scope: {
datepickerOptions: '=?'
},
require: ['uibDatepicker', '^ngModel'],
restrict: 'A',
controller: 'UibDatepickerController',
controllerAs: 'datepicker',
link: function(scope, element, attrs, ctrls) {
var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];
datepickerCtrl.init(ngModelCtrl);
}
};
})
.directive('uibDaypicker', function() {
return {
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/datepicker/day.html';
},
require: ['^uibDatepicker', 'uibDaypicker'],
restrict: 'A',
controller: 'UibDaypickerController',
link: function(scope, element, attrs, ctrls) {
var datepickerCtrl = ctrls[0],
daypickerCtrl = ctrls[1];
daypickerCtrl.init(datepickerCtrl);
}
};
})
.directive('uibMonthpicker', function() {
return {
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/datepicker/month.html';
},
require: ['^uibDatepicker', 'uibMonthpicker'],
restrict: 'A',
controller: 'UibMonthpickerController',
link: function(scope, element, attrs, ctrls) {
var datepickerCtrl = ctrls[0],
monthpickerCtrl = ctrls[1];
monthpickerCtrl.init(datepickerCtrl);
}
};
})
.directive('uibYearpicker', function() {
return {
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/datepicker/year.html';
},
require: ['^uibDatepicker', 'uibYearpicker'],
restrict: 'A',
controller: 'UibYearpickerController',
link: function(scope, element, attrs, ctrls) {
var ctrl = ctrls[0];
angular.extend(ctrl, ctrls[1]);
ctrl.yearpickerInit();
ctrl.refreshView();
}
};
});
+26
View File
@@ -0,0 +1,26 @@
<style>
.full button span {
background-color: limegreen;
border-radius: 32px;
color: black;
}
.partially button span {
background-color: orange;
border-radius: 32px;
color: black;
}
</style>
<div ng-controller="DatepickerDemoCtrl">
<pre>Selected date is: <em>{{dt | date:'fullDate' }}</em></pre>
<h4>Inline</h4>
<div style="display:inline-block; min-height:290px;">
<div uib-datepicker ng-model="dt" class="well well-sm" datepicker-options="options"></div>
</div>
<hr />
<button type="button" class="btn btn-sm btn-info" ng-click="today()">Today</button>
<button type="button" class="btn btn-sm btn-default" ng-click="setDate(2009, 7, 24)">2009-08-24</button>
<button type="button" class="btn btn-sm btn-danger" ng-click="clear()">Clear</button>
<button type="button" class="btn btn-sm btn-default" ng-click="toggleMin()" uib-tooltip="After today restriction">Min date</button>
</div>
+66
View File
@@ -0,0 +1,66 @@
angular.module('ui.bootstrap.demo').controller('DatepickerDemoCtrl', function ($scope) {
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.clear = function() {
$scope.dt = null;
};
$scope.options = {
customClass: getDayClass,
minDate: new Date(),
showWeeks: true
};
// Disable weekend selection
function disabled(data) {
var date = data.date,
mode = data.mode;
return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
}
$scope.toggleMin = function() {
$scope.options.minDate = $scope.options.minDate ? null : new Date();
};
$scope.toggleMin();
$scope.setDate = function(year, month, day) {
$scope.dt = new Date(year, month, day);
};
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
var afterTomorrow = new Date(tomorrow);
afterTomorrow.setDate(tomorrow.getDate() + 1);
$scope.events = [
{
date: tomorrow,
status: 'full'
},
{
date: afterTomorrow,
status: 'partially'
}
];
function getDayClass(data) {
var date = data.date,
mode = data.mode;
if (mode === 'day') {
var dayToCheck = new Date(date).setHours(0,0,0,0);
for (var i = 0; i < $scope.events.length; i++) {
var currentDay = new Date($scope.events[i].date).setHours(0,0,0,0);
if (dayToCheck === currentDay) {
return $scope.events[i].status;
}
}
}
return '';
}
});
+161
View File
@@ -0,0 +1,161 @@
Our datepicker is flexible and fully customizable.
You can navigate through days, months and years.
The datepicker has 3 modes:
* `day` - In this mode you're presented with a 6-week calendar for a specified month.
* `month` - In this mode you can select a month within a selected year.
* `year` - In this mode you are presented with a range of years (20 by default).
### uib-datepicker settings
* `ng-model`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i> -
The date object. Must be a Javascript `Date` object. You may use the `uibDateParser` service to assist in string-to-object conversion.
* `ng-model-options`
<small class="badge">$</small>
<small class="badge">C</small>
_(Default: `{}`)_ -
Supported [angular ngModelOptions](https://docs.angularjs.org/api/ng/directive/ngModelOptions):
* allowInvalid
* timezone
* `template-url`
_(Default: `uib/template/datepicker/datepicker.html`)_ -
Add the ability to override the template used on the component.
Apart from the previous settings, to configure the uib-datepicker you need to create an object in Javascript with all the options and use it on the `datepicker-options` attribute:
* `datepicker-options`
<small class="badge">$</small> -
An object to configure the datepicker in one place.
* `customClass ({date: date, mode: mode})` -
An optional expression to add classes based on passing an object with date and current mode properties.
* `dateDisabled ({date: date, mode: mode})` -
An optional expression to disable visible options based on passing an object with date and current mode properties.
* `datepickerMode`
<small class="badge">C</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `day`)_ -
Current mode of the datepicker _(day|month|year)_. Can be used to initialize the datepicker in a specific mode.
* `formatDay`
<small class="badge">C</small>
_(Default: `dd`)_ -
Format of day in month.
* `formatMonth`
<small class="badge">C</small>
_(Default: `MMMM`)_ -
Format of month in year.
* `formatYear`
<small class="badge">C</small>
_(Default: `yyyy`)_ -
Format of year in year range.
* `formatDayHeader`
<small class="badge">C</small>
_(Default: `EEE`)_ -
Format of day in week header.
* `formatDayTitle`
<small class="badge">C</small>
_(Default: `MMMM yyyy`)_ -
Format of title when selecting day.
* `formatMonthTitle`
<small class="badge">C</small>
_(Default: `yyyy`)_ -
Format of title when selecting month.
* `initDate`
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `null`)_ -
The initial date view when no model value is specified.
* `maxDate`
<small class="badge">C</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `null`)_ -
Defines the maximum available date. Requires a Javascript Date object.
* `maxMode`
<small class="badge">C</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `year`)_ -
Sets an upper limit for mode.
* `minDate`
<small class="badge">C</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `null`)_ -
Defines the minimum available date. Requires a Javascript Date object.
* `minMode`
<small class="badge">C</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `day`)_ -
Sets a lower limit for mode.
* `monthColumns`
<small class="badge">C</small>
_(Default: `3`)_ -
Number of columns displayed in month selection.
* `ngModelOptions`
<small class="badge">C</small>
_(Default: `null`)_ -
Sets `ngModelOptions` for datepicker. This can be overridden through attribute usage
* `shortcutPropagation`
<small class="badge">C</small>
_(Default: `false`)_ -
An option to disable the propagation of the keydown event.
* `showWeeks`
<small class="badge">C</small>
_(Default: `true`)_ -
Whether to display week numbers.
* `startingDay`
<small class="badge">C</small>
*(Default: `$locale.DATETIME_FORMATS.FIRSTDAYOFWEEK`)* -
Starting day of the week from 0-6 (0=Sunday, ..., 6=Saturday).
* `yearRows`
<small class="badge">C</small>
_(Default: `4`)_ -
Number of rows displayed in year selection.
* `yearColumns`
<small class="badge">C</small>
_(Default: `5`)_ -
Number of columns displayed in year selection.
### Keyboard support
Depending on datepicker's current mode, the date may refer either to day, month or year. Accordingly, the term view refers either to a month, year or year range.
* `Left`: Move focus to the previous date. Will move to the last date of the previous view, if the current date is the first date of a view.
* `Right`: Move focus to the next date. Will move to the first date of the following view, if the current date is the last date of a view.
* `Up`: Move focus to the same column of the previous row. Will wrap to the appropriate row in the previous view.
* `Down`: Move focus to the same column of the following row. Will wrap to the appropriate row in the following view.
* `PgUp`: Move focus to the same date of the previous view. If that date does not exist, focus is placed on the last date of the month.
* `PgDn`: Move focus to the same date of the following view. If that date does not exist, focus is placed on the last date of the month.
* `Home`: Move to the first date of the view.
* `End`: Move to the last date of the view.
* `Enter`/`Space`: Select date.
* `Ctrl`+`Up`: Move to an upper mode.
* `Ctrl`+`Down`: Move to a lower mode.
* `Esc`: Will close popup, and move focus to the input.
**Notes**
If the date a user enters falls outside of the min-/max-date range, a `dateDisabled` validation error will show on the form.
+13
View File
@@ -0,0 +1,13 @@
require('../dateparser');
require('../isClass');
require('../../template/datepicker/datepicker.html.js');
require('../../template/datepicker/day.html.js');
require('../../template/datepicker/month.html.js');
require('../../template/datepicker/year.html.js');
require('./datepicker');
var MODULE_NAME = 'ui.bootstrap.module.datepicker';
angular.module(MODULE_NAME, ['ui.bootstrap.datepicker', 'uib/template/datepicker/datepicker.html', 'uib/template/datepicker/day.html', 'uib/template/datepicker/month.html', 'uib/template/datepicker/year.html']);
module.exports = MODULE_NAME;
+2
View File
@@ -0,0 +1,2 @@
require('./datepicker.css');
module.exports = require('./index-nocss.js');
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
<style>
.full button span {
background-color: limegreen;
border-radius: 32px;
color: black;
}
.partially button span {
background-color: orange;
border-radius: 32px;
color: black;
}
</style>
<div ng-controller="DatepickerPopupDemoCtrl">
<pre>Selected date is: <em>{{dt | date:'fullDate' }}</em></pre>
<h4>Popup</h4>
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="dt" is-open="popup1.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup ng-model="dt" is-open="popup2.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open2()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Format: <span class="muted-text">(manual alternate <em>{{altInputFormats[0]}}</em>)</span></label> <select class="form-control" ng-model="format" ng-options="f for f in formats"><option></option></select>
</div>
</div>
<hr />
<button type="button" class="btn btn-sm btn-info" ng-click="today()">Today</button>
<button type="button" class="btn btn-sm btn-default" ng-click="setDate(2009, 7, 24)">2009-08-24</button>
<button type="button" class="btn btn-sm btn-danger" ng-click="clear()">Clear</button>
<button type="button" class="btn btn-sm btn-default" ng-click="toggleMin()" uib-tooltip="After today restriction">Min date</button>
</div>
+95
View File
@@ -0,0 +1,95 @@
angular.module('ui.bootstrap.demo').controller('DatepickerPopupDemoCtrl', function ($scope) {
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.clear = function() {
$scope.dt = null;
};
$scope.inlineOptions = {
customClass: getDayClass,
minDate: new Date(),
showWeeks: true
};
$scope.dateOptions = {
dateDisabled: disabled,
formatYear: 'yy',
maxDate: new Date(2020, 5, 22),
minDate: new Date(),
startingDay: 1
};
// Disable weekend selection
function disabled(data) {
var date = data.date,
mode = data.mode;
return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
}
$scope.toggleMin = function() {
$scope.inlineOptions.minDate = $scope.inlineOptions.minDate ? null : new Date();
$scope.dateOptions.minDate = $scope.inlineOptions.minDate;
};
$scope.toggleMin();
$scope.open1 = function() {
$scope.popup1.opened = true;
};
$scope.open2 = function() {
$scope.popup2.opened = true;
};
$scope.setDate = function(year, month, day) {
$scope.dt = new Date(year, month, day);
};
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
$scope.format = $scope.formats[0];
$scope.altInputFormats = ['M!/d!/yyyy'];
$scope.popup1 = {
opened: false
};
$scope.popup2 = {
opened: false
};
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
var afterTomorrow = new Date();
afterTomorrow.setDate(tomorrow.getDate() + 1);
$scope.events = [
{
date: tomorrow,
status: 'full'
},
{
date: afterTomorrow,
status: 'partially'
}
];
function getDayClass(data) {
var date = data.date,
mode = data.mode;
if (mode === 'day') {
var dayToCheck = new Date(date).setHours(0,0,0,0);
for (var i = 0; i < $scope.events.length; i++) {
var currentDay = new Date($scope.events[i].date).setHours(0,0,0,0);
if (dayToCheck === currentDay) {
return $scope.events[i].status;
}
}
}
return '';
}
});
+107
View File
@@ -0,0 +1,107 @@
The datepicker popup is meant to be used with an input element. To understand usage of the datepicker, please refer to its documentation [here](https://angular-ui.github.io/bootstrap/#/datepicker).
### uib-datepicker-popup settings
The popup is a wrapper that you can use in an input to toggle a datepicker. To configure the datepicker, use `datepicker-options` as documented in the [inline datepicker](https://angular-ui.github.io/bootstrap/#/datepicker).
* `alt-input-formats`
<small class="badge">$</small>
<small class="badge">C</small>
_(Default: `[]`)_ -
A list of alternate formats acceptable for manual entry.
* `clear-text`
<small class="badge">C</small>
_(Default: `Clear`)_ -
The text to display for the clear button.
* `close-on-date-selection`
<small class="badge">$</small>
<small class="badge">C</small>
_(Default: `true`)_ -
Whether to close calendar when a date is chosen.
* `close-text`
<small class="badge">C</small>
_(Default: `Done`)_ -
The text to display for the close button.
* `current-text`
<small class="badge">C</small>
_(Default: `Today`)_ -
The text to display for the current day button.
* `datepicker-append-to-body`
<small class="badge">$</small>
<small class="badge">C</small>
_(Default: `false`, Config: `appendToBody`)_ -
Append the datepicker popup element to `body`, rather than inserting after `datepicker-popup`.
* `datepicker-options`
<small class="badge">$</small> -
An object with any combination of the datepicker settings (in camelCase) used to configure the wrapped datepicker.
* `datepicker-popup-template-url`
<small class="badge">C</small>
_(Default: `uib/template/datepickerPopup/popup.html`)_ -
Add the ability to override the template used on the component.
* `datepicker-template-url`
<small class="badge">C</small>
_(Default: `uib/template/datepicker/datepicker.html`)_ -
Add the ability to override the template used on the component (inner uib-datepicker).
* `is-open`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `false`)_ -
Whether or not to show the datepicker.
* `ng-model`
<small class="badge">$</small>
<i class="glyphicon glyphicon-eye-open"></i> -
The date object. Must be a Javascript `Date` object. You may use the `uibDateParser` service to assist in string-to-object conversion.
* `on-open-focus`
<small class="badge">$</small>
<small class="badge">C</small>
_(Default: `true`)_ -
Whether or not to focus the datepicker popup upon opening.
* `show-button-bar`
<small class="badge">$</small>
<small class="badge">C</small>
_(Default: `true`)_ -
Whether or not to display a button bar underneath the uib-datepicker.
* `type`
<small class="badge">C</small>
_(Default: `text`, Config: `html5Types`)_ -
You can override the input type to be _(date|datetime-local|month)_. That will change the date format of the popup.
* `popup-placement`
<small class="badge">C</small>
_(Default: `auto bottom-left`, Config: 'placement')_ -
Passing in 'auto' separated by a space before the placement will enable auto positioning, e.g: "auto bottom-left". The popup will attempt to position where it fits in the closest scrollable ancestor. Accepts:
* `top` - popup on top, horizontally centered on input element.
* `top-left` - popup on top, left edge aligned with input element left edge.
* `top-right` - popup on top, right edge aligned with input element right edge.
* `bottom` - popup on bottom, horizontally centered on input element.
* `bottom-left` - popup on bottom, left edge aligned with input element left edge.
* `bottom-right` - popup on bottom, right edge aligned with input element right edge.
* `left` - popup on left, vertically centered on input element.
* `left-top` - popup on left, top edge aligned with input element top edge.
* `left-bottom` - popup on left, bottom edge aligned with input element bottom edge.
* `right` - popup on right, vertically centered on input element.
* `right-top` - popup on right, top edge aligned with input element top edge.
* `right-bottom` - popup on right, bottom edge aligned with input element bottom edge.
* `uib-datepicker-popup`
<small class="badge">C</small>
_(Default: `yyyy-MM-dd`, Config: `datepickerConfig`)_ -
The format for displayed dates. This string can take string literals by surrounding the value with single quotes, i.e. `yyyy-MM-dd h 'o\'clock'`.
**Notes**
If using this directive on input type date, a native browser datepicker could also appear.
+10
View File
@@ -0,0 +1,10 @@
require('../datepicker/index-nocss.js');
require('../position/index-nocss.js');
require('../../template/datepickerPopup/popup.html.js');
require('./popup.js');
var MODULE_NAME = 'ui.bootstrap.module.datepickerPopup';
angular.module(MODULE_NAME, ['ui.bootstrap.datepickerPopup', 'uib/template/datepickerPopup/popup.html', 'ui.bootstrap.module.datepicker']);
module.exports = MODULE_NAME;
+4
View File
@@ -0,0 +1,4 @@
require('../datepicker/datepicker.css');
require('../position/position.css');
require('./popup.css');
module.exports = require('./index-nocss.js');
+9
View File
@@ -0,0 +1,9 @@
.uib-datepicker-popup.dropdown-menu {
display: block;
float: none;
margin: 0;
}
.uib-button-bar {
padding: 10px 9px 2px;
}
+466
View File
@@ -0,0 +1,466 @@
angular.module('ui.bootstrap.datepickerPopup', ['ui.bootstrap.datepicker', 'ui.bootstrap.position'])
.value('$datepickerPopupLiteralWarning', true)
.constant('uibDatepickerPopupConfig', {
altInputFormats: [],
appendToBody: false,
clearText: 'Clear',
closeOnDateSelection: true,
closeText: 'Done',
currentText: 'Today',
datepickerPopup: 'yyyy-MM-dd',
datepickerPopupTemplateUrl: 'uib/template/datepickerPopup/popup.html',
datepickerTemplateUrl: 'uib/template/datepicker/datepicker.html',
html5Types: {
date: 'yyyy-MM-dd',
'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
'month': 'yyyy-MM'
},
onOpenFocus: true,
showButtonBar: true,
placement: 'auto bottom-left'
})
.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',
function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {
var cache = {},
isHtml5DateInput = false;
var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [];
this.init = function(_ngModel_) {
ngModel = _ngModel_;
ngModelOptions = extractOptions(ngModel);
closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
$scope.$parent.$eval($attrs.closeOnDateSelection) :
datepickerPopupConfig.closeOnDateSelection;
appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?
$scope.$parent.$eval($attrs.datepickerAppendToBody) :
datepickerPopupConfig.appendToBody;
onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?
$scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?
$attrs.datepickerPopupTemplateUrl :
datepickerPopupConfig.datepickerPopupTemplateUrl;
datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?
$attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
altInputFormats = angular.isDefined($attrs.altInputFormats) ?
$scope.$parent.$eval($attrs.altInputFormats) :
datepickerPopupConfig.altInputFormats;
$scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?
$scope.$parent.$eval($attrs.showButtonBar) :
datepickerPopupConfig.showButtonBar;
if (datepickerPopupConfig.html5Types[$attrs.type]) {
dateFormat = datepickerPopupConfig.html5Types[$attrs.type];
isHtml5DateInput = true;
} else {
dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
$attrs.$observe('uibDatepickerPopup', function(value, oldValue) {
var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
// Invalidate the $modelValue to ensure that formatters re-run
// FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
if (newDateFormat !== dateFormat) {
dateFormat = newDateFormat;
ngModel.$modelValue = null;
if (!dateFormat) {
throw new Error('uibDatepickerPopup must have a date format specified.');
}
}
});
}
if (!dateFormat) {
throw new Error('uibDatepickerPopup must have a date format specified.');
}
if (isHtml5DateInput && $attrs.uibDatepickerPopup) {
throw new Error('HTML5 date input types do not support custom formats.');
}
// popup element used to display calendar
popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');
popupEl.attr({
'ng-model': 'date',
'ng-change': 'dateSelection(date)',
'template-url': datepickerPopupTemplateUrl
});
// datepicker element
datepickerEl = angular.element(popupEl.children()[0]);
datepickerEl.attr('template-url', datepickerTemplateUrl);
if (!$scope.datepickerOptions) {
$scope.datepickerOptions = {};
}
if (isHtml5DateInput) {
if ($attrs.type === 'month') {
$scope.datepickerOptions.datepickerMode = 'month';
$scope.datepickerOptions.minMode = 'month';
}
}
datepickerEl.attr('datepicker-options', 'datepickerOptions');
if (!isHtml5DateInput) {
// Internal API to maintain the correct ng-invalid-[key] class
ngModel.$$parserName = 'date';
ngModel.$validators.date = validator;
ngModel.$parsers.unshift(parseDate);
ngModel.$formatters.push(function(value) {
if (ngModel.$isEmpty(value)) {
$scope.date = value;
return value;
}
if (angular.isNumber(value)) {
value = new Date(value);
}
$scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));
return dateParser.filter($scope.date, dateFormat);
});
} else {
ngModel.$formatters.push(function(value) {
$scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));
return value;
});
}
// Detect changes in the view from the text box
ngModel.$viewChangeListeners.push(function() {
$scope.date = parseDateString(ngModel.$viewValue);
});
$element.on('keydown', inputKeydownBind);
$popup = $compile(popupEl)($scope);
// Prevent jQuery cache memory leak (template is now redundant after linking)
popupEl.remove();
if (appendToBody) {
$document.find('body').append($popup);
} else {
$element.after($popup);
}
$scope.$on('$destroy', function() {
if ($scope.isOpen === true) {
if (!$rootScope.$$phase) {
$scope.$apply(function() {
$scope.isOpen = false;
});
}
}
$popup.remove();
$element.off('keydown', inputKeydownBind);
$document.off('click', documentClickBind);
if (scrollParentEl) {
scrollParentEl.off('scroll', positionPopup);
}
angular.element($window).off('resize', positionPopup);
//Clear all watch listeners on destroy
while (watchListeners.length) {
watchListeners.shift()();
}
});
};
$scope.getText = function(key) {
return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
};
$scope.isDisabled = function(date) {
if (date === 'today') {
date = dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));
}
var dates = {};
angular.forEach(['minDate', 'maxDate'], function(key) {
if (!$scope.datepickerOptions[key]) {
dates[key] = null;
} else if (angular.isDate($scope.datepickerOptions[key])) {
dates[key] = new Date($scope.datepickerOptions[key]);
} else {
if ($datepickerPopupLiteralWarning) {
$log.warn('Literal date support has been deprecated, please switch to date object usage');
}
dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));
}
});
return $scope.datepickerOptions &&
dates.minDate && $scope.compare(date, dates.minDate) < 0 ||
dates.maxDate && $scope.compare(date, dates.maxDate) > 0;
};
$scope.compare = function(date1, date2) {
return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
};
// Inner change
$scope.dateSelection = function(dt) {
$scope.date = dt;
var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
$element.val(date);
ngModel.$setViewValue(date);
if (closeOnDateSelection) {
$scope.isOpen = false;
$element[0].focus();
}
};
$scope.keydown = function(evt) {
if (evt.which === 27) {
evt.stopPropagation();
$scope.isOpen = false;
$element[0].focus();
}
};
$scope.select = function(date, evt) {
evt.stopPropagation();
if (date === 'today') {
var today = new Date();
if (angular.isDate($scope.date)) {
date = new Date($scope.date);
date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
} else {
date = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));
date.setHours(0, 0, 0, 0);
}
}
$scope.dateSelection(date);
};
$scope.close = function(evt) {
evt.stopPropagation();
$scope.isOpen = false;
$element[0].focus();
};
$scope.disabled = angular.isDefined($attrs.disabled) || false;
if ($attrs.ngDisabled) {
watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) {
$scope.disabled = disabled;
}));
}
$scope.$watch('isOpen', function(value) {
if (value) {
if (!$scope.disabled) {
$timeout(function() {
positionPopup();
if (onOpenFocus) {
$scope.$broadcast('uib:datepicker.focus');
}
$document.on('click', documentClickBind);
var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
if (appendToBody || $position.parsePlacement(placement)[2]) {
scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
if (scrollParentEl) {
scrollParentEl.on('scroll', positionPopup);
}
} else {
scrollParentEl = null;
}
angular.element($window).on('resize', positionPopup);
}, 0, false);
} else {
$scope.isOpen = false;
}
} else {
$document.off('click', documentClickBind);
if (scrollParentEl) {
scrollParentEl.off('scroll', positionPopup);
}
angular.element($window).off('resize', positionPopup);
}
});
function cameltoDash(string) {
return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });
}
function parseDateString(viewValue) {
var date = dateParser.parse(viewValue, dateFormat, $scope.date);
if (isNaN(date)) {
for (var i = 0; i < altInputFormats.length; i++) {
date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);
if (!isNaN(date)) {
return date;
}
}
}
return date;
}
function parseDate(viewValue) {
if (angular.isNumber(viewValue)) {
// presumably timestamp to date object
viewValue = new Date(viewValue);
}
if (!viewValue) {
return null;
}
if (angular.isDate(viewValue) && !isNaN(viewValue)) {
return viewValue;
}
if (angular.isString(viewValue)) {
var date = parseDateString(viewValue);
if (!isNaN(date)) {
return dateParser.toTimezone(date, ngModelOptions.getOption('timezone'));
}
}
return ngModelOptions.getOption('allowInvalid') ? viewValue : undefined;
}
function validator(modelValue, viewValue) {
var value = modelValue || viewValue;
if (!$attrs.ngRequired && !value) {
return true;
}
if (angular.isNumber(value)) {
value = new Date(value);
}
if (!value) {
return true;
}
if (angular.isDate(value) && !isNaN(value)) {
return true;
}
if (angular.isString(value)) {
return !isNaN(parseDateString(value));
}
return false;
}
function documentClickBind(event) {
if (!$scope.isOpen && $scope.disabled) {
return;
}
var popup = $popup[0];
var dpContainsTarget = $element[0].contains(event.target);
// The popup node may not be an element node
// In some browsers (IE) only element nodes have the 'contains' function
var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
$scope.$apply(function() {
$scope.isOpen = false;
});
}
}
function inputKeydownBind(evt) {
if (evt.which === 27 && $scope.isOpen) {
evt.preventDefault();
evt.stopPropagation();
$scope.$apply(function() {
$scope.isOpen = false;
});
$element[0].focus();
} else if (evt.which === 40 && !$scope.isOpen) {
evt.preventDefault();
evt.stopPropagation();
$scope.$apply(function() {
$scope.isOpen = true;
});
}
}
function positionPopup() {
if ($scope.isOpen) {
var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));
var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
var position = $position.positionElements($element, dpElement, placement, appendToBody);
dpElement.css({top: position.top + 'px', left: position.left + 'px'});
if (dpElement.hasClass('uib-position-measure')) {
dpElement.removeClass('uib-position-measure');
}
}
}
function extractOptions(ngModelCtrl) {
var ngModelOptions;
if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
// guarantee a value
ngModelOptions = angular.isObject(ngModelCtrl.$options) ?
ngModelCtrl.$options :
{
timezone: null
};
// mimic 1.6+ api
ngModelOptions.getOption = function (key) {
return ngModelOptions[key];
};
} else { // in angular >=1.6 $options is always present
ngModelOptions = ngModelCtrl.$options;
}
return ngModelOptions;
}
$scope.$on('uib:datepicker.mode', function() {
$timeout(positionPopup, 0, false);
});
}])
.directive('uibDatepickerPopup', function() {
return {
require: ['ngModel', 'uibDatepickerPopup'],
controller: 'UibDatepickerPopupController',
scope: {
datepickerOptions: '=?',
isOpen: '=?',
currentText: '@',
clearText: '@',
closeText: '@'
},
link: function(scope, element, attrs, ctrls) {
var ngModel = ctrls[0],
ctrl = ctrls[1];
ctrl.init(ngModel);
}
};
})
.directive('uibDatepickerPopupWrap', function() {
return {
restrict: 'A',
transclude: true,
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html';
}
};
});
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
angular.module('ui.bootstrap.debounce', [])
/**
* A helper, internal service that debounces a function
*/
.factory('$$debounce', ['$timeout', function($timeout) {
return function(callback, debounceTime) {
var timeoutPromise;
return function() {
var self = this;
var args = Array.prototype.slice.call(arguments);
if (timeoutPromise) {
$timeout.cancel(timeoutPromise);
}
timeoutPromise = $timeout(function() {
callback.apply(self, args);
}, debounceTime);
};
};
}]);
+7
View File
@@ -0,0 +1,7 @@
require('./debounce');
var MODULE_NAME = 'ui.bootstrap.module.debounce';
angular.module(MODULE_NAME, ['ui.bootstrap.debounce']);
module.exports = MODULE_NAME;
+48
View File
@@ -0,0 +1,48 @@
describe('$$debounce', function() {
var $$debounce, $timeout, debouncedFunction, i, args;
beforeEach(module('ui.bootstrap.debounce'));
beforeEach(inject(function(_$$debounce_, _$timeout_) {
$$debounce = _$$debounce_;
$timeout = _$timeout_;
i = 0;
debouncedFunction = $$debounce(function() {
args = Array.prototype.slice.call(arguments);
i++;
}, 100);
}));
it('should function like a $timeout when called once during timeout', function() {
debouncedFunction();
$timeout.flush(50);
expect(i).toBe(0);
$timeout.flush(50);
expect(i).toBe(1);
});
it('should only execute 100ms after last call when called twice', function() {
debouncedFunction();
$timeout.flush(50);
expect(i).toBe(0);
debouncedFunction();
$timeout.flush(50);
expect(i).toBe(0);
$timeout.flush(50);
expect(i).toBe(1);
});
it('should properly pass arguments to debounced function', function() {
debouncedFunction(1, 2, 3);
$timeout.flush(100);
expect(args).toEqual([1, 2, 3]);
});
});
-97
View File
@@ -1,97 +0,0 @@
# $dialogProvider <small>(service in ui.bootstrap)</small>
## Description
Used for configuring global options for dialogs.
### Methods
#### `options(opts)`
Sets the default global options for your application. Options can be overridden when opening dialogs. Available options are:
* `backdrop`: a boolean value indicating whether a backdrop should be used or not, defaults to true
* `dialogClass`: the css class for the modal div, defaults to 'modal'
* `backdropClass`: the css class for the backdrop, defaults to 'modal-backdrop'
* `transitionClass`: the css class that applies transitions to the modal and backdrop, defaults to 'fade'
* `triggerClass`: the css class that triggers the transitions, defaults to 'in'
* `dialogOpenClass`: the css class that is added to body when dialog is opened, defaults to 'modal-open'
* `resolve`: members that will be resolved and passed to the controller as locals
* `controller`: the controller to associate with the included partial view
* `backdropFade`: a boolean value indicating whether the backdrop should fade in and out using a CSS transition, defaults to false
* `dialogFade`: a boolean value indicating whether the modal should fade in and out using a CSS transition, defaults to false
* `keyboard`: indicates whether the dialog should be closable by hitting the ESC key, defaults to true
* `backdropClick`: indicates whether the dialog should be closable by clicking the backdrop area, defaults to true
Example:
var app = angular.module('App', ['ui.bootstrap.dialog'] , function($dialogProvider){
$dialogProvider.options({backdropClick: false, modalFade: true});
});
# $dialog service
## Description
Allows you to open dialogs from within your controller.
### Methods
#### `dialog([templateUrl[, controller]])`
Creates a new dialog, optionally setting the `templateUrl`, and `controller` options.
Example:
app.controller('MainCtrl', function($dialog, $scope) {
$scope.openItemEditor = function(item){
var d = $dialog.dialog({modalFade: false, resolve: {item: function(){ return angular.copy(item); } }});
d.open('dialogs/item-editor.html', 'EditItemController');
};
});
// note that the resolved item as well as the dialog are injected in the dialog's controller
app.controller('EditItemController', ['$scope', 'dialog', 'item', function($scope, dialog, item){
$scope.item = item;
$scope.submit = function(){
dialog.close('ok');
};
}]);
#### `messageBox(title, message, buttons)`
Opens a message box with the specified `title`, `message` and a series of `buttons` can be provided, every button can specify:
* `label`: the label of the button
* `result`: the result used to invoke the close method of the dialog
* `cssClass`: optional, the CSS class (e.g. btn-primary) to apply to the button
Example:
app.controller('MainCtrl', function($dialog, $scope) {
$scope.deleteItem = function(item){
var msgbox = $dialog.messageBox('Delete Item', 'Are you sure?', [{label:'Yes, I\'m sure', result: 'yes'},{label:'Nope', result: 'no'}]);
msgbox.open().then(function(result){
if(result === 'yes') {deleteItem(item);}
});
};
});
## Dialog class
The dialog object returned by the `$dialog` service methods `open` and `message`.
### Methods
#### `open`
(Re)Opens the dialog and returns a promise.
#### `close([result])`
Closes the dialog. Optionally a result can be specified. The result is used to resolve the promise returned by the `open` method.
#### `isOpen`
Returns true if the dialog is shown, else returns false.
-289
View File
@@ -1,289 +0,0 @@
// The `$dialogProvider` can be used to configure global defaults for your
// `$dialog` service.
var dialogModule = angular.module('ui.bootstrap.dialog', ['ui.bootstrap.transition']);
dialogModule.controller('MessageBoxController', ['$scope', 'dialog', 'model', function($scope, dialog, model){
$scope.title = model.title;
$scope.message = model.message;
$scope.buttons = model.buttons;
$scope.close = function(res){
dialog.close(res);
};
}]);
dialogModule.provider("$dialog", function(){
// The default options for all dialogs.
var defaults = {
backdrop: true,
dialogClass: 'modal',
backdropClass: 'modal-backdrop',
transitionClass: 'fade',
triggerClass: 'in',
dialogOpenClass: 'modal-open',
resolve:{},
backdropFade: false,
dialogFade:false,
keyboard: true, // close with esc key
backdropClick: true // only in conjunction with backdrop=true
/* other options: template, templateUrl, controller */
};
var globalOptions = {};
var activeBackdrops = {value : 0};
// The `options({})` allows global configuration of all dialogs in the application.
//
// var app = angular.module('App', ['ui.bootstrap.dialog'], function($dialogProvider){
// // don't close dialog when backdrop is clicked by default
// $dialogProvider.options({backdropClick: false});
// });
this.options = function(value){
globalOptions = value;
};
// Returns the actual `$dialog` service that is injected in controllers
this.$get = ["$http", "$document", "$compile", "$rootScope", "$controller", "$templateCache", "$q", "$transition", "$injector",
function ($http, $document, $compile, $rootScope, $controller, $templateCache, $q, $transition, $injector) {
var body = $document.find('body');
function createElement(clazz) {
var el = angular.element("<div>");
el.addClass(clazz);
return el;
}
// The `Dialog` class represents a modal dialog. The dialog class can be invoked by providing an options object
// containing at lest template or templateUrl and controller:
//
// var d = new Dialog({templateUrl: 'foo.html', controller: 'BarController'});
//
// Dialogs can also be created using templateUrl and controller as distinct arguments:
//
// var d = new Dialog('path/to/dialog.html', MyDialogController);
function Dialog(opts) {
var self = this, options = this.options = angular.extend({}, defaults, globalOptions, opts);
this._open = false;
this.backdropEl = createElement(options.backdropClass);
if(options.backdropFade){
this.backdropEl.addClass(options.transitionClass);
this.backdropEl.removeClass(options.triggerClass);
}
this.modalEl = createElement(options.dialogClass);
if(options.dialogFade){
this.modalEl.addClass(options.transitionClass);
this.modalEl.removeClass(options.triggerClass);
}
this.handledEscapeKey = function(e) {
if (e.which === 27) {
self.close();
e.preventDefault();
self.$scope.$apply();
}
};
this.handleBackDropClick = function(e) {
self.close();
e.preventDefault();
self.$scope.$apply();
};
this.handleLocationChange = function() {
self.close();
};
}
// The `isOpen()` method returns wether the dialog is currently visible.
Dialog.prototype.isOpen = function(){
return this._open;
};
// The `open(templateUrl, controller)` method opens the dialog.
// Use the `templateUrl` and `controller` arguments if specifying them at dialog creation time is not desired.
Dialog.prototype.open = function(templateUrl, controller){
var self = this, options = this.options;
if(templateUrl){
options.templateUrl = templateUrl;
}
if(controller){
options.controller = controller;
}
if(!(options.template || options.templateUrl)) {
throw new Error('Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.');
}
this._loadResolves().then(function(locals) {
var $scope = locals.$scope = self.$scope = locals.$scope ? locals.$scope : $rootScope.$new();
self.modalEl.html(locals.$template);
if (self.options.controller) {
var ctrl = $controller(self.options.controller, locals);
self.modalEl.children().data('ngControllerController', ctrl);
}
$compile(self.modalEl)($scope);
self._addElementsToDom();
body.addClass(self.options.dialogOpenClass);
// trigger tranisitions
setTimeout(function(){
if(self.options.dialogFade){ self.modalEl.addClass(self.options.triggerClass); }
if(self.options.backdropFade){ self.backdropEl.addClass(self.options.triggerClass); }
});
self._bindEvents();
});
this.deferred = $q.defer();
return this.deferred.promise;
};
// closes the dialog and resolves the promise returned by the `open` method with the specified result.
Dialog.prototype.close = function(result){
var self = this;
var fadingElements = this._getFadingElements();
body.removeClass(self.options.dialogOpenClass);
if(fadingElements.length > 0){
for (var i = fadingElements.length - 1; i >= 0; i--) {
$transition(fadingElements[i], removeTriggerClass).then(onCloseComplete);
}
return;
}
this._onCloseComplete(result);
function removeTriggerClass(el){
el.removeClass(self.options.triggerClass);
}
function onCloseComplete(){
if(self._open){
self._onCloseComplete(result);
}
}
};
Dialog.prototype._getFadingElements = function(){
var elements = [];
if(this.options.dialogFade){
elements.push(this.modalEl);
}
if(this.options.backdropFade){
elements.push(this.backdropEl);
}
return elements;
};
Dialog.prototype._bindEvents = function() {
if(this.options.keyboard){ body.bind('keydown', this.handledEscapeKey); }
if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.bind('click', this.handleBackDropClick); }
this.$scope.$on('$locationChangeSuccess', this.handleLocationChange);
};
Dialog.prototype._unbindEvents = function() {
if(this.options.keyboard){ body.unbind('keydown', this.handledEscapeKey); }
if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.unbind('click', this.handleBackDropClick); }
};
Dialog.prototype._onCloseComplete = function(result) {
this._removeElementsFromDom();
this._unbindEvents();
this.deferred.resolve(result);
};
Dialog.prototype._addElementsToDom = function(){
body.append(this.modalEl);
if(this.options.backdrop) {
if (activeBackdrops.value === 0) {
body.append(this.backdropEl);
}
activeBackdrops.value++;
}
this._open = true;
};
Dialog.prototype._removeElementsFromDom = function(){
this.modalEl.remove();
if(this.options.backdrop) {
activeBackdrops.value--;
if (activeBackdrops.value === 0) {
this.backdropEl.remove();
}
}
this._open = false;
};
// Loads all `options.resolve` members to be used as locals for the controller associated with the dialog.
Dialog.prototype._loadResolves = function(){
var values = [], keys = [], templatePromise, self = this;
if (this.options.template) {
templatePromise = $q.when(this.options.template);
} else if (this.options.templateUrl) {
templatePromise = $http.get(this.options.templateUrl, {cache:$templateCache})
.then(function(response) { return response.data; });
}
angular.forEach(this.options.resolve || [], function(value, key) {
keys.push(key);
values.push(angular.isString(value) ? $injector.get(value) : $injector.invoke(value));
});
keys.push('$template');
values.push(templatePromise);
return $q.all(values).then(function(values) {
var locals = {};
angular.forEach(values, function(value, index) {
locals[keys[index]] = value;
});
locals.dialog = self;
return locals;
});
};
// The actual `$dialog` service that is injected in controllers.
return {
// Creates a new `Dialog` with the specified options.
dialog: function(opts){
return new Dialog(opts);
},
// creates a new `Dialog` tied to the default message box template and controller.
//
// Arguments `title` and `message` are rendered in the modal header and body sections respectively.
// The `buttons` array holds an object with the following members for each button to include in the
// modal footer section:
//
// * `result`: the result to pass to the `close` method of the dialog when the button is clicked
// * `label`: the label of the button
// * `cssClass`: additional css class(es) to apply to the button for styling
messageBox: function(title, message, buttons){
return new Dialog({templateUrl: 'template/dialog/message.html', controller: 'MessageBoxController', resolve:
{model: function() {
return {
title: title,
message: message,
buttons: buttons
};
}
}});
}
};
}];
});
-19
View File
@@ -1,19 +0,0 @@
<div ng-controller="DialogDemoCtrl">
<div class="row-fluid">
<div class="span6">
<label class="checkbox"><input type=checkbox ng-model="opts.backdrop">Show backdrop</label>
<label class="checkbox"><input type=checkbox ng-model="opts.dialogFade">Fade modal dialog </label>
<label class="checkbox"><input type=checkbox ng-disabled="!opts.backdrop" ng-model="opts.backdropFade">Fade Backdrop</label>
<hr>
<label class="checkbox"><input type=checkbox ng-model="opts.keyboard">Close on Escape</label>
<label class="checkbox"><input type=checkbox ng-disabled="!opts.backdrop" ng-model="opts.backdropClick">Close on backdrop click</label>
</div>
<div class="span6">
<p>Change options at will and press the open dialog button below!</p>
<p><button class="btn btn-primary" ng-click="openDialog()">Open Dialog</button></p>
<p>Alternatively open a simple message box:</p>
<p><button class="btn btn-primary" ng-click="openMessageBox()">Open Message Box</button></p>
</div>
</div>
</div>
-50
View File
@@ -1,50 +0,0 @@
function DialogDemoCtrl($scope, $dialog){
// Inlined template for demo
var t = '<div class="modal-header">'+
'<h1>This is the title</h1>'+
'</div>'+
'<div class="modal-body">'+
'<p>Enter a value to pass to <code>close</code> as the result: <input ng-model="result" /></p>'+
'</div>'+
'<div class="modal-footer">'+
'<button ng-click="close(result)" class="btn btn-primary" >Close</button>'+
'</div>';
$scope.opts = {
backdrop: true,
keyboard: true,
backdropClick: true,
template: t, // OR: templateUrl: 'path/to/view.html',
controller: 'TestDialogController'
};
$scope.openDialog = function(){
var d = $dialog.dialog($scope.opts);
d.open().then(function(result){
if(result)
{
alert('dialog closed with result: ' + result);
}
});
};
$scope.openMessageBox = function(){
var title = 'This is a message box';
var msg = 'This is the content of the message box';
var btns = [{result:'cancel', label: 'Cancel'}, {result:'ok', label: 'OK', cssClass: 'btn-primary'}];
$dialog.messageBox(title, msg, btns)
.open()
.then(function(result){
alert('dialog closed with result: ' + result);
});
};
}
// the dialog is injected in the specified controller
function TestDialogController($scope, dialog){
$scope.close = function(result){
dialog.close(result);
};
}

Some files were not shown because too many files have changed in this diff Show More