Merge branch '2.0' into picker

# Conflicts:
#	ionic/components.ts
This commit is contained in:
Adam Bradley
2016-04-21 23:47:16 -05:00
65 changed files with 1105 additions and 313 deletions

View File

@@ -1,3 +1,107 @@
<a name="2.0.0-beta.6"></a>
# [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)
<a name="2.0.0-beta.5"></a>
# [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.
<a name="2.0.0-beta.4"></a>
# [2.0.0-beta.4](https://github.com/driftyco/ionic/compare/v2.0.0-beta.3...v2.0.0-beta.4) (2016-04-07)

View File

@@ -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. Youll find its pretty ineffective.
Simply put: be respectful and act like an adult. Critiques are better made on the Forum. If you cant do that, this isnt 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.

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 KiB

View File

@@ -1,6 +0,0 @@
import {App} from 'ionic-angular';
@App({
templateUrl: 'main.html'
})
class ApiDemoApp {}

View File

@@ -1,34 +0,0 @@
<ion-toolbar>
<ion-title>Blur</ion-title>
</ion-toolbar>
<ion-content>
<div class="blur-content">
<ion-card blur class="blur-card">
<ion-card-header>
Card
</ion-card-header>
<ion-card-content>
This card will blur the content behind it.
</ion-card-content>
</ion-card>
</div>
</ion-content>
<style>
.blur-content {
position: absolute;
text-align:center;
background: url('bg.jpg') no-repeat transparent;
background-size: cover;
height: 100%;
width: 100%;
}
.blur-card,
.blur-card ion-card-header {
background: transparent;
color: white;
}
</style>

59
demos/toast/index.ts Normal file
View File

@@ -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: '<ion-nav [root]="root"></ion-nav>'
})
class ApiDemoApp {
root = ApiPage;
constructor() { }
}

11
demos/toast/main.html Normal file
View File

@@ -0,0 +1,11 @@
<ion-toolbar>
<ion-title>Toast</ion-title>
</ion-toolbar>
<ion-content padding>
<button block (click)="showToast()">Show Toast</button>
<button block margin-bottom (click)="showLongToast()">Show Long Toast</button>
<button block (click)="showDismissDurationToast()">Show Custom Duration Toast</button>
<button block (click)="showToastWithCloseButton()">Show Close Button Toast</button>
</ion-content>

View File

@@ -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";

View File

@@ -28,6 +28,7 @@
"components/select/select.ios",
"components/tabs/tabs.ios",
"components/toggle/toggle.ios",
"components/toast/toast.ios",
"components/toolbar/toolbar.ios";

View File

@@ -28,6 +28,7 @@
"components/select/select.md",
"components/tabs/tabs.md",
"components/toggle/toggle.md",
"components/toast/toast.md",
"components/toolbar/toolbar.md";

View File

@@ -3,7 +3,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';

View File

@@ -28,6 +28,7 @@
"components/select/select.wp",
"components/tabs/tabs.wp",
"components/toggle/toggle.wp",
"components/toast/toast.wp",
"components/toolbar/toolbar.wp";

View File

