diff --git a/CHANGELOG.md b/CHANGELOG.md
index d07d955933..5d2462125e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,107 @@
+
+# [2.0.0-beta.6](https://github.com/driftyco/ionic/compare/v2.0.0-beta.5...v2.0.0-beta.6) (2016-04-21)
+
+
+### Bug Fixes
+
+* **nav:** tabs should not dereg child navs ([f3ddb0b](https://github.com/driftyco/ionic/commit/f3ddb0b)), closes [#6267](https://github.com/driftyco/ionic/issues/6267)
+* **sass:** fix sass errors ([219059c](https://github.com/driftyco/ionic/commit/219059c))
+* **toast:** create unique toast id ([e07f0ae](https://github.com/driftyco/ionic/commit/e07f0ae))
+* **toast:** remove default duration, allow close button click when bd disabled ([d6589e1](https://github.com/driftyco/ionic/commit/d6589e1))
+* **toast:** remove unused options ([f9ea2d8](https://github.com/driftyco/ionic/commit/f9ea2d8))
+
+### Features
+
+* **toast:** add toast component ([3fb79cf](https://github.com/driftyco/ionic/commit/3fb79cf))
+* **toast:** display the toast even on page change unless `dismissOnPageChange` is passed ([0264532](https://github.com/driftyco/ionic/commit/0264532)), closes [#5582](https://github.com/driftyco/ionic/issues/5582)
+
+
+
+
+# [2.0.0-beta.5](https://github.com/driftyco/ionic/compare/v2.0.0-beta.4...v2.0.0-beta.5) (2016-04-20)
+
+
+### Bug Fixes
+
+* **alert:** remove justify content from buttons in an alert ([9412a7c](https://github.com/driftyco/ionic/commit/9412a7c))
+* **app:** add iOS status bar padding to each mode ([5a1c441](https://github.com/driftyco/ionic/commit/5a1c441)), closes [#5924](https://github.com/driftyco/ionic/issues/5924)
+* **button:** add a category to buttons so they won't get the button styles ([35dd0ed](https://github.com/driftyco/ionic/commit/35dd0ed)), closes [#6237](https://github.com/driftyco/ionic/issues/6237)
+* **button:** buttons don't get activated when ion-label contains exotic elements ([0521ce2](https://github.com/driftyco/ionic/commit/0521ce2))
+* **button:** remove classes from buttons with categories ([5f8edc2](https://github.com/driftyco/ionic/commit/5f8edc2))
+* **checkbox:** add `type="button"` to button tag ([7583ebf](https://github.com/driftyco/ionic/commit/7583ebf))
+* **content:** fix padding/margin attributes so all work on scroll-content ([9020d52](https://github.com/driftyco/ionic/commit/9020d52))
+* **cordova:** add status bar padding for content for all modes ([f45ddf9](https://github.com/driftyco/ionic/commit/f45ddf9)), closes [#5934](https://github.com/driftyco/ionic/issues/5934)
+* **cordova:** only target navbar section when it has the statusbar-padding ([422c983](https://github.com/driftyco/ionic/commit/422c983))
+* **focus:** improve input focus control ([e27452b](https://github.com/driftyco/ionic/commit/e27452b)), closes [#5536](https://github.com/driftyco/ionic/issues/5536)
+* **input:** add 'type="button"' to button tag ([f17f517](https://github.com/driftyco/ionic/commit/f17f517))
+* **input:** blur when tapping outside input on iOS ([f9b46c2](https://github.com/driftyco/ionic/commit/f9b46c2)), closes [#5020](https://github.com/driftyco/ionic/issues/5020)
+* **input:** move nested function outside of if statment so as to fix issue related to strict ([c8e58e5](https://github.com/driftyco/ionic/commit/c8e58e5))
+* **keyboard:** remove content padding after input blur ([e21c4d5](https://github.com/driftyco/ionic/commit/e21c4d5)), closes [#5800](https://github.com/driftyco/ionic/issues/5800)
+* **label:** remove flex-basis to fix floating/stacked labels on iOS/Safari ([cd62a4c](https://github.com/driftyco/ionic/commit/cd62a4c)), closes [#6109](https://github.com/driftyco/ionic/issues/6109)
+* **loading:** present loading from root nav controller ([f972908](https://github.com/driftyco/ionic/commit/f972908)), closes [#6121](https://github.com/driftyco/ionic/issues/6121)
+* **platform:** fire cordova platform.ready using zone ([ba5624b](https://github.com/driftyco/ionic/commit/ba5624b)), closes [#6186](https://github.com/driftyco/ionic/issues/6186)
+* **platform:** run zone after cordova deviceready ([e082bd1](https://github.com/driftyco/ionic/commit/e082bd1)), closes [#6087](https://github.com/driftyco/ionic/issues/6087)
+* **sass:** move the `@at-root` font import to the components file ([8f08de1](https://github.com/driftyco/ionic/commit/8f08de1)), closes [#5931](https://github.com/driftyco/ionic/issues/5931)
+* **searchbar:** only show clear icon when focused on the searchbar ([ecf9302](https://github.com/driftyco/ionic/commit/ecf9302)), closes [#5922](https://github.com/driftyco/ionic/issues/5922)
+* **showHideWhen:** remove hidden attribute on directives and use classes ([5692abe](https://github.com/driftyco/ionic/commit/5692abe)), closes [#5836](https://github.com/driftyco/ionic/issues/5836)
+* **slides:** add id to the slide component to grab the correct pagination ([7263728](https://github.com/driftyco/ionic/commit/7263728)), closes [#5745](https://github.com/driftyco/ionic/issues/5745) [#5508](https://github.com/driftyco/ionic/issues/5508)
+* **tabs:** do not init w/ tab that is hidden or disabled ([8d8cc4c](https://github.com/driftyco/ionic/commit/8d8cc4c)), closes [#6226](https://github.com/driftyco/ionic/issues/6226)
+* **tabs:** remove tabbarIcons and fix windows styling to use tabbarLayout ([81dd1cc](https://github.com/driftyco/ionic/commit/81dd1cc)), closes [#6126](https://github.com/driftyco/ionic/issues/6126)
+* **toolbar:** add border-top when toolbar is positioned to the bottom ([29e6242](https://github.com/driftyco/ionic/commit/29e6242)), closes [#5967](https://github.com/driftyco/ionic/issues/5967)
+* **virtualScroll:** load async data ([16a283e](https://github.com/driftyco/ionic/commit/16a283e)), closes [#6124](https://github.com/driftyco/ionic/issues/6124)
+
+### Features
+
+* **app:** getActiveNav() method ([7777237](https://github.com/driftyco/ionic/commit/7777237))
+* **backbutton:** add hardware back button ([68278b0](https://github.com/driftyco/ionic/commit/68278b0)), closes [#5071](https://github.com/driftyco/ionic/issues/5071)
+* **changeDetection:** detach Tabs when not active ([0c4171e](https://github.com/driftyco/ionic/commit/0c4171e))
+* **changeDetection:** detach ViewControllers when not active ([b282e90](https://github.com/driftyco/ionic/commit/b282e90))
+* **config:** create a method to access the global app injector which contains references the ([17a9e6d](https://github.com/driftyco/ionic/commit/17a9e6d)), closes [#5973](https://github.com/driftyco/ionic/issues/5973)
+* **content:** add scrollToBottom ([bef4a67](https://github.com/driftyco/ionic/commit/bef4a67))
+* **directives:** auto provide IONIC_DIRECTIVES to all components ([0a83f2f](https://github.com/driftyco/ionic/commit/0a83f2f)), closes [#6092](https://github.com/driftyco/ionic/issues/6092)
+* **platform:** add backbutton event ([156fdc3](https://github.com/driftyco/ionic/commit/156fdc3))
+* **platform:** default desktop to use material design ([51032d2](https://github.com/driftyco/ionic/commit/51032d2)), closes [#6003](https://github.com/driftyco/ionic/issues/6003)
+* **select:** fallback to alert interface when more than 6 opts ([1c67b02](https://github.com/driftyco/ionic/commit/1c67b02))
+* **select:** using action-sheet as ion-select interface ([81096f1](https://github.com/driftyco/ionic/commit/81096f1))
+* **slides:** add ability to slide to specific index ([a6091bd](https://github.com/driftyco/ionic/commit/a6091bd))
+* **slides:** add method to get previous index ([a54361c](https://github.com/driftyco/ionic/commit/a54361c))
+* **statusbarPadding:** add statusbar-padding css to content ([98c2aab](https://github.com/driftyco/ionic/commit/98c2aab))
+* **statusbarPadding:** add statusbar-padding css to toolbars ([44403d1](https://github.com/driftyco/ionic/commit/44403d1))
+* **tabs:** enabled and show inputs ([1b085e3](https://github.com/driftyco/ionic/commit/1b085e3)), closes [#5768](https://github.com/driftyco/ionic/issues/5768)
+* **toggle:** add animation for windows mode toggle ([f841bef](https://github.com/driftyco/ionic/commit/f841bef)), closes [#5981](https://github.com/driftyco/ionic/issues/5981)
+
+### Performance Improvements
+
+* **img:** do not reuse img elements ([b744275](https://github.com/driftyco/ionic/commit/b744275)), closes [#6112](https://github.com/driftyco/ionic/issues/6112)
+
+
+### BREAKING CHANGES
+
+* **tabs:** `tabbarIcons` is officially removed, please use `tabbarLayout` instead. View the [Tabs API docs](http://ionicframework.com/docs/v2/api/components/tabs/Tabs/) for more information.
+* **slides:** The Slides component has been refactored. Many methods and events were
+ renamed.
+
+ The following events have been renamed:
+
+ - `slideChangeStart` has been renamed `willChange`
+ - `change` has been renamed `didChange`
+
+ The following methods have been renamed:
+
+ - `next()` has been renamed to `slideNext()`
+ - `prev()` has been renamed to `slidePrev()`
+ - `getIndex()` has been renamed to `getActiveIndex()`
+ - `getNumSlides()` has been renamed to `length()`
+ - `isAtEnd()` has been renamed to `isEnd()`
+ - `isAtBeginning()` has been renamed to `isBeginning()`
+ - `getSliderWidget()` has been renamed to `getSlider()`
+
+ All methods have been documented in the API docs:
+ http://ionicframework.com/docs/v2/api/components/slides/Slides/
+
+* **platform:** `platform.versions()` no longer accepts an optional parameter for platform name
+and now returns only an object containing all of the platforms and their versions.
+
# [2.0.0-beta.4](https://github.com/driftyco/ionic/compare/v2.0.0-beta.3...v2.0.0-beta.4) (2016-04-07)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1b5e0ba37b..323fecfe18 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,118 +1,115 @@
-### Creating an Issue
+# Contributing
-If you have a question on how something works, or its expected functionality, you might want to visit the [Ionic Forum](http://forum.ionicframework.com/) first.
-
-If you think you have found a bug, or have a new feature idea, please start by making sure it hasn't already been [reported](https://github.com/driftyco/ionic/issues?state=open). You can search through existing issues to see if someone's reported one similar to yours.
-
-Next [create a new issue](https://github.com/driftyco/ionic/issues/new) that thoroughly explains the problem, how to reproduce the issue, and provide any additional information such as code examples and error logs.
-
-### Issue Etiquette Guidelines
-
-Poor attitude, ranting, name-calling, bullying, being a jerk, complaining, or spamming are fruitless and unacceptable. Issues that violate the open source spirit of this community, or any of the guidelines listed here, may result in your Issue being deleted or reposted to our Forum, a better place for debate and discussion. If you wish to contribute, either make your response respectful or do not bother to respond. You’ll find it’s pretty ineffective.
-
-Simply put: be respectful and act like an adult. Critiques are better made on the Forum. If you can’t do that, this isn’t a community for you.
-
-See our [Code of Conduct](./CODE_OF_CONDUCT.md) for more info.
+Thanks for your interest in contributing to the Ionic Framework! :tada:
-### Pull Request Guidelines
+## Contributing Etiquette
-Please use [Commitizen](https://github.com/commitizen/cz-cli#installing-the-command-line-tool) to commit to this repository. This ensures your commits will match our git conventions. It can be installed by running the following command (add sudo if on OSX/Linux):
-
-```
-npm install -g commitizen
-```
-
-Then, when you want to commit, instead of writing `git commit` you will write:
-
-```
-git cz
-```
-
-This will prompt you with some questions.
-
-When in doubt, keep your pull requests small. To give a PR the best chance of getting accepted, do not bundle more than one "feature" or bug fix per PR. Doing so makes it very hard to accept it if one of the fixes has issues.
-
-It's always best to create two smaller PRs than one big one.
-
-### Style
-
-Always use two spaces, no tabs. This goes for any HTML, CSS, or Javascript.
-
-#### Sass Guidelines
-
-##### Sass Linter
-
-Run [Sass Linter](https://github.com/brigade/scss-lint) to ensure the css/sass matches our conventions (requires Ruby)
-
-1. Install the linter: `gem install scss_lint`
-2. Make sure to run the linter at the root of the repository where the `.scss-lint.yml` file is located
-3. For all component Sass files: `scss-lint ionic/**/**/*.scss`
-4. For a specific Sass file: `scss-lint ionic/components/toolbar/toolbar.ios.scss`
+Please see our [Contributor Code of Conduct](./CODE_OF_CONDUCT.md) for information on our rules of conduct.
-##### Variable Naming Conventions
+## Creating an Issue
-The Sass variable should start with the component name:
+If you have a question about using the framework, please ask on the [Ionic Forum](http://forum.ionicframework.com/) or in the [Ionic Worldwide Slack](http://ionicworldwide.herokuapp.com/) group.
-```
-$alert
-$action-sheet
-$badge
-$toolbar
-```
+If you think you have found a bug, or have a new feature idea, please start by making sure it hasn't already been [reported](https://github.com/driftyco/ionic/issues?utf8=%E2%9C%93&q=is%3Aissue). You can search through existing issues to see if there is a similar one reported. Include closed issues as it may have been closed with a solution.
-Then it should use the mode abbreviation (ios, md, wp):
+Next, [create a new issue](https://github.com/driftyco/ionic/issues/new) that thoroughly explains the problem. Please fill out the populated issue form before submitting the issue.
-```
-$alert-md
-$action-sheet-ios
-$badge-md
-$toolbar-wp
-```
-Next should be the css property it is affecting, for example:
+## Creating a Pull Request
-```
-$alert-md-max-width
-$action-sheet-ios-background
-$badge-md-border-radius
-$toolbar-wp-padding
-```
+We appreciate you taking the time to contribute! Before submitting a pull request, we ask that you please [create an issue](#creating-an-issue) that explains the bug or feature request and let us know that you plan on creating a pull request for it. If an issue already exists, please comment on that issue letting us know you would like to submit a pull request for it. This helps us to keep track of the pull request and make sure there isn't duplicated effort.
-If it is affecting a component inside of the top level component, that should come next instead of the css property:
+Looking for an issue to fix? Make sure to look through our issues with the [help wanted](https://github.com/driftyco/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) label!
-```
-$alert-md-title
-$alert-md-sub-title
-$alert-md-message
-$action-sheet-ios-title
-$action-sheet-ios-button
-```
+### Setup
-Followed by the css property of that component:
+1. Fork the repo.
+2. Clone your fork.
+3. Make a branch for your change.
+4. Run `npm install` (make sure you have [node](https://nodejs.org/en/) and [npm](http://blog.npmjs.org/post/85484771375/how-to-install-npm) installed first)
-```
-$alert-md-title-font-size
-$alert-md-sub-title-font-size
-$alert-md-message-padding
-$action-sheet-ios-title-color
-$action-sheet-ios-button-background
-```
-If the variable only applies to a specific state, that should come last (hover, focused, activated, etc):
+### Modifying Components
-```
-$action-sheet-ios-button-background-activated
-$alert-md-input-border-width-focused
-```
+1. Make any changes to the component.
+2. Modify the e2e test in the `test/` directory under the component directory, if possible. If the test does not exist and it is possible to show the change, please create a new test in a directory called `basic/`.
-**Should I use `background` or `bg`?**
-`background`
+#### TypeScript Changes
-**Should I use `background` or `background-color`?**
-`background` so users can override backgrounds in Sass variables using images and etc
+1. If there is a `*.spec.ts` file located in the `test/` folder, update it to include a karma test for your change, if needed. If this file doesn't exist, please notify us.
+2. Run `gulp karma` to make sure all tests are working, regardless if a test was added.
+3. Run `gulp tslint` and fix any linter errors.
-### License
+#### Sass Changes
+
+1. If the css property is something that the user may want to override and it won't break the component layout, it should be given a Sass variable. See our [doc on naming Sass variables](https://docs.google.com/document/d/1OyOyrRE5lpB_9mdkF0HWVQLV97fHma450N8XqE4mjZQ/edit?usp=sharing).
+2. After any changes to the Sass files run the [Sass Linter](https://github.com/brigade/scss-lint), and fix any linter errors:
+ - Requires [Ruby](https://www.ruby-lang.org/en/documentation/installation/). **Skip this step entirely if you are unable to install Ruby.**
+ - Install the linter: `gem install scss_lint`
+ - Make sure to run the linter at the root of the repository.
+ - To check all component Sass files: `scss-lint ionic/**/**/*.scss`
+ - To check a specific Sass file: `scss-lint ionic/components/toolbar/toolbar.ios.scss`
+
+
+#### Viewing Changes
+
+1. Run the gulp watch task for e2e tests: `gulp watch.e2e`
+2. Launch your browser and navigate to `http://localhost:8000/dist/e2e`
+3. From here, navigate to the component you are changing.
+4. Any changes to the e2e tests in the `test/` directory will show here.
+5. If your changes look good, you're ready to [commit](#committing)!
+
+
+#### Adding Documentation
+
+1. To add or modify API Documentation for a component, it should be added/changed in the component's TypeScript (`*.ts`) file, prior to the Class definition. For example, `Badge` looks similar to this:
+
+ ```
+ /**
+ * @name Badge
+ * @module ionic
+ * @description
+ * Badges are simple components in Ionic containing numbers or text.
+ *
+ * @see {@link /docs/v2/components/#badges Badges Component Docs}
+ * @demo /docs/v2/demos/badge/
+ **/
+ ```
+
+ where `@name` is the Class name, `@description` is the description displayed on the documentation page, `@see` links to any related pages, and `@demo` links to the API demo located in the `demos` folder.
+2. In order to run API documentation locally, you will need to clone the `ionic-site` repo as a sibling to the `ionic` repo and then run it: https://github.com/driftyco/ionic-site#local-build
+3. Then, run `gulp docs` in the `ionic` repo every time you make a change and the site will update.
+4. If the change affects the component documentation, create an issue on the `ionic-site` repo: https://github.com/driftyco/ionic-site/issues
+
+
+#### Adding Demos
+
+1. Create or modify the demo in the `demos/` folder.
+2. If it is new, link to the demo in the component's TypeScript (`*.ts`) file (under `ionic/components`) by adding a link to it in the documentation using `@demo`, for example:
+
+ ```
+ /**
+ * @name Badge
+ *
+ * ...
+ *
+ * @demo /docs/v2/demos/badge/
+ **/
+ ```
+3. Run `gulp watch.demos` to watch for changes to the demo
+4. Navigate to `http://localhost:8000/dist/demos/` and then to your component's demo to view it.
+5. If the change affects the component demos, create an issue on the `ionic-site` repo: https://github.com/driftyco/ionic-site/issues
+
+### Committing
+
+1. Install [Commitizen](https://github.com/commitizen/cz-cli#installing-the-command-line-tool) (add sudo if on OSX/Linux): `npm install -g commitizen`
+2. Use commitizen to commit instead of `git commit`: `git cz`
+3. This will prompt you with questions and commit when you are finished.
+4. Submit the Pull Request!
+
+
+## License
By contributing your code to the driftyco/ionic GitHub Repository, you agree to license your contribution under the MIT license.
diff --git a/demos/blur/bg.jpg b/demos/blur/bg.jpg
deleted file mode 100644
index c3298fcb99..0000000000
Binary files a/demos/blur/bg.jpg and /dev/null differ
diff --git a/demos/blur/index.ts b/demos/blur/index.ts
deleted file mode 100644
index 64f6d23af8..0000000000
--- a/demos/blur/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import {App} from 'ionic-angular';
-
-@App({
- templateUrl: 'main.html'
-})
-class ApiDemoApp {}
diff --git a/demos/blur/main.html b/demos/blur/main.html
deleted file mode 100644
index d54b9c1a36..0000000000
--- a/demos/blur/main.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- Blur
-
-
-
-
-
-
- Card
-
-
- This card will blur the content behind it.
-
-
-
In this example we're using the showWhen directive to decide whether to show an icon based on the platform.
-
+
+
+
+
+ <ion-icon name="logo-apple" showWhen="ios"></ion-icon>
+
+
+
+
-
+ <ion-icon name="logo-android" showWhen="android"></ion-icon>
+
+
+
+
+
+
+
+ <ion-icon name="logo-windows" showWhen="windows"></ion-icon>
@@ -20,7 +36,10 @@
.show-when-demo ion-col {
background: #f8f8f8;
border: 1px solid #ddd;
- margin: 5px;
+ margin: 1%;
+ max-width: 48%;
+ flex: 0 0 48%;
+ min-height: 120px;
}
.show-when-demo code {
@@ -28,6 +47,6 @@
}
.show-when-demo ion-icon {
- font-size: 200px;
+ font-size: 100px;
}
diff --git a/demos/toast/index.ts b/demos/toast/index.ts
new file mode 100644
index 0000000000..d49af6a0cb
--- /dev/null
+++ b/demos/toast/index.ts
@@ -0,0 +1,59 @@
+import {App, Page, Toast, NavController} from 'ionic-angular';
+
+@Page({
+ templateUrl: 'main.html'
+})
+class ApiPage {
+ constructor(private nav: NavController) { }
+
+ showToast() {
+ const toast = Toast.create({
+ message: 'User was created successfully',
+ });
+
+ toast.onDismiss(this.dismissHandler);
+ this.nav.present(toast);
+ }
+
+ showLongToast() {
+ const toast = Toast.create({
+ message: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea voluptatibus quibusdam eum nihil optio, ullam accusamus magni, nobis suscipit reprehenderit, sequi quam amet impedit. Accusamus dolorem voluptates laborum dolor obcaecati.',
+ });
+
+ toast.onDismiss(this.dismissHandler);
+ this.nav.present(toast);
+ }
+
+ showDismissDurationToast() {
+ const toast = Toast.create({
+ message: 'I am dismissed after 1.5 seconds',
+ duration: 1500
+ });
+ toast.onDismiss(this.dismissHandler);
+ this.nav.present(toast);
+ }
+
+ showToastWithCloseButton() {
+ const toast = Toast.create({
+ message: 'Your internet connection appears to be offline. Data integrity is not guaranteed.',
+ showCloseButton: true,
+ closeButtonText: 'Ok'
+ });
+ toast.onDismiss(this.dismissHandler);
+ this.nav.present(toast);
+ }
+
+ private dismissHandler(toast: Toast) {
+ console.info('Toast onDismiss()');
+ }
+
+}
+
+
+@App({
+ template: ''
+})
+class ApiDemoApp {
+ root = ApiPage;
+ constructor() { }
+}
diff --git a/demos/toast/main.html b/demos/toast/main.html
new file mode 100644
index 0000000000..42341c5178
--- /dev/null
+++ b/demos/toast/main.html
@@ -0,0 +1,11 @@
+
+ Toast
+
+
+
+
+
+
+
+
+
diff --git a/ionic/components.core.scss b/ionic/components.core.scss
index 7252f4a8ad..5c03c0d153 100644
--- a/ionic/components.core.scss
+++ b/ionic/components.core.scss
@@ -29,8 +29,5 @@
"components/virtual-scroll/virtual-scroll";
-// Ionicons (to be replaced with SVGs)
-$ionicons: true !default;
-@if ($ionicons) {
- @import "fonts/ionicons";
-}
+// Ionicons
+@import "fonts/ionicons";
diff --git a/ionic/components.ios.scss b/ionic/components.ios.scss
index aa02af24f1..b37c65aff0 100644
--- a/ionic/components.ios.scss
+++ b/ionic/components.ios.scss
@@ -27,6 +27,7 @@
"components/select/select.ios",
"components/tabs/tabs.ios",
"components/toggle/toggle.ios",
+ "components/toast/toast.ios",
"components/toolbar/toolbar.ios";
diff --git a/ionic/components.md.scss b/ionic/components.md.scss
index 91911f4c62..4515f65aa1 100644
--- a/ionic/components.md.scss
+++ b/ionic/components.md.scss
@@ -27,6 +27,7 @@
"components/select/select.md",
"components/tabs/tabs.md",
"components/toggle/toggle.md",
+ "components/toast/toast.md",
"components/toolbar/toolbar.md";
diff --git a/ionic/components.ts b/ionic/components.ts
index 86455e54bb..49dc914bf8 100644
--- a/ionic/components.ts
+++ b/ionic/components.ts
@@ -4,7 +4,6 @@ export * from './components/app/id'
export * from './components/action-sheet/action-sheet'
export * from './components/alert/alert'
export * from './components/badge/badge'
-export * from './components/blur/blur'
export * from './components/button/button'
export * from './components/checkbox/checkbox'
export * from './components/content/content'
@@ -47,5 +46,6 @@ export * from './components/tabs/tabs'
export * from './components/tabs/tab'
export * from './components/tap-click/tap-click'
export * from './components/toggle/toggle'
+export * from './components/toast/toast'
export * from './components/toolbar/toolbar'
export * from './components/virtual-scroll/virtual-scroll'
diff --git a/ionic/components.wp.scss b/ionic/components.wp.scss
index 5cdf5f81d1..e1e423801f 100644
--- a/ionic/components.wp.scss
+++ b/ionic/components.wp.scss
@@ -27,6 +27,7 @@
"components/select/select.wp",
"components/tabs/tabs.wp",
"components/toggle/toggle.wp",
+ "components/toast/toast.wp",
"components/toolbar/toolbar.wp";
diff --git a/ionic/components/action-sheet/action-sheet.ios.scss b/ionic/components/action-sheet/action-sheet.ios.scss
index 4eba06bbd3..14c5a70e74 100644
--- a/ionic/components/action-sheet/action-sheet.ios.scss
+++ b/ionic/components/action-sheet/action-sheet.ios.scss
@@ -91,7 +91,7 @@ ion-action-sheet {
.action-sheet-selected {
font-weight: bold;
- background: white;
+ background: #fff;
}
.action-sheet-destructive {
diff --git a/ionic/components/action-sheet/action-sheet.md.scss b/ionic/components/action-sheet/action-sheet.md.scss
index fb00fc0dd5..908dcdfdce 100644
--- a/ionic/components/action-sheet/action-sheet.md.scss
+++ b/ionic/components/action-sheet/action-sheet.md.scss
@@ -70,6 +70,10 @@ $action-sheet-md-icon-margin: 0 28px 0 0 !default;
&:last-child .action-sheet-button {
margin-bottom: $action-sheet-md-group-margin-bottom;
}
+
+ .button-inner {
+ justify-content: flex-start;
+ }
}
.action-sheet-selected {
diff --git a/ionic/components/action-sheet/action-sheet.ts b/ionic/components/action-sheet/action-sheet.ts
index 6479980f95..e6578d9bc9 100644
--- a/ionic/components/action-sheet/action-sheet.ts
+++ b/ionic/components/action-sheet/action-sheet.ts
@@ -75,6 +75,62 @@ import {ViewController} from '../nav/view-controller';
* }
* ```
*
+ *
+ * ### Dismissing And Async Navigation
+ *
+ * After an action sheet has been dismissed, the app may need to also transition
+ * to another page depending on the handler's logic. However, because multiple
+ * transitions were fired at roughly the same time, it's difficult for the
+ * nav controller to cleanly animate multiple transitions that may
+ * have been kicked off asynchronously. This is further described in the
+ * [`Nav Transition Promises`](../../nav/NavController) section. For action sheets,
+ * this means it's best to wait for the action sheet to finish its transition
+ * out before starting a new transition on the same nav controller.
+ *
+ * In the example below, after the button has been clicked, its handler
+ * waits on async operation to complete, *then* it uses `pop` to navigate
+ * back a page in the same stack. The potential problem is that the async operation
+ * may have been completed before the action sheet has even finished its transition
+ * out. In this case, it's best to ensure the action sheet has finished its transition
+ * out first, *then* start the next transition.
+ *
+ * ```ts
+ * let actionSheet = ActionSheet.create({
+ * title: 'Hello',
+ * buttons: [{
+ * text: 'Ok',
+ * handler: () => {
+ * // user has clicked the action sheet button
+ * // begin the action sheet's dimiss transition
+ * let navTransition = actionSheet.dismiss();
+ *
+ * // start some async method
+ * someAsyncOperation().then(() => {
+ * // once the async operation has completed
+ * // then run the next nav transition after the
+ * // first transition has finished animating out
+ *
+ * navTransition.then(() => {
+ * this.nav.pop();
+ * });
+ * });
+ * return false;
+ * }
+ * }]
+ * });
+ *
+ * this.nav.present(actionSheet);
+ * ```
+ *
+ * It's important to note that the handler returns `false`. A feature of
+ * button handlers is that they automatically dismiss the action sheet when their button
+ * was clicked, however, we'll need more control regarding the transition. Because
+ * the handler returns `false`, then the action sheet does not automatically dismiss
+ * itself. Instead, you now have complete control of when the action sheet has finished
+ * transitioning, and the ability to wait for the action sheet to finish transitioning
+ * out before starting a new transition.
+ *
+ *
* @demo /docs/v2/demos/action-sheet/
* @see {@link /docs/v2/components#action-sheets ActionSheet Component Docs}
*/
@@ -166,14 +222,14 @@ export class ActionSheet extends ViewController {
'
' +
'
{{d.title}}
' +
'
{{d.subTitle}}
' +
- '
' +
'
' +
- '' +
+ '' +
' ' +
'{{d.cancelButton.text}}' +
'' +
@@ -234,7 +290,7 @@ class ActionSheetCmp {
// deprecated warning
if (button.style) {
- console.warn('Alert "style" property has been renamed to "role"');
+ console.warn('Action sheet "style" property has been renamed to "role"');
button.role = button.style;
}
diff --git a/ionic/components/action-sheet/action-sheet.wp.scss b/ionic/components/action-sheet/action-sheet.wp.scss
index 05ce0c5060..a92e44858d 100644
--- a/ionic/components/action-sheet/action-sheet.wp.scss
+++ b/ionic/components/action-sheet/action-sheet.wp.scss
@@ -73,6 +73,10 @@ $action-sheet-wp-icon-margin: 0 16px 0 0 !default;
&:last-child .action-sheet-button {
margin-bottom: $action-sheet-wp-group-margin-bottom;
}
+
+ .button-inner {
+ justify-content: flex-start;
+ }
}
.action-sheet-selected {
diff --git a/ionic/components/alert/alert.ios.scss b/ionic/components/alert/alert.ios.scss
index 3f546b614f..9a76a9ccf9 100644
--- a/ionic/components/alert/alert.ios.scss
+++ b/ionic/components/alert/alert.ios.scss
@@ -58,7 +58,7 @@ $alert-ios-radio-label-padding: 13px !default;
$alert-ios-radio-min-width: 30px !default;
-$alert-ios-radio-icon-top: 13px !default;
+$alert-ios-radio-icon-top: -7px !default;
$alert-ios-radio-icon-left: 7px !default;
$alert-ios-radio-icon-width: 6px !default;
$alert-ios-radio-icon-height: 12px !default;
diff --git a/ionic/components/alert/alert.md.scss b/ionic/components/alert/alert.md.scss
index 4a14f36e74..7c654afdb0 100644
--- a/ionic/components/alert/alert.md.scss
+++ b/ionic/components/alert/alert.md.scss
@@ -57,7 +57,7 @@ $alert-md-list-border-bottom: $alert-md-list-border-top !default
$alert-md-radio-label-padding: 13px 26px !default;
-$alert-md-radio-top: 13px !default;
+$alert-md-radio-top: 0 !default;
$alert-md-radio-left: 13px !default;
$alert-md-radio-width: 16px !default;
$alert-md-radio-height: 16px !default;
@@ -78,7 +78,7 @@ $alert-md-radio-icon-transition: transform 280ms cubic-bezier(.4, 0
$alert-md-checkbox-label-padding: 13px 26px !default;
-$alert-md-checkbox-top: 13px !default;
+$alert-md-checkbox-top: 0 !default;
$alert-md-checkbox-left: 13px !default;
$alert-md-checkbox-width: 16px !default;
$alert-md-checkbox-height: 16px !default;
@@ -337,4 +337,8 @@ $alert-md-checkbox-icon-transform: rotate(45deg) !default;
&.activated {
background-color: $alert-md-button-background-color-activated;
}
+
+ .button-inner {
+ justify-content: $alert-md-button-group-justify-content;
+ }
}
diff --git a/ionic/components/alert/alert.ts b/ionic/components/alert/alert.ts
index 6554984b6b..12f1b64d2a 100644
--- a/ionic/components/alert/alert.ts
+++ b/ionic/components/alert/alert.ts
@@ -128,6 +128,62 @@ import {ViewController} from '../nav/view-controller';
* }
* ```
*
+ *
+ * ### Dismissing And Async Navigation
+ *
+ * After an alert has been dismissed, the app may need to also transition
+ * to another page depending on the handler's logic. However, because multiple
+ * transitions were fired at roughly the same time, it's difficult for the
+ * nav controller to cleanly animate multiple transitions that may
+ * have been kicked off asynchronously. This is further described in the
+ * [`Nav Transition Promises`](../../nav/NavController) section. For alerts,
+ * this means it's best to wait for the alert to finish its transition
+ * out before starting a new transition on the same nav controller.
+ *
+ * In the example below, after the alert button has been clicked, its handler
+ * waits on async operation to complete, *then* it uses `pop` to navigate
+ * back a page in the same stack. The potential problem is that the async operation
+ * may have been completed before the alert has even finished its transition
+ * out. In this case, it's best to ensure the alert has finished its transition
+ * out first, *then* start the next transition.
+ *
+ * ```ts
+ * let alert = Alert.create({
+ * title: 'Hello',
+ * buttons: [{
+ * text: 'Ok',
+ * handler: () => {
+ * // user has clicked the alert button
+ * // begin the alert's dimiss transition
+ * let navTransition = alert.dismiss();
+ *
+ * // start some async method
+ * someAsyncOperation().then(() => {
+ * // once the async operation has completed
+ * // then run the next nav transition after the
+ * // first transition has finished animating out
+ *
+ * navTransition.then(() => {
+ * this.nav.pop();
+ * });
+ * });
+ * return false;
+ * }
+ * }]
+ * });
+ *
+ * this.nav.present(alert);
+ * ```
+ *
+ * It's important to note that the handler returns `false`. A feature of
+ * button handlers is that they automatically dismiss the alert when their button
+ * was clicked, however, we'll need more control regarding the transition. Because
+ * the handler returns `false`, then the alert does not automatically dismiss
+ * itself. Instead, you now have complete control of when the alert has finished
+ * transitioning, and the ability to wait for the alert to finish transitioning
+ * out before starting a new transition.
+ *
+ *
* @demo /docs/v2/demos/alert/
*/
export class Alert extends ViewController {
@@ -242,7 +298,7 @@ export class Alert extends ViewController {
* | cssClass | `string` | An additional CSS class for the button |
* | role | `string` | The buttons role, null or `cancel` |
*
- * @param {object} opts Alert. See the tabel above
+ * @param {object} opts Alert. See the table above
*/
static create(opts: AlertOptions = {}) {
return new Alert(opts);
@@ -267,7 +323,7 @@ export class Alert extends ViewController {
'' +
'
`
})
@@ -107,6 +110,46 @@ class AnotherPage {
this.nav.present(alert);
}
+ doFastPop() {
+ let alert = Alert.create({
+ title: 'Async Nav Transition',
+ message: 'This is an example of dismissing an alert, then quickly starting another transition on the same nav controller.',
+ buttons: [{
+ text: 'Ok',
+ handler: () => {
+ // present a loading indicator
+ let loading = Loading.create({
+ content: 'Loading...'
+ });
+ this.nav.present(loading);
+
+ // start an async operation
+ setTimeout(() => {
+ // the async operation has completed
+ // dismiss the loading indicator
+ loading.dismiss();
+
+ // begin dismissing the alert
+ alert.dismiss().then(() => {
+ // after the alert has been dismissed
+ // then you can do another nav transition
+ this.nav.pop();
+ });
+ }, 100);
+
+ // return false so the alert doesn't automatically
+ // dismissed itself. Instead we're manually
+ // handling the dismiss logic above so that we
+ // can wait for the alert to finish it's dismiss
+ // transition before starting another nav transition
+ // on the same nav controller
+ return false;
+ }
+ }]
+ });
+ this.nav.present(alert);
+ }
+
}
diff --git a/ionic/components/app/app.ts b/ionic/components/app/app.ts
index 08aab92d04..b5693d9a84 100644
--- a/ionic/components/app/app.ts
+++ b/ionic/components/app/app.ts
@@ -1,4 +1,4 @@
-import {Injectable} from 'angular2/core';
+import {Injectable, Injector} from 'angular2/core';
import {Title} from 'angular2/platform/browser';
import {Config} from '../../config/config';
@@ -19,6 +19,7 @@ export class IonicApp {
private _titleSrv: Title = new Title();
private _isProd: boolean = false;
private _rootNav: any = null;
+ private _appInjector: Injector;
constructor(
private _config: Config,
@@ -199,4 +200,19 @@ export class IonicApp {
return this._cmps[id];
}
+ /**
+ * Set the global app injector that contains references to all of the instantiated providers
+ * @param injector
+ */
+ setAppInjector(injector: Injector) {
+ this._appInjector = injector;
+ }
+
+ /**
+ * Get an instance of the global app injector that contains references to all of the instantiated providers
+ * @returns {Injector}
+ */
+ getAppInjector(): Injector {
+ return this._appInjector;
+ }
}
diff --git a/ionic/components/app/id.ts b/ionic/components/app/id.ts
index cc5f83e604..b070d4ac83 100644
--- a/ionic/components/app/id.ts
+++ b/ionic/components/app/id.ts
@@ -3,6 +3,7 @@ import {AppViewManager, ElementRef, Directive, Renderer, Input} from 'angular2/c
import {IonicApp} from './app';
/**
+ * @private
* @name Id
* @description
* The `id` attribute is an easy way to identify unique components in an app and access them
diff --git a/ionic/components/app/normalize.scss b/ionic/components/app/normalize.scss
index d5597afc11..a4cef5c4a3 100644
--- a/ionic/components/app/normalize.scss
+++ b/ionic/components/app/normalize.scss
@@ -151,6 +151,12 @@ textarea {
touch-action: manipulation;
}
+a ion-label,
+button ion-label,
+[tappable] ion-label {
+ pointer-events: none;
+}
+
button {
border: 0;
font-family: inherit;
diff --git a/ionic/components/app/test/app.spec.ts b/ionic/components/app/test/app.spec.ts
index eb950a1e9c..10d91d0084 100644
--- a/ionic/components/app/test/app.spec.ts
+++ b/ionic/components/app/test/app.spec.ts
@@ -89,9 +89,10 @@ describe('IonicApp', () => {
var app: IonicApp;
var config: Config;
var platform: Platform;
+ var _cd: any;
function mockNav(): Nav {
- return new Nav(null,null,null,config,null,null,null,null,null,null);
+ return new Nav(null, null, null, config, null, null, null, null, null, null);
}
function mockTabs(): Tabs {
@@ -99,13 +100,17 @@ describe('IonicApp', () => {
}
function mockTab(parentTabs: Tabs): Tab {
- return new Tab(parentTabs,null,config,null,null,null,null,null,null);
+ return new Tab(parentTabs, app, config, null, null, null, null, null, null, _cd);
}
beforeEach(() => {
config = new Config();
platform = new Platform();
app = new IonicApp(config, null, platform);
+ _cd = {
+ reattach: function(){},
+ detach: function(){}
+ };
});
});
diff --git a/ionic/components/blur/blur.ts b/ionic/components/blur/blur.ts
deleted file mode 100644
index 044e225161..0000000000
--- a/ionic/components/blur/blur.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import {Directive, Renderer, ElementRef} from 'angular2/core';
-
-
-/**
- * @name Blur
- * @description
- * The blur attribute applies the CSS blur attribute to an element. Safari only.
- *
- * @usage
- * ```html
- *
- * This card will blur the content behind it.
- *
- * ```
- *
- * @demo /docs/v2/demos/blur/
- * @private
- */
-@Directive({
- selector: '[blur]'
-})
-export class Blur {
- constructor(private _elementRef: ElementRef, private _renderer: Renderer) {
- _renderer.setElementStyle(_elementRef.nativeElement, '-webkit-backdrop-filter', 'blur(10px)');
- }
-}
diff --git a/ionic/components/blur/test/basic/bg.jpg b/ionic/components/blur/test/basic/bg.jpg
deleted file mode 100644
index c3298fcb99..0000000000
Binary files a/ionic/components/blur/test/basic/bg.jpg and /dev/null differ
diff --git a/ionic/components/blur/test/basic/index.ts b/ionic/components/blur/test/basic/index.ts
deleted file mode 100644
index 53fad6e85a..0000000000
--- a/ionic/components/blur/test/basic/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import {App} from 'ionic-angular';
-
-
-@App({
- templateUrl: 'main.html'
-})
-class E2EApp {
- constructor() {
- }
-}
diff --git a/ionic/components/blur/test/basic/main.html b/ionic/components/blur/test/basic/main.html
deleted file mode 100644
index d54b9c1a36..0000000000
--- a/ionic/components/blur/test/basic/main.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- Blur
-
-
-
-
-
-
- Card
-
-
- This card will blur the content behind it.
-
-
-
-
-
-
diff --git a/ionic/components/button/button.ts b/ionic/components/button/button.ts
index 23f4b1afbf..30776cdf1e 100644
--- a/ionic/components/button/button.ts
+++ b/ionic/components/button/button.ts
@@ -58,6 +58,11 @@ export class Button {
*/
isItem: boolean;
+ /**
+ * @input {string} The category of the button.
+ */
+ @Input() category: string;
+
/**
* @input {string} Large button.
*/
@@ -185,6 +190,16 @@ export class Button {
this._readAttrs(element);
}
+ /**
+ * @private
+ */
+ ngOnInit() {
+ // If the button has a role applied to it
+ if (this.category) {
+ this.setRole(this.category);
+ }
+ }
+
/**
* @private
*/
diff --git a/ionic/components/checkbox/checkbox.ts b/ionic/components/checkbox/checkbox.ts
index bdb44b4f01..29f8cf2814 100644
--- a/ionic/components/checkbox/checkbox.ts
+++ b/ionic/components/checkbox/checkbox.ts
@@ -55,6 +55,7 @@ const CHECKBOX_VALUE_ACCESSOR = new Provider(
'
' +
'View
-
+
+
+
+
ng-for {{i}}
+ 260k
+
+
diff --git a/ionic/components/label/label.ts b/ionic/components/label/label.ts
index 280c4d8366..193fbdd1fa 100644
--- a/ionic/components/label/label.ts
+++ b/ionic/components/label/label.ts
@@ -7,9 +7,9 @@ import {Directive, ElementRef, Renderer, Input, Optional, Attribute} from 'angul
* Labels are placed inside of an `ion-item` element and can be used
* to describe an `ion-input`, `ion-toggle`, `ion-checkbox`, and more.
*
- * @property [fixed] - a persistant label that sits next the the input
- * @property [floating] - a label that will float about the input if the input is empty of looses focus
- * @property [stacked] - A stacked label will always appear on top of the input
+ * @property [fixed] - A persistant label that sits next the input.
+ * @property [floating] - A label that will float about the input if the input is empty of looses focus.
+ * @property [stacked] - A stacked label will always appear on top of the input.
*
* @usage
diff --git a/ionic/components/list/list.ts b/ionic/components/list/list.ts
index ca2eb1b298..1435db4784 100644
--- a/ionic/components/list/list.ts
+++ b/ionic/components/list/list.ts
@@ -52,11 +52,12 @@ export class List extends Ion {
* Enable sliding items if your page has them
*
* ```ts
+ * import {Page, List} from 'ionic-angular';
+ * import {ViewChild} from 'angular2/core';
+ * @Page...
* export class MyClass {
- * constructor(app: IonicApp){
- * this.app = app;
- * this.list = this.app.getComponent('my-list');
- * }
+ * @ViewChild(List) list: List;
+ * constructor(){}
* stopSliding(){
* this.list.enableSlidingItems(false);
* }
@@ -86,13 +87,12 @@ export class List extends Ion {
* Enable sliding items if your page has
*
* ```ts
+ * import {Page, List} from 'ionic-angular';
+ * import {ViewChild} from 'angular2/core';
+ * @Page...
* export class MyClass {
- * constructor(app: IonicApp){
- * this.app = app;
- * this.list = this.app.getComponent('my-list');
- * }
- * // Here we have some method that will close the items
- * // when called
+ * @ViewChild(List) list: List;
+ * constructor(){}
* closeItmes(){
* this.list.closeSlidingItems();
* }
diff --git a/ionic/components/loading/loading.ts b/ionic/components/loading/loading.ts
index 4f200c7a53..727403bb17 100644
--- a/ionic/components/loading/loading.ts
+++ b/ionic/components/loading/loading.ts
@@ -36,7 +36,9 @@ import {ViewController} from '../nav/view-controller';
* the `duration` of the loading options. By default the loading indicator
* will show even during page changes, but this can be disabled by setting
* `dismissOnPageChange` to `true`. To dismiss the loading indicator after
- * creation, call the `dismiss()` method on the Loading instance.
+ * creation, call the `dismiss()` method on the Loading instance. The
+ * `onDismiss` function can be called to perform an action after the loading
+ * indicator is dismissed.
*
* ### Limitations
* The element is styled to appear on top of other content by setting its
@@ -71,6 +73,10 @@ import {ViewController} from '../nav/view-controller';
* duration: 5000
* });
*
+ * loading.onDismiss(() => {
+ * console.log('Dismissed loading');
+ * });
+ *
* this.nav.present(loading);
* }
*
diff --git a/ionic/components/loading/test/basic/index.ts b/ionic/components/loading/test/basic/index.ts
index baf8063c09..d3d46c3c5d 100644
--- a/ionic/components/loading/test/basic/index.ts
+++ b/ionic/components/loading/test/basic/index.ts
@@ -13,6 +13,10 @@ class E2EPage {
duration: 1000
});
+ loading.onDismiss(() => {
+ console.log('Dismissed loading');
+ });
+
this.nav.present(loading);
}
diff --git a/ionic/components/nav/nav-controller.ts b/ionic/components/nav/nav-controller.ts
index 1cc3c3176e..56b172ba83 100644
--- a/ionic/components/nav/nav-controller.ts
+++ b/ionic/components/nav/nav-controller.ts
@@ -37,7 +37,7 @@ import {ViewController} from './view-controller';
* specific NavController, most times you will inject and use a reference to the
* nearest NavController to manipulate the navigation stack.
*
- *
Injecting NavController
+ * ### Injecting NavController
* Injecting NavController will always get you an instance of the nearest
* NavController, regardless of whether it is a Tab or a Nav.
*
@@ -58,7 +58,8 @@ import {ViewController} from './view-controller';
* }
* ```
*
- *
Page creation
+ *
+ * ## Page creation
* _For more information on the `@Page` decorator see the [@Page API
* reference](../../../decorators/Page/)._
*
@@ -73,7 +74,7 @@ import {ViewController} from './view-controller';
* [pop()](#pop) or [setRoot()](#setRoot)).
*
*
- *
Lifecycle events
+ * ## Lifecycle events
* Lifecycle events are fired during various stages of navigation. They can be
* defined in any `@Page` decorated component class.
*
@@ -91,15 +92,53 @@ import {ViewController} from './view-controller';
* }
* ```
*
+ * | Page Event | Description |
+ * |--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+ * | `onPageLoaded` | Runs when the page has loaded. This event only happens once per page being created and added to the DOM. If a page leaves but is cached, then this event will not fire again on a subsequent viewing. The `onPageLoaded` event is good place to put your setup code for the page. |
+ * | `onPageWillEnter` | Runs when the page is about to enter and become the active page. |
+ * | `onPageDidEnter` | Runs when the page has fully entered and is now the active page. This event will fire, whether it was the first load or a cached page. |
+ * | `onPageWillLeave` | Runs when the page is about to leave and no longer be the active page. |
+ * | `onPageDidLeave` | Runs when the page has finished leaving and is no longer the active page. |
+ * | `onPageWillUnload` | Runs when the page is about to be destroyed and have its elements removed. |
+ * | `onPageDidUnload` | Runs after the page has been destroyed and its elements have been removed.
*
*
- * - `onPageLoaded` - Runs when the page has loaded. This event only happens once per page being created and added to the DOM. If a page leaves but is cached, then this event will not fire again on a subsequent viewing. The `onPageLoaded` event is good place to put your setup code for the page.
- * - `onPageWillEnter` - Runs when the page is about to enter and become the active page.
- * - `onPageDidEnter` - Runs when the page has fully entered and is now the active page. This event will fire, whether it was the first load or a cached page.
- * - `onPageWillLeave` - Runs when the page is about to leave and no longer be the active page.
- * - `onPageDidLeave` - Runs when the page has finished leaving and is no longer the active page.
- * - `onPageWillUnload` - Runs when the page is about to be destroyed and have its elements removed.
- * - `onPageDidUnload` - Runs after the page has been destroyed and its elements have been removed.
+ * ## Nav Transition Promises
+ *
+ * Navigation transitions are asynchronous, meaning they take a few moments to finish, and
+ * the duration of a transition could be any number. In most cases the async nature of a
+ * transition doesn't cause any problems and the nav controller is pretty good about handling
+ * which transition was the most recent when multiple transitions have been kicked off.
+ * However, when an app begins firing off many transitions, on the same stack at
+ * *roughly* the same time, the nav controller can start to get lost as to which transition
+ * should be finishing, and which transitions should not be animated.
+ *
+ * In cases where an app's navigation can be altered by other async tasks, which may or
+ * may not take a long time, it's best to rely on each nav transition's returned
+ * promise. So instead of firing and forgetting multiple `push` or `pop` nav transitions,
+ * it's better to fire the next nav transition when the previous one has finished.
+ *
+ * In the example below, after the async operation has completed, we then want to transition
+ * to another page. Where the potential problem comes in, is that if the async operation
+ * completed 100ms after the first transition started, then kicking off another transition
+ * halfway through the first transition ends up with a janky animation. Instead, it's best
+ * to always ensure the first transition has already finished before starting the next.
+ *
+ * ```ts
+ * // begin the first transition
+ * let navTransition = this.nav.push(SomePage);
+ *
+ * // start an async call, we're not sure how long it'll take
+ * someAsyncOperation().then(() => {
+ * // incase the async operation completed faster than the time
+ * // it took to finish the first transition, this logic should
+ * // always ensure that the previous transition has resolved
+ * // first before kicking off the next transition
+ * navTransition.then(() => {
+ * this.nav.push(AnotherPage);
+ * });
+ * });
+ * ```
*
* @see {@link /docs/v2/components#navigation Navigation Component Docs}
*/
@@ -178,6 +217,9 @@ export class NavController extends Ion {
]);
}
+ /**
+ * @private
+ */
setPortal(val: Portal) {
this._portal = val;
}
@@ -1357,7 +1399,7 @@ export class NavController extends Ion {
}
this._views.length = 0;
- if (this.parent) {
+ if (this.parent && this.parent.unregisterChildNav) {
this.parent.unregisterChildNav(this);
}
}
diff --git a/ionic/components/nav/test/basic/index.ts b/ionic/components/nav/test/basic/index.ts
index ba4fb24999..cb70681b7c 100644
--- a/ionic/components/nav/test/basic/index.ts
+++ b/ionic/components/nav/test/basic/index.ts
@@ -1,13 +1,12 @@
import {Component, Type, ViewChild} from 'angular2/core';
import {App, NavController, Alert, Content} from 'ionic-angular';
import {Page, Config, IonicApp} from 'ionic-angular';
-import {NavParams, ViewController, IONIC_DIRECTIVES} from 'ionic-angular';;
+import {NavParams, ViewController} from 'ionic-angular';;
@Component({
selector: 'my-cmp',
- template: `
My Custom Component Test
`,
- directives: [IONIC_DIRECTIVES]
+ template: `
My Custom Component Test
`
})
class MyCmpTest{}
@@ -49,6 +48,7 @@ class MyCmpTest{}
New push during transitionNew pop during transitionReload
+ Scroll to bottomPage {{i}}Scroll to top
@@ -122,6 +122,10 @@ class FirstPage {
scrollToTop() {
this.content.scrollToTop();
}
+
+ scrollToBottom() {
+ this.content.scrollToBottom(1000);
+ }
}
diff --git a/ionic/components/navbar/navbar.ts b/ionic/components/navbar/navbar.ts
index db3c458f33..cd571be8a3 100644
--- a/ionic/components/navbar/navbar.ts
+++ b/ionic/components/navbar/navbar.ts
@@ -91,7 +91,7 @@ class ToolbarBackground {
selector: 'ion-navbar',
template:
'' +
- '' +
+ '' +
'' +
'' +
'' +
diff --git a/ionic/components/radio/radio-button.ts b/ionic/components/radio/radio-button.ts
index 9eb36c3bf6..409d47c5f7 100644
--- a/ionic/components/radio/radio-button.ts
+++ b/ionic/components/radio/radio-button.ts
@@ -37,6 +37,7 @@ import {RadioGroup} from './radio-group';
'
' +
'' +
@@ -255,7 +256,7 @@ export class Select {
this.onChange(input.value);
this.change.emit(input.value);
}
- }
+ };
}));
alertOptions.cssClass = 'select-action-sheet';
@@ -273,7 +274,7 @@ export class Select {
label: input.text,
value: input.value,
checked: input.checked
- }
+ };
});
// create the alert instance from our built up alertOptions
diff --git a/ionic/components/show-hide-when/show-hide-when.scss b/ionic/components/show-hide-when/show-hide-when.scss
index d47865bf23..40eb064f69 100644
--- a/ionic/components/show-hide-when/show-hide-when.scss
+++ b/ionic/components/show-hide-when/show-hide-when.scss
@@ -5,10 +5,10 @@
// Applied by the showWhen directive
.hidden-show-when {
- display: none;
+ display: none !important;
}
// Applied by the hideWhen directive
.hidden-hide-when {
- display: none;
+ display: none !important;
}
diff --git a/ionic/components/show-hide-when/show-hide-when.ts b/ionic/components/show-hide-when/show-hide-when.ts
index 28b88b779d..ead749f783 100644
--- a/ionic/components/show-hide-when/show-hide-when.ts
+++ b/ionic/components/show-hide-when/show-hide-when.ts
@@ -62,7 +62,15 @@ export class DisplayWhen {
* @description
* The `showWhen` attribute takes a string that represents a platform or screen orientation.
* The element the attribute is added to will only be shown when that platform or screen orientation is active.
- * Complements the [hideWhen attribute](../HideWhen).
+ *
+ * Complements the [hideWhen attribute](../HideWhen). If the `showWhen` attribute is used on an
+ * element that also has the `hideWhen` attribute, the element will not show if `hideWhen` evaluates
+ * to `true` or `showWhen` evaluates to `false`. If the `hidden` attribute is also added, the element
+ * will not show if `hidden` evaluates to `true`.
+ *
+ * View the [Platform API docs](../../../platform/Platform) for more information on the different
+ * platforms you can use.
+ *
* @usage
* ```html
*
@@ -87,6 +95,7 @@ export class DisplayWhen {
* ```
* @demo /docs/v2/demos/show-when/
* @see {@link ../HideWhen HideWhen API Docs}
+ * @see {@link ../../../platform/Platform Platform API Docs}
*/
@Directive({
selector: '[showWhen]',
@@ -111,7 +120,15 @@ export class ShowWhen extends DisplayWhen {
* @description
* The `hideWhen` attribute takes a string that represents a plaform or screen orientation.
* The element the attribute is added to will only be hidden when that platform or screen orientation is active.
- * Complements the [showWhen attribute](../ShowWhen).
+ *
+ * Complements the [showWhen attribute](../ShowWhen). If the `hideWhen` attribute is used on an
+ * element that also has the `showWhen` attribute, the element will not show if `hideWhen` evaluates
+ * to `true` or `showWhen` evaluates to `false`. If the `hidden` attribute is also added, the element
+ * will not show if `hidden` evaluates to `true`.
+ *
+ * View the [Platform API docs](../../../platform/Platform) for more information on the different
+ * platforms you can use.
+ *
* @usage
* ```html
*
@@ -137,7 +154,8 @@ export class ShowWhen extends DisplayWhen {
*
* @demo /docs/v2/demos/hide-when/
* @see {@link ../ShowWhen ShowWhen API Docs}
- */
+ * @see {@link ../../../platform/Platform Platform API Docs}
+*/
@Directive({
selector: '[hideWhen]',
host: {
diff --git a/ionic/components/show-hide-when/test/basic/main.html b/ionic/components/show-hide-when/test/basic/main.html
index 07ac5d9aac..41fa32c34d 100644
--- a/ionic/components/show-hide-when/test/basic/main.html
+++ b/ionic/components/show-hide-when/test/basic/main.html
@@ -1,8 +1,18 @@
-Show/Hide When
+
+ Show/Hide When
+
+ iOS
+ Windows
+ Android
+
+
+ iOS
+ Windows
+ Android
showWhen="ios"
diff --git a/ionic/components/slides/slides.scss b/ionic/components/slides/slides.scss
index 5bae405f95..ded9090c6e 100644
--- a/ionic/components/slides/slides.scss
+++ b/ionic/components/slides/slides.scss
@@ -1,10 +1,5 @@
@import "../../globals.core";
-ion-swipe-slides {
- display: block;
- width: 100%;
- height: 100%;
-}
/**
* Swiper 3.1.2
diff --git a/ionic/components/slides/slides.ts b/ionic/components/slides/slides.ts
index e71acaef71..aaa73e19eb 100644
--- a/ionic/components/slides/slides.ts
+++ b/ionic/components/slides/slides.ts
@@ -7,7 +7,7 @@ import {Gesture} from '../../gestures/gesture';
import {DragGesture} from '../../gestures/drag-gesture';
import {dom} from '../../util';
import {CSS} from '../../util/dom';
-import {debounce, isTrueProperty, defaults} from '../../util/util';
+import {debounce, isTrueProperty, isPresent, defaults} from '../../util/util';
import {Swiper} from './swiper-widget';
import {Scroll} from '../scroll/scroll';
@@ -16,38 +16,159 @@ import {Scroll} from '../scroll/scroll';
/**
* @name Slides
* @description
- * Slides is a slide box implementation based on Swiper.js
+ * The Slides component is a multi-section container. Each section can be swiped
+ * or dragged between. It contains any number of [Slide](../Slide) components.
+ *
+ *
+ * ### Creating
+ * You should use a template to create slides and listen to slide events. The template
+ * should contain the slide container, an `` element, and any number of
+ * [Slide](../Slide) components, written as ``. Any configuration of the
+ * slides should be passed in the `options` property of the `` element.
+ * You can listen to events such as the slide changing by placing the event on the
+ * `` element. See [Usage](#usage) below for more information on
+ * creating slides.
+ *
+ *
+ * ### Configuring
+ * There are several configuration options that can be passed to Slides. These should
+ * be passed in the `options` property of the `` element upon creation.
+ * You can allow the slides to loop around from the last to the first, set autoplay
+ * on the slides so it will automatically switch between them, and more.
+ *
+ * Properties to pass in options:
+ *
+ * | Property | Type | Default | Description |
+ * |-----------------------|-----------|----------------|--------------------------------------------------------------------------------------------|
+ * | autoplay | `number` | - | Delay between transitions (in ms). If this parameter is not passed, autoplay is disabled. |
+ * | direction | `string` | 'horizontal' | Swipe direction: 'horizontal' or 'vertical'. |
+ * | initialSlide | `number` | 0 | Index number of initial slide |
+ * | loop | `boolean` | false | Whether to continuously loop from the last slide to the first slide. |
+ * | pager | `boolean` | false | Show the pagination bullets. |
+ * | speed | `number` | 300 | Duration of transition between slides (in ms). |
+ *
+ * See [Usage](#usage) below for more information on configuring slides.
+ *
+ *
+ * ### Navigating
+ * After creating and configuring the slides, you can navigate between them
+ * by swiping or calling methods on the `Slides` instance. You can call `slideTo()` to
+ * navigate to a specific slide, or `slideNext()` to change to the slide that follows
+ * the active slide. All of the [methods](#instance-members) provided by the `Slides`
+ * instance are listed below. See [Usage](#usage) below for more information on
+ * navigating between slides.
+ *
+ *
+ * ### Limitations
+ * The Slides component wraps the [Swiper](http://www.idangero.us/swiper/) component
+ * built by iDangero.us. This means that all of the Swiper API isn't exposed on the
+ * Slides component. See the [`getSlider()`](#getSlider) method for information on
+ * getting the `Swiper` instance and using its methods directly.
+ *
*
* @usage
- * ```ts
- * @Page({
- * template: `
- *
- *
- *
Thank you for choosing the Awesome App!
- *
- * The number one app for everything awesome.
- *
- *
- *
- *
Using Awesome
- *
- *
Just three steps:
- *
- *
Be awesome
- *
Stay awesome
- *
There is no step 3
- *
- *
- *
- *
- *
Any questions?
- *
- *
- * `
- *})
*
- *```
+ * You can add slides to a `@Page` using the following template:
+ *
+ * ```html
+ *
+ *
+ *
Slide 1
+ *
+ *
+ *
Slide 2
+ *
+ *
+ *
Slide 3
+ *
+ *
+ * ```
+ *
+ * To add [options](#configuring), we will define them in `mySlideOptions` in our class `MyPage`:
+ *
+ * ```ts
+ * import {Page, Slides} from 'ionic-angular';
+ *
+ * @Page({
+ * templateUrl: 'my-page.html'
+ * })
+ * class MyPage {
+ * mySlideOptions = {
+ * initialSlide: 1,
+ * loop: true
+ * };
+ * }
+ * ```
+ *
+ * This is setting the second slide as the initial slide on load, since
+ * the `initialSlide` begins at `0`. We are also setting `loop` to true which
+ * allows us to swipe from the last slide to the first continuously. Then,
+ * we will pass `mySlideOptions` in the `options` property of the ``
+ * element. We are using [property binding](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#property-binding)
+ * on `options` because `mySlideOptions` is an expression:
+ *
+ * ```html
+ *
+ * ```
+ *
+ * To grab a reference to the Slides, we will add a [local template variable](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#local-vars)
+ * to `` called `mySlider`:
+ *
+ * ```html
+ *
+ * ```
+ *
+ * Next, we can use `ViewChild` to assign the Slides instance to `slider`:
+ *
+ * ```ts
+ * import {ViewChild} from 'angular2/core';
+ *
+ * class MyPage {
+ * @ViewChild('mySlider') slider: Slides;
+ *
+ * ...
+ * }
+ * ```
+ *
+ * Now we can call any of the `Slider` [methods]((#instance-members)),
+ * for example we can use the Slider's `slideTo()` method in order to
+ * navigate to a specific slide on a button click. Below we call the
+ * `goToSlide()` method and it navigates to the 3rd slide:
+ *
+ * ```ts
+ * class MyPage {
+ * ...
+ *
+ * goToSlide() {
+ * this.slider.slideTo(2, 500);
+ * }
+ * }
+ * ```
+ *
+ * We can also add events to listen to on the `` element.
+ * Let's add the `didChange` event and call a method when the slide changes:
+ *
+ * ```html
+ *
+ * ```
+ *
+ * In our class, we add the `onSlideChanged()` method which gets the active
+ * index and prints it:
+ *
+ * ```ts
+ * class MyPage {
+ * ...
+ *
+ * onSlideChanged() {
+ * let currentIndex = this.slider.getActiveIndex();
+ * console.log("Current index is", currentIndex);
+ * }
+ * }
+ * ```
+ *
+ * For all of the methods you can call on the `Slider` instance, see the
+ * [Instance Members](#instance-members).
+ *
* @demo /docs/v2/demos/slides/
* @see {@link /docs/v2/components#slides Slides Component Docs}
*
@@ -72,6 +193,9 @@ import {Scroll} from '../scroll/scroll';
'' +
'
',
directives: [NgClass],
+ host: {
+ '[class]': 'slideId'
+ },
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
@@ -82,6 +206,16 @@ export class Slides extends Ion {
*/
public rapidUpdate: Function;
+ /**
+ * @private
+ */
+ private id: number;
+
+ /**
+ * @private
+ */
+ private slideId: string;
+
/**
* @private
*/
@@ -156,54 +290,64 @@ export class Slides extends Ion {
};
/**
- * @input {boolean} Whether the slide should show the pager or not
- */
- @Input() pager: any;
-
- /**
- * @input {any} Any slider options you want to configure, see swiper parameters: http://www.idangero.us/swiper/api/
+ * @input {Object} Any configuration for the slides
*/
@Input() options: any;
/**
- * @input {number} Whether or not the slider can zoom in or out
+ * @private Deprecated
+ */
+ @Input() pager: any;
+
+ /**
+ * @private Deprecated
*/
@Input() zoom: any;
/**
- * @input {number} how long it should take to zoom a slide
+ * @private Deprecated
*/
@Input() zoomDuration: any;
/**
- * @input {number} the max scale an slide can be zoomed
+ * @private Deprecated
*/
@Input() zoomMax: any;
/**
- * @output {any} expression to evaluate when a slide has been changed
- */
- @Output() change: EventEmitter = new EventEmitter();
-
- /**
- * @output {any} expression to evaluate when a slide change starts
+ * @private Deprecated
*/
@Output() slideChangeStart: EventEmitter = new EventEmitter();
/**
- * @output {any} expression to evaluate when a slide moves
+ * @private Deprecated
+ */
+ @Output() change: EventEmitter = new EventEmitter();
+
+ /**
+ * @output {any} Expression to evaluate when a slide change starts.
+ */
+ @Output() willChange: EventEmitter = new EventEmitter();
+
+ /**
+ * @output {any} Expression to evaluate when a slide change ends.
+ */
+ @Output() didChange: EventEmitter = new EventEmitter();
+
+ /**
+ * @output {any} Expression to evaluate when a slide moves.
*/
@Output() move: EventEmitter = new EventEmitter();
- /**
- * @private
- * @param {ElementRef} elementRef TODO
- */
+
constructor(elementRef: ElementRef) {
super(elementRef);
this.rapidUpdate = debounce(() => {
this.update();
}, 10);
+
+ this.id = ++slidesId;
+ this.slideId = 'slides-' + this.id;
}
/**
@@ -214,10 +358,32 @@ export class Slides extends Ion {
this.options = {};
}
- this.showPager = isTrueProperty(this.pager);
+ if (isPresent(this.pager)) {
+ // beta.5 2016-04-18 deprecated warning
+ // Pager should be passed as an option
+ console.warn('The "pager" attribute has been deprecated. Please pass it in options.');
+ // Remove this with the deprecation warning
+ this.showPager = isTrueProperty(this.pager);
+ }
+
+ if (isPresent(this.zoom)) {
+ // beta.5 2016-04-18 deprecated warning
+ // Zoom should be passed as an option
+ console.warn('The "zoom" attribute has been deprecated. Please pass it in options.');
+ }
+
+ // Deprecated 04-18 beta.5
+ console.warn('The "slideChangeStart" event has been deprecated. Please use "willChange" instead. Ignore this if you aren\'t using it.');
+ console.warn('The "change" event has been deprecated. Please use "didChange" instead. Ignore this if you aren\'t using it.');
+
+ if (isPresent(this.options.pager)) {
+ this.showPager = isTrueProperty(this.options.pager);
+ }
+
+ let paginationId = '.' + this.slideId + ' .swiper-pagination';
var options = defaults({
- pagination: '.swiper-pagination',
+ pagination: paginationId
}, this.options);
options.onTap = (swiper, e) => {
@@ -241,11 +407,17 @@ export class Slides extends Ion {
return this.options.onTransitionEnd && this.options.onTransitionEnd(swiper, e);
};
options.onSlideChangeStart = (swiper) => {
+ // TODO deprecated 2016-04-18
this.slideChangeStart.emit(swiper);
+
+ this.willChange.emit(swiper);
return this.options.onSlideChangeStart && this.options.onSlideChangeStart(swiper);
};
options.onSlideChangeEnd = (swiper) => {
+ // TODO deprecated 2016-04-18
this.change.emit(swiper);
+
+ this.didChange.emit(swiper);
return this.options.onSlideChangeEnd && this.options.onSlideChangeEnd(swiper);
};
options.onLazyImageLoad = (swiper, slide, img) => {
@@ -259,6 +431,7 @@ export class Slides extends Ion {
return this.options.onSliderMove && this.options.onSliderMove(swiper, e);
};
+
setTimeout(() => {
var swiper = new Swiper(this.getNativeElement().children[0], options);
this.slider = swiper;
@@ -266,7 +439,7 @@ export class Slides extends Ion {
/*
* TODO: Finish this
- if (util.isTrueProperty(this.zoom)) {
+ if (isTrueProperty(this.zoom)) {
this.enableZoom = true;
setTimeout(() => {
this.initZoom();
@@ -290,7 +463,6 @@ export class Slides extends Ion {
* @private
*/
onDoubleTap(swiper, e) {
-
this.toggleZoom(swiper, e);
}
/**
@@ -602,58 +774,98 @@ export class Slides extends Ion {
this.slider.update();
// Don't allow pager to show with > 10 slides
- if (this.slider.slides.length > 10) {
+ if (this.length() > 10) {
this.showPager = false;
}
});
}
/**
- * @private
+ * Transition to the specified slide.
+ *
+ * @param {number} index The index number of the slide.
+ * @param {number} speed Transition duration (in ms). Optional.
+ * @param {boolean} runCallbacks Whether or not to emit the `willChange`/`didChange` events. Optional. Default true.
*/
- next() {
- this.slider.slideNext();
+ slideTo(index: number, speed: number, runCallbacks: boolean) {
+ this.slider.slideTo(index, speed, runCallbacks);
}
/**
- * @private
+ * Transition to the next slide.
+ *
+ * @param {number} speed Transition duration (in ms). Optional.
+ * @param {boolean} runCallbacks Whether or not to emit the `willChange`/`didChange` events. Optional. Default true.
*/
- prev() {
- this.slider.slidePrev();
+ slideNext(speed: number, runCallbacks: boolean) {
+ this.slider.slideNext(runCallbacks, speed);
}
/**
- * @private
+ * Transition to the previous slide.
+ *
+ * @param {number} speed Transition duration (in ms). Optional.
+ * @param {boolean} runCallbacks Whether or not to emit the `willChange`/`didChange` events. Optional. Default true.
*/
- getIndex(): number {
+ slidePrev(speed: number, runCallbacks: boolean) {
+ this.slider.slidePrev(runCallbacks, speed);
+ }
+
+ /**
+ * Get the index of the active slide.
+ *
+ * @returns {number} The index number of the current slide.
+ */
+ getActiveIndex(): number {
return this.slider.activeIndex;
}
/**
- * @private
+ * Get the index of the previous slide.
+ *
+ * @returns {number} The index number of the previous slide.
*/
- getNumSlides(): number {
+ getPreviousIndex(): number {
+ return this.slider.previousIndex;
+ }
+
+ /**
+ * Get the total number of slides.
+ *
+ * @returns {number} The total number of slides.
+ */
+ length(): number {
return this.slider.slides.length;
}
/**
- * @private
+ * Get whether or not the current slide is the last slide.
+ *
+ * @returns {boolean} If the slide is the last slide or not.
*/
- isAtEnd(): boolean {
+ isEnd(): boolean {
return this.slider.isEnd;
}
/**
- * @private
+ * Get whether or not the current slide is the first slide.
+ *
+ * @returns {boolean} If the slide is the first slide or not.
*/
- isAtBeginning(): boolean {
+ isBeginning(): boolean {
return this.slider.isBeginning;
}
/**
- * @private
+ * Get the `Swiper` instance.
+ *
+ * The Slides component wraps the `Swiper` component built by iDangero.us. See the
+ * [Swiper API Docs](http://idangero.us/swiper/api/) for information on using
+ * the `Swiper` instance directly.
+ *
+ * @returns {Swiper}
*/
- getSliderWidget() {
+ getSlider() {
return this.slider;
}
}
@@ -661,7 +873,11 @@ export class Slides extends Ion {
/**
* @name Slide
* @description
- * `ion-slide` is a child component of `ion-slides` and is where all your individule slide content will be rendered too.
+ * The Slide component is a child component of [Slides](../Slides). The template
+ * should be written as `ion-slide`. Any slide content should be written
+ * in this component and it should be used in conjunction with [Slides](../Slides).
+ *
+ * See the [Slides API Docs](../Slides) for more usage information.
*
* @demo /docs/v2/demos/slides/
* @see {@link /docs/v2/api/components/slides/Slides/ Slides API Docs}
@@ -706,3 +922,5 @@ export class Slide {
}
})
export class SlideLazy {}
+
+let slidesId = -1;
diff --git a/ionic/components/slides/swiper-widget.d.ts b/ionic/components/slides/swiper-widget.d.ts
index 46ba753043..054b6491c9 100644
--- a/ionic/components/slides/swiper-widget.d.ts
+++ b/ionic/components/slides/swiper-widget.d.ts
@@ -3,9 +3,11 @@ export declare class Swiper {
constructor(container: HTMLElement, params: any);
slides: Array;
activeIndex: number;
+ previousIndex: number;
isEnd: boolean;
isBeginning: boolean;
update(): any;
- slideNext(): any;
- slidePrev(): any;
+ slideNext(runCallbacks: boolean, speed: number);
+ slidePrev(runCallbacks: boolean, speed: number);
+ slideTo(slideIndex: number, speed: number, runCallbacks: boolean);
}
diff --git a/ionic/components/slides/test/controller/index.ts b/ionic/components/slides/test/controller/index.ts
new file mode 100644
index 0000000000..01cfd5a43c
--- /dev/null
+++ b/ionic/components/slides/test/controller/index.ts
@@ -0,0 +1,53 @@
+import {ViewChild} from 'angular2/core';
+import {App, Page, Slides} from 'ionic-angular';
+
+
+@App({
+ templateUrl: 'main.html'
+})
+class MyPage {
+ @ViewChild('mySlider') slider: Slides;
+ mySlideOptions = {
+ initialSlide: 1,
+ loop: false
+ };
+
+ ngAfterViewInit() {
+
+ }
+
+ onSlideChanged() {
+ let previousIndex = this.slider.getPreviousIndex();
+ let currentIndex = this.slider.getActiveIndex();
+ console.log("Previous index is", previousIndex, "Current index is", currentIndex);
+ }
+
+ goToPrevSlide() {
+ this.slider.slidePrev();
+ }
+
+ goToNextSlide() {
+ this.slider.slideNext();
+ }
+
+ goToSlide(index) {
+ this.slider.slideTo(index);
+ }
+
+ getIndex() {
+ let index = this.slider.getActiveIndex();
+ console.log("Current Index is", index);
+ }
+
+ getLength() {
+ let length = this.slider.length();
+ console.log("Current Length is", length);
+ }
+}
+
+@App({
+ template: ``
+})
+class E2EApp {
+ root: Page = MyPage;
+}
diff --git a/ionic/components/slides/test/controller/main.html b/ionic/components/slides/test/controller/main.html
new file mode 100644
index 0000000000..1ec9978f97
--- /dev/null
+++ b/ionic/components/slides/test/controller/main.html
@@ -0,0 +1,23 @@
+
+
+
Slide 1
+ Navigate Back
+ Navigate Forward
+ Navigate to 3rd Slide
+ Get Slide Length
+ Get Index
+
+
+
Slide 2
+ Navigate Back
+ Navigate Forward
+ Navigate to 3rd Slide
+ Get Index
+
+
+
Slide 3
+ Navigate Back
+ Navigate Forward
+ Get Index
+
+
diff --git a/ionic/components/slides/test/intro/main.html b/ionic/components/slides/test/intro/main.html
index 33cb3a55e9..f2a1e4d888 100644
--- a/ionic/components/slides/test/intro/main.html
+++ b/ionic/components/slides/test/intro/main.html
@@ -8,7 +8,7 @@
-
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed lacinia purus ac turpis fermentum, nec accumsan nulla rutrum. Aenean lorem est, luctus id iaculis ac, ultricies quis odio. Aenean imperdiet imperdiet ex et vehicula. Suspendisse vulputate turpis quis ultricies porttitor. Proin malesuada tortor at libero laoreet, eu eleifend enim pulvinar. Nulla facilisi. Fusce sit amet mauris mauris. Mauris consequat libero sed egestas tincidunt.
+
+
+
+ In felis augue, sagittis id dui ac, tempor luctus turpis. Vestibulum nec urna vitae nisl malesuada lacinia ut sit amet orci. Suspendisse sed mauris vitae mauris porttitor pulvinar. Donec quis ante id dui cursus malesuada ut nec magna. Vestibulum venenatis efficitur urna, quis tempus quam. Curabitur id elementum eros, at euismod nisl. Aliquam ultricies imperdiet arcu id consequat. Aliquam erat volutpat. Nam quis laoreet dui. Donec eget neque non leo porta scelerisque. In blandit placerat nibh, ut viverra nisi feugiat a. Pellentesque semper, ligula et tincidunt egestas, urna arcu pellentesque massa, vitae accumsan ligula velit vitae sem. Nulla porta est id ligula viverra, ut placerat quam auctor. Morbi eget efficitur nibh.
+
+
+
+ Aenean viverra commodo enim eget interdum. Donec condimentum tincidunt sollicitudin. Curabitur malesuada est elementum lectus sodales, vitae eleifend massa dignissim. Pellentesque nec diam dapibus purus vulputate pharetra at id nunc. Vivamus dapibus sed turpis in facilisis. Nulla sollicitudin lacus sem, vel fringilla neque accumsan non. Suspendisse non congue turpis, id mattis ex. Nam sit amet diam quis neque convallis aliquet quis et lorem. Donec sit amet libero sit amet nisl mollis vehicula nec id eros. Curabitur rutrum condimentum porta. Donec pellentesque consectetur lacus. Etiam maximus ante vitae varius eleifend. Integer ac justo sem. Morbi iaculis vel urna in tempus. Aenean at rhoncus nulla.
+
+
diff --git a/ionic/components/toast/toast.ios.scss b/ionic/components/toast/toast.ios.scss
new file mode 100644
index 0000000000..61f3a3ca58
--- /dev/null
+++ b/ionic/components/toast/toast.ios.scss
@@ -0,0 +1,52 @@
+@import "../../globals.ios";
+@import "./toast";
+
+// iOS Toast
+// --------------------------------------------------
+
+$toast-ios-text-align: left !default;
+$toast-ios-background: rgba(0, 0, 0, .9) !default;
+$toast-ios-border-radius: .65rem !default;
+
+$toast-ios-title-color: #fff !default;
+$toast-ios-title-font-size: 1.4rem !default;
+$toast-ios-title-padding: 1.5rem !default;
+
+
+ion-toast {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: $z-index-overlay;
+ display: block;
+
+ width: $toast-width;
+ height: $toast-width;
+}
+
+.toast-wrapper {
+ position: absolute;
+ right: 10px;
+ bottom: 10px;
+ left: 10px;
+ z-index: $z-index-overlay-wrapper;
+ display: block;
+
+ margin: auto;
+
+ max-width: $toast-max-width;
+
+ border-radius: $toast-ios-border-radius;
+
+ background: $toast-ios-background;
+
+ transform: translate3d(0, 100%, 0);
+}
+
+.toast-message {
+ padding: $toast-ios-title-padding;
+
+ font-size: $toast-ios-title-font-size;
+
+ color: $toast-ios-title-color;
+}
diff --git a/ionic/components/toast/toast.md.scss b/ionic/components/toast/toast.md.scss
new file mode 100644
index 0000000000..e740d17efa
--- /dev/null
+++ b/ionic/components/toast/toast.md.scss
@@ -0,0 +1,51 @@
+@import "../../globals.md";
+@import "./toast";
+
+// Material Design Toast
+// --------------------------------------------------
+
+$toast-md-text-align: left !default;
+$toast-md-background: #333 !default;
+$toast-md-group-margin-bottom: 8px !default;
+
+$toast-md-title-color: #fff !default;
+$toast-md-title-font-size: 1.5rem !default;
+$toast-md-title-padding: 19px 16px 17px !default;
+
+
+ion-toast {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: $z-index-overlay;
+ display: block;
+
+ width: $toast-width;
+ height: $toast-width;
+}
+
+.toast-wrapper {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: $z-index-overlay-wrapper;
+ display: block;
+
+ margin: auto;
+
+ width: $toast-width;
+ max-width: $toast-max-width;
+
+ background: $toast-md-background;
+
+ transform: translate3d(0, 100%, 0);
+}
+
+.toast-message {
+ padding: $toast-md-title-padding;
+
+ font-size: $toast-md-title-font-size;
+
+ color: $toast-md-title-color;
+}
diff --git a/ionic/components/toast/toast.scss b/ionic/components/toast/toast.scss
new file mode 100644
index 0000000000..9c146beaf2
--- /dev/null
+++ b/ionic/components/toast/toast.scss
@@ -0,0 +1,52 @@
+@import "../../globals.core";
+
+
+// Toast
+// --------------------------------------------------
+
+$toast-width: 100% !default;
+$toast-max-width: 700px !default;
+
+
+ion-toast {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: $z-index-overlay;
+
+ display: block;
+
+ width: $toast-width;
+ height: $toast-width;
+}
+
+.toast-container {
+ display: flex;
+
+ align-items: center;
+
+ button {
+ padding: 19px 16px 17px;
+
+ font-size: 1.5rem;
+ }
+}
+
+.toast-message {
+ flex: 1;
+}
+
+.toast-wrapper {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: $z-index-overlay-wrapper;
+ display: block;
+
+ margin: auto;
+
+ max-width: $toast-max-width;
+
+ transform: translate3d(0, 100%, 0);
+}
diff --git a/ionic/components/toast/toast.ts b/ionic/components/toast/toast.ts
new file mode 100644
index 0000000000..52afca33e6
--- /dev/null
+++ b/ionic/components/toast/toast.ts
@@ -0,0 +1,322 @@
+import {Component, ElementRef, Renderer, Output, EventEmitter} from 'angular2/core';
+import {NgClass, NgIf, NgFor} from 'angular2/common';
+
+import {Button} from '../button/button';
+import {Icon} from '../icon/icon';
+import {ActionSheet, ActionSheetOptions} from '../action-sheet/action-sheet';
+import {Animation} from '../../animations/animation';
+import {Transition, TransitionOptions} from '../../transitions/transition';
+
+import {Config} from '../../config/config';
+import {isPresent} from '../../util/util';
+import {NavParams} from '../nav/nav-params';
+import {NavController} from '../nav/nav-controller';
+import {ViewController} from '../nav/view-controller';
+
+/**
+ * @name Toast
+ * @description
+ * A Toast is a subtle notification that appears at the bottom of the
+ * screen. It can be used to provide feedback about an operation or to
+ * display a system message. The toast appears on top of the app's content,
+ * and can be dismissed by the app to resume user interaction with
+ * the app. It includes a backdrop, which can optionally be clicked to
+ * dismiss the toast.
+ *
+ * ### Creating
+ * All of the toast options should be passed in the first argument of
+ * the create method: `Toast.create(opts)`. The message to display should be
+ * passed in the `message` property. The `showCloseButton` option can be set to
+ * true in order to display a close button on the toast. See the [create](#create)
+ * method below for all available options.
+ *
+ * ### Dismissing
+ * The toast can be dismissed automatically after a specific amount of time
+ * by passing the number of milliseconds to display it in the `duration` of
+ * the toast options. It can also be dismissed by clicking on the backdrop,
+ * unless `enableBackdropDismiss` is set to `false` upon creation. If `showCloseButton`
+ * is set to true, then the close button will dismiss the toast. To dismiss
+ * the toast after creation, call the `dismiss()` method on the Toast instance.
+ * The `onDismiss` function can be called to perform an action after the toast
+ * is dismissed.
+ *
+ * @usage
+ * ```ts
+ * constructor(nav: NavController) {
+ * this.nav = nav;
+ * }
+ *
+ * presentToast() {
+ * let toast = Toast.create({
+ * message: 'User was added successfully',
+ * duration: 3000
+ * });
+ *
+ * toast.onDismiss(() => {
+ * console.log('Dismissed toast');
+ * });
+ *
+ * this.nav.present(toast);
+ * }
+ * ```
+ *
+ * @demo /docs/v2/demos/toast/
+ */
+export class Toast extends ViewController {
+
+ constructor(opts: ToastOptions = {}) {
+ opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
+ opts.dismissOnPageChange = isPresent(opts.dismissOnPageChange) ? !!opts.dismissOnPageChange : false;
+
+ super(ToastCmp, opts);
+ this.viewType = 'toast';
+ this.isOverlay = true;
+ this.usePortal = true;
+
+ // by default, toasts should not fire lifecycle events of other views
+ // for example, when an toast enters, the current active view should
+ // not fire its lifecycle events because it's not conceptually leaving
+ this.fireOtherLifecycles = false;
+ }
+
+
+
+ /**
+ * @private
+ */
+ getTransitionName(direction: string) {
+ let key = 'toast' + (direction === 'back' ? 'Leave' : 'Enter');
+ return this._nav && this._nav.config.get(key);
+ }
+
+ /**
+ * @param {string} message Toast message content
+ */
+ setMessage(message: string) {
+ this.data.message = message;
+ }
+
+ /**
+ *
+ * Toast options
+ *
+ * | Property | Type | Default | Description |
+ * |-----------------------|-----------|-----------------|---------------------------------------------------------------------------------------------------------------|
+ * | message | `string` | - | The message for the toast. Long strings will wrap and the toast container will expand. |
+ * | duration | `number` | - | How many milliseconds to wait before hiding the toast. By default, it will show until `dismiss()` is called. |
+ * | cssClass | `string` | - | Any additional class for custom styles. |
+ * | showCloseButton | `boolean` | false | Whether or not to show a button to close the toast. |
+ * | closeButtonText | `string` | "Close" | Text to display in the close button. |
+ * | enableBackdropDismiss | `boolean` | true | Whether the toast should be dismissed by tapping the backdrop. |
+ * | dismissOnPageChange | `boolean` | false | Whether to dismiss the toast when navigating to a new page. |
+ *
+ * @param {object} opts Toast options. See the above table for available options.
+ */
+ static create(opts: ToastOptions = {}) {
+ return new Toast(opts);
+ }
+
+}
+
+
+/**
+* @private
+*/
+@Component({
+ selector: 'ion-toast',
+ template: `
+
+