@@ -91,7 +91,7 @@ ion-action-sheet {
.action-sheet-selected {
font-weight: bold;
background: white;
background: #fff;
}
.action-sheet-destructive {

View File

@@ -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 {

View File

@@ -122,7 +122,7 @@ import {ViewController} from '../nav/view-controller';
* this.nav.present(actionSheet);
* ```
*
* It's important to note that the the handler returns `false`. A feature of
* 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
@@ -222,14 +222,14 @@ export class ActionSheet extends ViewController {
'<div class="action-sheet-group">' +
'<div class="action-sheet-title" id="{{hdrId}}" *ngIf="d.title">{{d.title}}</div>' +
'<div class="action-sheet-sub-title" id="{{descId}}" *ngIf="d.subTitle">{{d.subTitle}}</div>' +
'<button (click)="click(b)" *ngFor="#b of d.buttons" class="action-sheet-button disable-hover" [ngClass]="b.cssClass">' +
'<button category="action-sheet-button" (click)="click(b)" *ngFor="#b of d.buttons" class="disable-hover" [ngClass]="b.cssClass">' +
'<ion-icon [name]="b.icon" *ngIf="b.icon" class="action-sheet-icon"></ion-icon> ' +
'{{b.text}}' +
'<ion-button-effect></ion-button-effect>' +
'</button>' +
'</div>' +
'<div class="action-sheet-group" *ngIf="d.cancelButton">' +
'<button (click)="click(d.cancelButton)" class="action-sheet-button action-sheet-cancel disable-hover" [ngClass]="d.cancelButton.cssClass">' +
'<button category="action-sheet-button" (click)="click(d.cancelButton)" class="action-sheet-cancel disable-hover" [ngClass]="d.cancelButton.cssClass">' +
'<ion-icon [name]="d.cancelButton.icon" *ngIf="d.cancelButton.icon" class="action-sheet-icon"></ion-icon> ' +
'{{d.cancelButton.text}}' +
'<ion-button-effect></ion-button-effect>' +

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -175,7 +175,7 @@ import {ViewController} from '../nav/view-controller';
* this.nav.present(alert);
* ```
*
* It's important to note that the the handler returns `false`. A feature of
* 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
@@ -298,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);
@@ -323,7 +323,7 @@ export class Alert extends ViewController {
'<template ngSwitchWhen="radio">' +
'<div class="alert-radio-group" role="radiogroup" [attr.aria-labelledby]="hdrId" [attr.aria-activedescendant]="activeId">' +
'<button *ngFor="#i of d.inputs" (click)="rbClick(i)" [attr.aria-checked]="i.checked" [attr.id]="i.id" class="alert-tappable alert-radio" role="radio">' +
'<button category="alert-radio-button" *ngFor="#i of d.inputs" (click)="rbClick(i)" [attr.aria-checked]="i.checked" [attr.id]="i.id" class="alert-tappable alert-radio" role="radio">' +
'<div class="alert-radio-icon"><div class="alert-radio-inner"></div></div>' +
'<div class="alert-radio-label">' +
'{{i.label}}' +
@@ -334,7 +334,7 @@ export class Alert extends ViewController {
'<template ngSwitchWhen="checkbox">' +
'<div class="alert-checkbox-group">' +
'<button *ngFor="#i of d.inputs" (click)="cbClick(i)" [attr.aria-checked]="i.checked" class="alert-tappable alert-checkbox" role="checkbox">' +
'<button category="alert-checkbox-button" *ngFor="#i of d.inputs" (click)="cbClick(i)" [attr.aria-checked]="i.checked" class="alert-tappable alert-checkbox" role="checkbox">' +
'<div class="alert-checkbox-icon"><div class="alert-checkbox-inner"></div></div>' +
'<div class="alert-checkbox-label">' +
'{{i.label}}' +
@@ -353,7 +353,7 @@ export class Alert extends ViewController {
'</div>' +
'<div class="alert-button-group" [ngClass]="{vertical: d.buttons.length>2}">' +
'<button *ngFor="#b of d.buttons" (click)="btnClick(b)" [ngClass]="b.cssClass" class="alert-button">' +
'<button category="alert-button" *ngFor="#b of d.buttons" (click)="btnClick(b)" [ngClass]="b.cssClass">' +
'{{b.text}}' +
'<ion-button-effect></ion-button-effect>' +
'</button>' +

View File

@@ -59,7 +59,7 @@ $alert-wp-radio-border-color: $input-wp-border-color !default;
$alert-wp-radio-label-padding: 13px 26px !default;
$alert-wp-radio-top: 13px !default;
$alert-wp-radio-top: 0 !default;
$alert-wp-radio-left: 13px !default;
$alert-wp-radio-width: 16px !default;
$alert-wp-radio-height: 16px !default;
@@ -76,7 +76,7 @@ $alert-wp-radio-icon-border-radius: $alert-wp-radio-border-radius !de
$alert-wp-checkbox-label-padding: 13px 26px !default;
$alert-wp-checkbox-top: 13px !default;
$alert-wp-checkbox-top: 0 !default;
$alert-wp-checkbox-left: 13px !default;
$alert-wp-checkbox-width: 16px !default;
$alert-wp-checkbox-height: 16px !default;

View File

@@ -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(){}
};
});
});

View File

@@ -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
* <ion-card blur>
* This card will blur the content behind it.
* </ion-card>
* ```
*
* @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)');
}
}

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 KiB

View File

@@ -1,10 +0,0 @@
import {App} from 'ionic-angular';
@App({
templateUrl: 'main.html'
})
class E2EApp {
constructor() {
}
}

View File

@@ -1,34 +0,0 @@
<ion-toolbar>
<ion-title>Blur</ion-title>
</ion-toolbar>
<ion-content>
<div class="blur-content">
<ion-card blur class="blur-card">
<ion-card-header>
Card
</ion-card-header>
<ion-card-content>
This card will blur the content behind it.
</ion-card-content>
</ion-card>
</div>
</ion-content>
<style>
.blur-content {
position: absolute;
text-align:center;
background: url('bg.jpg') no-repeat transparent;
background-size: cover;
height: 100%;
width: 100%;
}
.blur-card,
.blur-card ion-card-header {
background: transparent;
color: white;
}
</style>

View File

@@ -58,6 +58,11 @@ export class Button {
*/
isItem: boolean;
/**
* @input {string} The category of the button.
*/
@Input() category: string;
/**
* @input {string} Large button.
*/
@@ -179,6 +184,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
*/

View File

@@ -55,6 +55,7 @@ const CHECKBOX_VALUE_ACCESSOR = new Provider(
'</div>' +
'<button role="checkbox" ' +
'type="button" ' +
'category="item-cover" ' +
'[id]="id" ' +
'[attr.aria-checked]="_checked" ' +
'[attr.aria-labelledby]="_labelId" ' +

View File

@@ -434,7 +434,7 @@ export class InputBase {
/**
* @private
* Angular2 Forms API method called by the the view (NgControl) to register
* Angular2 Forms API method called by the view (NgControl) to register
* the onTouched event handler that marks model (Control) as touched.
* @param {Function} fn onTouched event handler.
*/

View File

@@ -44,7 +44,7 @@ export class NativeInput {
function docTouchEnd(ev) {
var tapped: HTMLElement = ev.target;
if (tapped && self.element()) {
if (tapped.tagName !== "INPUT" && tapped.tagName !== "TEXTAREA" && !tapped.classList.contains('input-cover')) {
if (tapped.tagName !== 'INPUT' && tapped.tagName !== 'TEXTAREA' && !tapped.classList.contains('input-cover')) {
self.element().blur();
}
}
@@ -211,4 +211,4 @@ export class NextInput {
this.focused.emit(true);
}
}
}

View File

@@ -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

View File

@@ -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);
* }
*

View File

@@ -13,6 +13,10 @@ class E2EPage {
duration: 1000
});
loading.onDismiss(() => {
console.log('Dismissed loading');
});
this.nav.present(loading);
}

View File

@@ -25,8 +25,8 @@ class E2EPage {
console.log('android', platform.is('android'));
console.log('windows phone', platform.is('windows'));
platform.ready().then(() => {
console.log('platform.ready');
platform.ready().then((readySource) => {
console.log('platform.ready, readySource:', readySource);
});
this.platforms = platform.platforms();

View File

@@ -1399,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);
}
}

View File

@@ -91,7 +91,7 @@ class ToolbarBackground {
selector: 'ion-navbar',
template:
'<div class="toolbar-background"></div>' +
'<button class="back-button bar-button bar-button-default" [hidden]="_hideBb">' +
'<button category="bar-button" class="back-button" [hidden]="_hideBb">' +
'<span class="button-inner">' +
'<ion-icon class="back-button-icon" [name]="_bbIcon"></ion-icon>' +
'<span class="back-button-text">' +

View File

@@ -37,6 +37,7 @@ import {RadioGroup} from './radio-group';
'</div>' +
'<button role="radio" ' +
'type="button" ' +
'category="item-cover" ' +
'[id]="id" ' +
'[attr.aria-checked]="_checked" ' +
'[attr.aria-labelledby]="_labelId" ' +

View File

@@ -109,6 +109,7 @@ const SELECT_VALUE_ACCESSOR = new Provider(
'</div>' +
'<button aria-haspopup="true" ' +
'[id]="id" ' +
'category="item-cover" ' +
'[attr.aria-labelledby]="_labelId" ' +
'[attr.aria-disabled]="_disabled" ' +
'class="item-cover">' +
@@ -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

View File

@@ -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;
}

View File

@@ -1,8 +1,18 @@
<ion-toolbar><ion-title>Show/Hide When</ion-title></ion-toolbar>
<ion-toolbar>
<ion-title>Show/Hide When</ion-title>
<ion-buttons end>
<button showWhen="ios">iOS</button>
<button showWhen="windows">Windows</button>
<button showWhen="android">Android</button>
</ion-buttons>
</ion-toolbar>
<ion-content padding>
<button showWhen="ios">iOS</button>
<button showWhen="windows">Windows</button>
<button showWhen="android">Android</button>
<p showWhen="ios" style="background:blue; color:white">
showWhen="ios"

View File

@@ -44,6 +44,7 @@ import {Scroll} from '../scroll/scroll';
* | 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.
@@ -371,17 +372,9 @@ export class Slides extends Ion {
console.warn('The "zoom" attribute has been deprecated. Please pass it in options.');
}
if (isPresent(this.change)) {
// beta.5 2016-04-18 deprecated warning
// change has been renamed to didChange
console.warn('The "change" event has been deprecated. Please use "didChange" instead.');
}
if (isPresent(this.slideChangeStart)) {
// beta.5 2016-04-18 deprecated warning
// slideChangeStart has been renamed to willChange
console.warn('The "slideChangeStart" event has been deprecated. Please use "willChange" instead.');
}
// 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);
@@ -827,6 +820,15 @@ export class Slides extends Ion {
return this.slider.activeIndex;
}
/**
* Get the index of the previous slide.
*
* @returns {number} The index number of the previous slide.
*/
getPreviousIndex(): number {
return this.slider.previousIndex;
}
/**
* Get the total number of slides.
*

View File

@@ -3,6 +3,7 @@ export declare class Swiper {
constructor(container: HTMLElement, params: any);
slides: Array<HTMLElement>;
activeIndex: number;
previousIndex: number;
isEnd: boolean;
isBeginning: boolean;
update(): any;

View File

@@ -9,7 +9,7 @@ class MyPage {
@ViewChild('mySlider') slider: Slides;
mySlideOptions = {
initialSlide: 1,
loop: true
loop: false
};
ngAfterViewInit() {
@@ -17,8 +17,9 @@ class MyPage {
}
onSlideChanged() {
let previousIndex = this.slider.getPreviousIndex();
let currentIndex = this.slider.getActiveIndex();
console.log("Current index is", currentIndex);
console.log("Previous index is", previousIndex, "Current index is", currentIndex);
}
goToPrevSlide() {
@@ -30,7 +31,7 @@ class MyPage {
}
goToSlide(index) {
this.slider.slideTo(index, 500, false);
this.slider.slideTo(index);
}
getIndex() {

View File

@@ -1,16 +1,23 @@
<ion-slides #mySlider [options]="mySlideOptions" (didChange)="onSlideChanged()">
<ion-slide padding>
<h1>Slide 1</h1>
<button block (click)="goToPrevSlide()">Navigate Back</button>
<button block (click)="goToNextSlide()">Navigate Forward</button>
<button block (click)="goToSlide(2)">Navigate to 3rd Slide</button>
<button block (click)="getLength()">Get Slide Length</button>
<button block (click)="getIndex()">Get Index</button>
</ion-slide>
<ion-slide padding>
<h1>Slide 2</h1>
<button block (click)="goToPrevSlide()">Navigate Back</button>
<button block (click)="goToNextSlide()">Navigate Forward</button>
<button block (click)="goToSlide(2)">Navigate to 3rd Slide</button>
<button block (click)="getIndex()">Get Index</button>
</ion-slide>
<ion-slide padding>
<h1>Slide 3</h1>
<button block (click)="goToPrevSlide()">Navigate Back</button>
<button block (click)="goToNextSlide()">Navigate Forward</button>
<button block (click)="getIndex()">Get Index</button>
</ion-slide>
</ion-slides>

View File

@@ -10,7 +10,6 @@ $tabbar-ios-item-font-size: 10px !default;
$tabbar-ios-item-icon-size: 30px !default;
$tabbar-ios-height: 49px !default;
$tab-button-ios-min-width: 80px !default;
$tab-button-ios-max-width: 240px !default;
$tab-button-ios-active-color: $toolbar-ios-active-color !default;
$tab-button-ios-inactive-color: $toolbar-ios-inactive-color !default;
@@ -29,7 +28,6 @@ ion-tabs[tabbarPlacement=top] tabbar {
.tab-button {
padding: $tabbar-ios-item-padding;
min-width: $tab-button-ios-min-width;
max-width: $tab-button-ios-max-width;
min-height: $tabbar-ios-height;

View File

@@ -90,7 +90,7 @@ tabbar {
ion-badge,
ion-icon,
span {
opacity: 0.4;
opacity: .4;
}
}

View File

@@ -81,7 +81,7 @@ tabbar {
// Windows Tabbar Color Mixin
// --------------------------------------------------
@mixin tabbar-wp($color-name, $color-base) {
@mixin tabbar-wp($color-name, $color-base, $color-contrast) {
ion-tabs[#{$color-name}] tabbar {
background-color: $color-base;
@@ -104,5 +104,5 @@ tabbar {
// --------------------------------------------------
@each $color-name, $color-base, $color-contrast in get-colors($colors-wp) {
@include tabbar-wp($color-name, $color-base);
@include tabbar-wp($color-name, $color-base, $color-contrast);
}

View File

@@ -59,6 +59,8 @@
<ion-tabs tabbarLayout="title-hide" secondary no-navbar>
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
<ion-tab tabTitle="Radio" tabIcon="musical-notes" [root]="root"></ion-tab>
<ion-tab tabTitle="Messages" tabIcon="chatboxes" [root]="root"></ion-tab>
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
</ion-tabs>

View File

@@ -0,0 +1,8 @@
it('should open toast', function() {
element(by.css('.e2eOpenToast')).click();
});
it('should close with backdrop click', function() {
element(by.css('.backdrop')).click();
});

View File

@@ -0,0 +1,84 @@
import {App, Page, Toast, NavController} from 'ionic-angular';
@Page({
template: `
<ion-navbar *navbar>
<ion-title>Another Page</ion-title>
</ion-navbar>
<ion-content padding>
<p>This is another page to show that the toast stays.</p>
</ion-content>
`
})
class AnotherPage {
}
@Page({
templateUrl: 'main.html'
})
class E2EPage {
constructor(private nav: NavController) { }
showToast() {
const toast = Toast.create({
message: 'User was created successfully',
showCloseButton: true,
enableBackdropDismiss: false
});
toast.onDismiss(() => {
console.log('Dismissed toast');
});
this.nav.present(toast);
setTimeout(() => {
this.nav.push(AnotherPage);
}, 1000);
}
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 gauranteed.',
showCloseButton: true,
closeButtonText: 'Ok'
});
toast.onDismiss(this.dismissHandler);
this.nav.present(toast);
}
private dismissHandler(toast: Toast) {
console.info('Toast onDismiss()');
}
}
@App({
template: '<ion-nav [root]="root"></ion-nav>'
})
class E2EApp {
root = E2EPage;
constructor() {
}
}

View File

@@ -0,0 +1,23 @@
<ion-navbar *navbar>
<ion-title>Toasts</ion-title>
</ion-navbar>
<ion-content padding>
<button block (click)="showToast()">Show Toast and Navigate</button>
<button block (click)="showLongToast()">Show Long Toast</button>
<br />
<button block (click)="showDismissDurationToast()">Custom (1.5s) Duration</button>
<button block (click)="showToastWithCloseButton()" class="e2eOpenToast">With closeButtonText</button>
<p>
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.
</p>
<p>
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.
</p>
<p>
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.
</p>
</ion-content>

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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: `
<div (click)="bdClick()" tappable disable-activated class="backdrop" role="presentation"></div>
<div class="toast-wrapper">
<div class="toast-container">
<div class="toast-message" id="{{hdrId}}" *ngIf="d.message">{{d.message}}</div>
<button clear class="toast-button" *ngIf="d.showCloseButton" (click)="cbClick()">
{{ d.closeButtonText || 'Close' }}
<ion-button-effect></ion-button-effect>
</button>
</div>
</div>
`,
host: {
'role': 'dialog',
'[attr.aria-labelledby]': 'hdrId',
'[attr.aria-describedby]': 'descId'
},
directives: [NgIf, Icon, Button]
})
class ToastCmp {
private d: any;
private descId: string;
private hdrId: string;
private created: number;
private id: number;
private dismissTimeout: number = undefined;
constructor(
private _nav: NavController,
private _viewCtrl: ViewController,
private _config: Config,
private _elementRef: ElementRef,
params: NavParams,
renderer: Renderer
) {
this.d = params.data;
this.created = Date.now();
if (this.d.cssClass) {
renderer.setElementClass(_elementRef.nativeElement, this.d.cssClass, true);
}
this.id = (++toastIds);
if (this.d.message) {
this.hdrId = 'toast-hdr-' + this.id;
}
}
onPageDidEnter() {
const { activeElement }: any = document;
if (activeElement) {
activeElement.blur();
}
let focusableEle = this._elementRef.nativeElement.querySelector('button');
if (focusableEle) {
focusableEle.focus();
}
// if there's a `duration` set, automatically dismiss.
if (this.d.duration) {
this.dismissTimeout =
setTimeout(() => {
this.dismiss('backdrop');
}, this.d.duration);
}
}
bdClick() {
if (this.isEnabled() && this.d.enableBackdropDismiss) {
this.dismiss('backdrop');
}
}
cbClick() {
if (this.isEnabled()) {
this.dismiss('close');
}
}
dismiss(role): Promise<any> {
clearTimeout(this.dismissTimeout);
this.dismissTimeout = undefined;
return this._viewCtrl.dismiss(null, role);
}
isEnabled() {
let tm = this._config.getNumber('overlayCreatedDiff', 750);
return (this.created + tm < Date.now());
}
}
export interface ToastOptions {
message?: string;
cssClass?: string;
duration?: number;
showCloseButton?: boolean;
closeButtonText?: string;
enableBackdropDismiss?: boolean;
dismissOnPageChange?: boolean;
}
class ToastSlideIn extends Transition {
constructor(enteringView, leavingView, opts: TransitionOptions) {
super(opts);
let ele = enteringView.pageRef().nativeElement;
let wrapper = new Animation(ele.querySelector('.toast-wrapper'));
wrapper.fromTo('translateY', '120%', '0%');
this.easing('cubic-bezier(.36,.66,.04,1)').duration(400).add(wrapper);
}
}
class ToastSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = leavingView.pageRef().nativeElement;
let wrapper = new Animation(ele.querySelector('.toast-wrapper'));
wrapper.fromTo('translateY', '0%', '120%');
this.easing('cubic-bezier(.36,.66,.04,1)').duration(300).add(wrapper);
}
}
class ToastMdSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
let wrapper = new Animation(ele.querySelector('.toast-wrapper'));
backdrop.fromTo('opacity', 0, 0);
wrapper.fromTo('translateY', '120%', '0%');
this.easing('cubic-bezier(.36,.66,.04,1)').duration(400).add(backdrop).add(wrapper);
}
}
class ToastMdSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = leavingView.pageRef().nativeElement;
let wrapper = new Animation(ele.querySelector('.toast-wrapper'));
let backdrop = new Animation(ele.querySelector('.backdrop'));
wrapper.fromTo('translateY', '0%', '120%');
backdrop.fromTo('opacity', 0, 0);
this.easing('cubic-bezier(.36,.66,.04,1)').duration(450).add(backdrop).add(wrapper);
}
}
class ToastWpPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
let wrapper = new Animation(ele.querySelector('.toast-wrapper'));
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.3', '1');
backdrop.fromTo('opacity', 0, 0);
this.easing('cubic-bezier(0,0 0.05,1)').duration(200).add(backdrop).add(wrapper);
}
}
class ToastWpPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
let wrapper = new Animation(ele.querySelector('.toast-wrapper'));
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '1.3');
backdrop.fromTo('opacity', 0, 0);
this.easing('ease-out').duration(150).add(backdrop).add(wrapper);
}
}
Transition.register('toast-slide-in', ToastSlideIn);
Transition.register('toast-slide-out', ToastSlideOut);
Transition.register('toast-md-slide-in', ToastMdSlideIn);
Transition.register('toast-md-slide-out', ToastMdSlideOut);
Transition.register('toast-wp-slide-out', ToastWpPopOut);
Transition.register('toast-wp-slide-in', ToastWpPopIn);
let toastIds = -1;

View File

@@ -0,0 +1,44 @@
@import "../../globals.wp";
@import "./toast";
// Windows Phone Toast
// --------------------------------------------------
$toast-wp-text-align: left !default;
$toast-wp-background: rgba(0, 0, 0, 1) !default;
$toast-wp-border-radius: 0 !default;
$toast-wp-button-color: #fff !default;
$toast-wp-title-color: #fff !default;
$toast-wp-title-font-size: 1.4rem !default;
$toast-wp-title-padding: 1.5rem !default;
.toast-wrapper {
position: absolute;
bottom: 0;
left: 0;
z-index: $z-index-overlay-wrapper;
display: block;
margin: auto;
max-width: $toast-max-width;
border-radius: $toast-wp-border-radius;
background: $toast-wp-background;
transform: translate3d(0, 100%, 0);
}
.toast-message {
padding: $toast-wp-title-padding;
font-size: $toast-wp-title-font-size;
color: $toast-wp-title-color;
}
.toast-button {
color: $toast-wp-button-color;
}

View File

@@ -58,6 +58,7 @@ const TOGGLE_VALUE_ACCESSOR = new Provider(
'</div>' +
'<button role="checkbox" ' +
'type="button" ' +
'category="item-cover" ' +
'[id]="id" ' +
'[attr.aria-checked]="_checked" ' +
'[attr.aria-labelledby]="_labelId" ' +

View File

@@ -128,7 +128,7 @@ ion-toggle {
// Windows Color Mixin
// --------------------------------------------------
@mixin toggle-theme-wp($color-name, $color-base) {
@mixin toggle-theme-wp($color-name, $color-base, $color-contrast) {
ion-toggle[#{$color-name}] {
@@ -151,6 +151,6 @@ ion-toggle {
@each $color-name, $color-base, $color-contrast in get-colors($colors-wp) {
@include toggle-theme-wp($color-name, $color-base);
@include toggle-theme-wp($color-name, $color-base, $color-contrast);
}

View File

@@ -6,7 +6,6 @@ import {MenuToggle} from '../components/menu/menu-toggle';
import {MenuClose} from '../components/menu/menu-close';
import {Badge} from '../components/badge/badge';
import {Button} from '../components/button/button';
import {Blur} from '../components/blur/blur';
import {Content} from '../components/content/content';
import {Img} from '../components/img/img';
import {Scroll} from '../components/scroll/scroll';
@@ -93,7 +92,6 @@ import {ShowWhen, HideWhen} from '../components/show-hide-when/show-hide-when';
* - MenuClose
* - Badge
* - Button
* - Blur
* - Content
* - Scroll
* - InfiniteScroll
@@ -154,7 +152,6 @@ export const IONIC_DIRECTIVES = [
Badge,
Button,
Blur,
Content,
Scroll,
InfiniteScroll,

View File

@@ -9,6 +9,9 @@ Config.setModeConfig('ios', {
actionSheetEnter: 'action-sheet-slide-in',
actionSheetLeave: 'action-sheet-slide-out',
toastEnter: 'toast-slide-in',
toastLeave: 'toast-slide-out',
alertEnter: 'alert-pop-in',
alertLeave: 'alert-pop-out',
@@ -44,6 +47,9 @@ Config.setModeConfig('md', {
actionSheetEnter: 'action-sheet-md-slide-in',
actionSheetLeave: 'action-sheet-md-slide-out',
toastEnter: 'toast-md-slide-in',
toastLeave: 'toast-md-slide-out',
alertEnter: 'alert-md-pop-in',
alertLeave: 'alert-md-pop-out',
@@ -82,6 +88,9 @@ Config.setModeConfig('wp', {
actionSheetEnter: 'action-sheet-wp-slide-in',
actionSheetLeave: 'action-sheet-wp-slide-out',
toastEnter: 'toast-wp-slide-in',
toastLeave: 'toast-wp-slide-out',
alertEnter: 'alert-wp-pop-in',
alertLeave: 'alert-wp-pop-out',

View File

@@ -92,7 +92,7 @@ export function App(args: AppMetadata = {}) {
let directives = args.directives ? args.directives.concat(IONIC_DIRECTIVES) : IONIC_DIRECTIVES;
// automatically provide all of Ionic's directives to every component
providers.push(provide(PLATFORM_DIRECTIVES, {useValue: [directives], multi:true}));
providers.push(provide(PLATFORM_DIRECTIVES, {useValue: [directives], multi: true}));
if (args.prodMode) {
enableProdMode();

View File

@@ -152,9 +152,7 @@ export class Platform {
* }
* ```
*
* @param {string} [platformName] optional platformName
* @returns {object} An object with various platform info
*
* @returns {object} An object containing all of the platforms and their versions.
*/
versions(): {[name: string]: PlatformVersion} {
// get all the platforms that have a valid parsed version
@@ -177,48 +175,59 @@ export class Platform {
* Returns a promise when the platform is ready and native functionality
* can be called. If the app is running from within a web browser, then
* the promise will resolve when the DOM is ready. When the app is running
* from an application engine such as Cordova, then the promise
* will resolve when Cordova triggers the `deviceready` event.
* from an application engine such as Cordova, then the promise will
* resolve when Cordova triggers the `deviceready` event.
*
* The resolved value is the `readySource`, which states which platform
* ready was used. For example, when Cordova is ready, the resolved ready
* source is `cordova`. The default ready source value will be `dom`. The
* `readySource` is useful if different logic should run depending on the
* platform the app is running from. For example, only Cordova can execute
* the status bar plugin, so the web should not run status bar plugin logic.
*
* ```
* import {Platform} from 'ionic-angular';
* import {App, Platform} from 'ionic-angular';
*
* @Page({...})
* export MyPage {
* @App({...})
* export MyApp {
* constructor(platform: Platform) {
* platform.ready().then(() => {
* console.log('Platform ready');
* // The platform is now ready, execute any native code you want
* platform.ready().then((readySource) => {
* console.log('Platform ready from', readySource);
* // Platform now ready, execute any required native code
* });
* }
* }
* ```
* @returns {promise}
*/
ready(): Promise<any> {
// this is the default if it's not replaced by the engine
// if there was no custom ready method from the engine
// then use the default DOM ready
ready(): Promise<string> {
return this._readyPromise;
}
/**
* @private
* This should be triggered by the engine when the platform is
* ready. If there was no custom prepareReady method from the engine,
* such as Cordova or Electron, then it uses the default DOM ready.
*/
triggerReady() {
triggerReady(readySource: string) {
this._zone.run(() => {
this._readyResolve();
this._readyResolve(readySource);
});
}
/**
* @private
* This is the default prepareReady if it's not replaced by an engine,
* such as Cordova or Electron. If there was no custom prepareReady
* method from an engine then it uses the method below, which triggers
* the platform ready on the DOM ready event, and the default resolved
* value is `dom`.
*/
prepareReady() {
// this is the default prepareReady if it's not replaced by the engine
// if there was no custom ready method from the engine
// then use the default DOM ready
ready(this.triggerReady.bind(this));
ready(() => {
this.triggerReady('dom');
});
}
/**
@@ -292,7 +301,9 @@ export class Platform {
// called by engines (the browser)that do not provide them
/**
* @private
* The `exitApp` method is useful when running from a native platform,
* such as Cordova. This adds the ability to place the Cordova app
* in the background.
*/
exitApp() {}
@@ -300,17 +311,29 @@ export class Platform {
// **********************************************
/**
* @private
* The back button event is emitted when the user presses the native
* platform's back button, also referred to as the "hardware" back button.
* This event is only emitted within Cordova apps running on Android and
* Windows platforms. This event is not fired on iOS since iOS doesn't come
* with a hardware back button in the same sense an Android or Windows device
* does. It's important to note that this event does not emit when the Ionic
* app's back button within the navbar is clicked, but this event is only
* referencing the platform's hardward back button.
*/
backButton: EventEmitter<any> = new EventEmitter();
/**
* @private
* The pause event emits when the native platform puts the application
* into the background, typically when the user switches to a different
* application. This event would emit when a Cordova app is put into
* the background, however, it would not fire on a standard web browser.
*/
pause: EventEmitter<any> = new EventEmitter();
/**
* @private
* The resume event emits when the native platform pulls the application
* out from the background. This event would emit when a Cordova app comes
* out from the background, however, it would not fire on a standard web browser.
*/
resume: EventEmitter<any> = new EventEmitter();

View File

@@ -175,28 +175,28 @@ Platform.register({
doc.addEventListener('deviceready', function() {
// 3) cordova deviceready event triggered
// add cordova listeners to fire platform events
// add cordova listeners to emit platform events
doc.addEventListener('backbutton', function() {
p.backButton.emit(null);
});
// doc.addEventListener('pause', function() {
// p.pause.emit(null);
// });
// doc.addEventListener('resume', function() {
// p.resume.emit(null);
// });
doc.addEventListener('pause', function() {
p.pause.emit(null);
});
doc.addEventListener('resume', function() {
p.resume.emit(null);
});
// cordova has its own exitApp method
p.exitApp = function() {
win.navigator.app.exitApp();
};
// cordova has fully loaded and we've added listeners
p.triggerReady();
p.triggerReady('cordova');
});
});
};
// cordova has its own exitApp method
p.exitApp = function() {
win.navigator.app.exitApp();
};
},
isMatch(): boolean {
return !!(win.cordova || win.PhoneGap || win.phonegap);

View File

@@ -1,7 +1,7 @@
{
"private": "true",
"name": "ionic2",
"version": "2.0.0-beta.4",
"version": "2.0.0-beta.6",
"license": "MIT",
"repository": {
"type": "git",
@@ -17,7 +17,7 @@
"colors": "^1.1.2",
"es6-shim": "^0.35.0",
"inquirer": "0.11.0",
"ionicons": "3.0.0-alpha.3",
"ionicons": "3.0.0",
"lodash": "3.10.1",
"mkdirp-no-bin": "0.5.1",
"q": "1.4.1",
@@ -91,4 +91,4 @@
"path": "node_modules/ionic-cz-conventional-changelog"
}
}
}
}

View File

@@ -37,7 +37,9 @@ function run {
./node_modules/.bin/gulp demos --production=true
# process new docs
rm -R $DOCS_DEST/api
if [ -d "$DOCS_DEST/api" ]; then
rm -R $DOCS_DEST/api
fi
./node_modules/.bin/gulp docs --doc-version="$VERSION_NAME"
# compile sass vars json for ionic-site docs

View File

@@ -10,7 +10,5 @@ import {Page, NavController} from 'ionic-angular';
templateUrl: 'build/<%= directory %>/<%= fileName %>/<%= fileName %>.html',
})
export class <%= jsClassName %> {
constructor(public nav: NavController) {
this.nav = nav;
}
constructor(public nav: NavController) {}
}