mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
112 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8dc08f9c1f | ||
|
|
bc7bb21f1a | ||
|
|
016b90da47 | ||
|
|
0f5c47db15 | ||
|
|
86495e111d | ||
|
|
fba6ff0638 | ||
|
|
30f69c8a16 | ||
|
|
1beef75c80 | ||
|
|
58e1d79518 | ||
|
|
0480f73f8e | ||
|
|
f39c3811c5 | ||
|
|
6f7acdbddf | ||
|
|
bcc85d9144 | ||
|
|
00fbded168 | ||
|
|
5cad96570f | ||
|
|
e3a8d27ec1 | ||
|
|
d8b65da6ac | ||
|
|
70b5b6b5e5 | ||
|
|
5094feec89 | ||
|
|
1ca7df75ed | ||
|
|
877d8211d5 | ||
|
|
a8731dfc98 | ||
|
|
7803998542 | ||
|
|
8bd2f24d06 | ||
|
|
63f728f517 | ||
|
|
61935602a1 | ||
|
|
1a4aacf8be | ||
|
|
5a5da39a1e | ||
|
|
c7645ee59d | ||
|
|
2743c63537 | ||
|
|
7a1342caa1 | ||
|
|
3564bcfe1b | ||
|
|
f149c5ee95 | ||
|
|
2791c40c29 | ||
|
|
54ac2e393f | ||
|
|
dc958c3e2c | ||
|
|
9f86e10f46 | ||
|
|
8041eedf22 | ||
|
|
ef85ba6c1f | ||
|
|
6dee17b89b | ||
|
|
c10f72b1e2 | ||
|
|
47e3c70bf3 | ||
|
|
a91a68e198 | ||
|
|
3e0d43e7dc | ||
|
|
d0847aabdb | ||
|
|
63b0f0aaf6 | ||
|
|
10f4df42d0 | ||
|
|
f4452b5d33 | ||
|
|
20c9dd7e64 | ||
|
|
6db8c147a6 | ||
|
|
3c046b413b | ||
|
|
30dc247404 | ||
|
|
ac52d3b724 | ||
|
|
435f5c4db0 | ||
|
|
30047f004e | ||
|
|
75bfbad21e | ||
|
|
2273fb5d47 | ||
|
|
bb574743d9 | ||
|
|
d0ae810bae | ||
|
|
344589a00e | ||
|
|
dc6c5863fb | ||
|
|
f7ac32bbf1 | ||
|
|
c0033f512a | ||
|
|
305c306b14 | ||
|
|
9aedc9dc52 | ||
|
|
fe751f7ac3 | ||
|
|
5d2974f2d2 | ||
|
|
133a0f9379 | ||
|
|
bb966e5a31 | ||
|
|
f0c6948ef8 | ||
|
|
ad40b3b86b | ||
|
|
cb5d505d64 | ||
|
|
2cffb44187 | ||
|
|
35a0e228de | ||
|
|
7d8696c050 | ||
|
|
1c25acbb1f | ||
|
|
64cac79da6 | ||
|
|
59a1e3def1 | ||
|
|
e3c60c5de4 | ||
|
|
f5bbdcd32e | ||
|
|
6322134994 | ||
|
|
dd6de0d625 | ||
|
|
c9cb9ae15a | ||
|
|
6256b0fa66 | ||
|
|
a40b872975 | ||
|
|
57dc22d173 | ||
|
|
0f4ed1c7f8 | ||
|
|
1c76cde986 | ||
|
|
76a9454285 | ||
|
|
0570e3e262 | ||
|
|
4c57326dc4 | ||
|
|
0624a77afe | ||
|
|
7af93d23b8 | ||
|
|
42d29f4331 | ||
|
|
ecc4e4a530 | ||
|
|
18517660d4 | ||
|
|
117003e9e4 | ||
|
|
041689b5f5 | ||
|
|
e354f21936 | ||
|
|
73ab06e360 | ||
|
|
d4fce8995b | ||
|
|
2afb936536 | ||
|
|
e526ce1da5 | ||
|
|
39909d0f68 | ||
|
|
261bc4d5f4 | ||
|
|
f14d7d6524 | ||
|
|
2edb085d4d | ||
|
|
638ab70309 | ||
|
|
556745191f | ||
|
|
3de6d24a40 | ||
|
|
8ba1fcac45 | ||
|
|
4a56cbba29 |
18
.github/CONTRIBUTING.md
vendored
18
.github/CONTRIBUTING.md
vendored
@@ -5,7 +5,7 @@ Thanks for your interest in contributing to the Ionic Framework! :tada:
|
||||
|
||||
## Contributing Etiquette
|
||||
|
||||
Please see our [Contributor Code of Conduct](https://github.com/driftyco/ionic/blob/master/CODE_OF_CONDUCT.md) for information on our rules of conduct.
|
||||
Please see our [Contributor Code of Conduct](https://github.com/ionic-team/ionic/blob/master/CODE_OF_CONDUCT.md) for information on our rules of conduct.
|
||||
|
||||
|
||||
## Creating an Issue
|
||||
@@ -18,16 +18,16 @@ Please see our [Contributor Code of Conduct](https://github.com/driftyco/ionic/b
|
||||
|
||||
* Issues with no clear steps to reproduce will not be triaged. If an issue is labeled with "needs reply" and receives no further replies from the author of the issue for more than 5 days, it will be closed.
|
||||
|
||||
* 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.
|
||||
* 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/ionic-team/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.
|
||||
|
||||
* 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.
|
||||
* Next, [create a new issue](https://github.com/ionic-team/ionic/issues/new) that thoroughly explains the problem. Please fill out the populated issue form before submitting the issue.
|
||||
|
||||
|
||||
## Creating a Pull Request
|
||||
|
||||
* 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.
|
||||
|
||||
* 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!
|
||||
* Looking for an issue to fix? Make sure to look through our issues with the [help wanted](https://github.com/ionic-team/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) label!
|
||||
|
||||
### Setup
|
||||
|
||||
@@ -85,9 +85,9 @@ Please see our [Contributor Code of Conduct](https://github.com/driftyco/ionic/b
|
||||
```
|
||||
|
||||
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
|
||||
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/ionic-team/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
|
||||
4. If the change affects the component documentation, create an issue on the `ionic-site` repo: https://github.com/ionic-team/ionic-site/issues
|
||||
|
||||
|
||||
#### Adding Demos
|
||||
@@ -106,12 +106,12 @@ Please see our [Contributor Code of Conduct](https://github.com/driftyco/ionic/b
|
||||
```
|
||||
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
|
||||
5. If the change affects the component demos, create an issue on the `ionic-site` repo: https://github.com/ionic-team/ionic-site/issues
|
||||
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
We have very precise rules over how our git commit messages should be formatted. This leads to readable messages that are easy to follow when looking through the project history. We also use the git commit messages to generate our [changelog](https://github.com/driftyco/ionic/blob/master/CHANGELOG.md). (Ok you got us, it's basically Angular's commit message format).
|
||||
We have very precise rules over how our git commit messages should be formatted. This leads to readable messages that are easy to follow when looking through the project history. We also use the git commit messages to generate our [changelog](https://github.com/ionic-team/ionic/blob/master/CHANGELOG.md). (Ok you got us, it's basically Angular's commit message format).
|
||||
|
||||
`type(scope): subject`
|
||||
|
||||
@@ -143,4 +143,4 @@ The subject contains succinct description of the change:
|
||||
|
||||
## License
|
||||
|
||||
By contributing your code to the driftyco/ionic GitHub Repository, you agree to license your contribution under the MIT license.
|
||||
By contributing your code to the ionic-team/ionic GitHub Repository, you agree to license your contribution under the MIT license.
|
||||
|
||||
4
.github/ISSUE_TEMPLATE.md
vendored
4
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,5 +1,5 @@
|
||||
**Ionic version:** (check one with "x")
|
||||
[ ] **1.x** (For Ionic 1.x issues, please use https://github.com/driftyco/ionic-v1)
|
||||
[ ] **1.x** (For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1)
|
||||
[ ] **2.x**
|
||||
[ ] **3.x**
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
For Ionic V1 issues - http://plnkr.co/edit/Xo1QyAUx35ny1Xf9ODHx?p=preview
|
||||
|
||||
For Ionic issues - http://plnkr.co/edit/z0DzVL?p=preview
|
||||
For Ionic issues - http://plnkr.co/edit/cpeRJs?p=preview
|
||||
-->
|
||||
|
||||
**Related code:**
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
|
||||
# See config at https://github.com/brigade/scss-lint/blob/master/config/default.yml
|
||||
|
||||
plugin_directories: ['.scss-linters']
|
||||
|
||||
exclude:
|
||||
- 'src/components/item/item.ios.scss'
|
||||
- 'src/components/item/item.md.scss'
|
||||
- 'src/components/list/list.ios.scss'
|
||||
- 'src/components/show-hide-when/**'
|
||||
- 'src/components/slides/**'
|
||||
- 'src/themes/ionic.mixins.scss'
|
||||
- 'src/themes/license.scss'
|
||||
- 'src/themes/util.scss'
|
||||
@@ -19,6 +16,9 @@ linters:
|
||||
ColorVariable:
|
||||
enabled: false
|
||||
|
||||
DefaultRule:
|
||||
enabled: true
|
||||
|
||||
DuplicateProperty:
|
||||
enabled: false
|
||||
|
||||
@@ -56,11 +56,6 @@ linters:
|
||||
- justify-content
|
||||
- order
|
||||
-
|
||||
- margin-top
|
||||
- margin-bottom
|
||||
- padding-top
|
||||
- padding-bottom
|
||||
-
|
||||
- width
|
||||
- min-width
|
||||
- max-width
|
||||
@@ -140,7 +135,6 @@ linters:
|
||||
- background-color
|
||||
- background-image
|
||||
- background-repeat
|
||||
- background-position
|
||||
- background-size
|
||||
|
||||
# Other
|
||||
@@ -163,7 +157,6 @@ linters:
|
||||
|
||||
- transform
|
||||
- transform-box
|
||||
- transform-origin
|
||||
- transform-style
|
||||
|
||||
- transition
|
||||
@@ -188,27 +181,33 @@ linters:
|
||||
enabled: true
|
||||
style: double_quotes
|
||||
|
||||
SelectorDepth:
|
||||
enabled: true
|
||||
max_depth: 5
|
||||
|
||||
PropertySpelling:
|
||||
extra_properties:
|
||||
- contain
|
||||
disabled_properties:
|
||||
- background-position
|
||||
- direction
|
||||
- right
|
||||
- left
|
||||
|
||||
- float
|
||||
|
||||
- padding
|
||||
- padding-left
|
||||
- padding-right
|
||||
|
||||
- padding-top
|
||||
- padding-bottom
|
||||
- margin
|
||||
- margin-left
|
||||
- margin-right
|
||||
|
||||
- margin-top
|
||||
- margin-bottom
|
||||
- border-radius
|
||||
- border-top-left-radius
|
||||
- border-top-right-radius
|
||||
- border-bottom-right-radius
|
||||
- border-bottom-left-radius
|
||||
|
||||
- text-align
|
||||
- transform-origin
|
||||
18
.scss-linters/default_rule.rb
Normal file
18
.scss-linters/default_rule.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
module SCSSLint
|
||||
# Reports the use of !default at the end of variable declarations.
|
||||
class Linter::DefaultRule < Linter
|
||||
include LinterRegistry
|
||||
|
||||
def visit_function(node)
|
||||
return true
|
||||
end
|
||||
|
||||
def visit_variable(node)
|
||||
return if source_from_range(node.source_range).include?('!default')
|
||||
|
||||
return unless node_ancestor(node, 2).nil?
|
||||
|
||||
add_lint(node, '!default should be used')
|
||||
end
|
||||
end
|
||||
end
|
||||
1626
CHANGELOG.md
1626
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
12
README.md
12
README.md
@@ -1,5 +1,5 @@
|
||||
[](https://badge.fury.io/js/ionic-angular)
|
||||
[](https://circleci.com/gh/driftyco/ionic)
|
||||
[](https://circleci.com/gh/ionic-team/ionic)
|
||||
|
||||
# Ionic
|
||||
|
||||
@@ -17,21 +17,21 @@ started using Ionic.
|
||||
|
||||
Start a new project by following our quick [Getting Started guide](https://ionicframework.com/getting-started/).
|
||||
We would love to hear from you! If you have any feedback or run into issues using our framework, please file
|
||||
an [issue](https://github.com/driftyco/ionic/issues/new) on this repository.
|
||||
an [issue](https://github.com/ionic-team/ionic/issues/new) on this repository.
|
||||
|
||||
### Contributing
|
||||
|
||||
Thanks for your interest in contributing! Read up on our guidelines for
|
||||
[contributing](https://github.com/driftyco/ionic/blob/master/.github/CONTRIBUTING.md)
|
||||
and then look through our issues with a [help wanted](https://github.com/driftyco/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
[contributing](https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md)
|
||||
and then look through our issues with a [help wanted](https://github.com/ionic-team/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
label.
|
||||
|
||||
### Examples
|
||||
|
||||
The [Ionic Conference App](https://github.com/driftyco/ionic-conference-app) is a full featured Ionic app.
|
||||
The [Ionic Conference App](https://github.com/ionic-team/ionic-conference-app) is a full featured Ionic app.
|
||||
It is the perfect starting point for learning and building your own app.
|
||||
|
||||
### Ionic V1
|
||||
|
||||
The source code for Ionic V1 has been moved to [driftyco/ionic-v1](https://github.com/driftyco/ionic-v1).
|
||||
The source code for Ionic V1 has been moved to [ionic-team/ionic-v1](https://github.com/ionic-team/ionic-v1).
|
||||
Please open any issues and pull requests related to Ionic V1 on that repository.
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
|
||||
<h4>Icons</h4>
|
||||
|
||||
<button ion-button icon-left color="dark">
|
||||
<button ion-button icon-start color="dark">
|
||||
<ion-icon name="star"></ion-icon>
|
||||
Left Icon
|
||||
</button>
|
||||
|
||||
<button ion-button icon-right color="dark">
|
||||
<button ion-button icon-end color="dark">
|
||||
Right Icon
|
||||
<ion-icon name="star"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<ion-icon name="trash"></ion-icon>
|
||||
</button>
|
||||
</ion-item-options>
|
||||
<ion-item-options (ionSwipe)="download(item)" icon-left>
|
||||
<ion-item-options (ionSwipe)="download(item)" icon-start>
|
||||
<button ion-button color="dark" (click)="more(item)">
|
||||
<ion-icon name="volume-off"></ion-icon>
|
||||
Mute
|
||||
@@ -85,7 +85,7 @@
|
||||
</ion-content>
|
||||
|
||||
<style>
|
||||
/* TODO: spinner is dropping classes so we have to use ids: https://github.com/driftyco/ionic/issues/7087 */
|
||||
/* TODO: spinner is dropping classes so we have to use ids: https://github.com/ionic-team/ionic/issues/7087 */
|
||||
#archive-spinner,
|
||||
#download-spinner,
|
||||
.archiving .expand-hide,
|
||||
@@ -93,7 +93,7 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* TODO: spinner doesn't have a good way to do this yet: https://github.com/driftyco/ionic/issues/7087 */
|
||||
/* TODO: spinner doesn't have a good way to do this yet: https://github.com/ionic-team/ionic/issues/7087 */
|
||||
#archive-spinner.spinner-ios line,
|
||||
#archive-spinner.spinner-crescent circle {
|
||||
stroke: #fff;
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-right (click)="goToPage2()">
|
||||
<button ion-button icon-end (click)="goToPage2()">
|
||||
Show Loading and Navigate
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
</ion-buttons>
|
||||
<ion-title>Solid</ion-title>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-right solid color="secondary">
|
||||
<button ion-button icon-end solid color="secondary">
|
||||
Help
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
</button>
|
||||
@@ -69,7 +69,7 @@
|
||||
</button>
|
||||
</ion-buttons>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-right outline color="secondary">
|
||||
<button ion-button icon-end outline color="secondary">
|
||||
Help
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Hair Color</ion-label>
|
||||
<ion-select [(ngModel)]="hairColor" okText="Okay" cancelText="Dismiss" [compareWith]="compareFn">
|
||||
<ion-option *ngFor="let o of hairColorData" [value]="o">{{o.text}}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Gaming</ion-label>
|
||||
<ion-select [(ngModel)]="gaming" okText="Okay" cancelText="Dismiss">
|
||||
@@ -147,6 +154,13 @@
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Skittles</ion-label>
|
||||
<ion-select [(ngModel)]="skittles" multiple="true" okText="Okay" cancelText="Dismiss" [compareWith]="compareFn">
|
||||
<ion-option *ngFor="let o of skittlesData" [value]="o">{{o.text}}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Disabled</ion-label>
|
||||
<ion-select multiple disabled="true">
|
||||
|
||||
@@ -10,6 +10,10 @@ export class PageOne {
|
||||
petAlertOpts: any;
|
||||
petData: any;
|
||||
pets: Array<string>;
|
||||
hairColorData: any;
|
||||
hairColor: any;
|
||||
skittlesData: any;
|
||||
skittles: Array<any>;
|
||||
notifications: string = 'mute_1';
|
||||
rating: number = 2;
|
||||
|
||||
@@ -31,9 +35,37 @@ export class PageOne {
|
||||
{ text: 'Honey Badger', value: 'honeybadger' },
|
||||
];
|
||||
|
||||
this.hairColorData = [
|
||||
{ text: 'Brown', value: 'brown' },
|
||||
{ text: 'Blonde', value: 'blonde' },
|
||||
{ text: 'Black', value: 'black' },
|
||||
{ text: 'Red', value: 'red' }
|
||||
];
|
||||
|
||||
// Pre-selected object with different object reference
|
||||
this.hairColor = { text: 'Brown', value: 'brown' };
|
||||
|
||||
this.skittlesData = [
|
||||
{ text: 'Red', value: 'red' },
|
||||
{ text: 'Orange', value: 'orange' },
|
||||
{ text: 'Yellow', value: 'yellow' },
|
||||
{ text: 'Green', value: 'green' },
|
||||
{ text: 'Purple', value: 'purple' }
|
||||
];
|
||||
|
||||
// Pre-selected object with different object reference
|
||||
this.skittles = [
|
||||
{ text: 'Red', value: 'red' },
|
||||
{ text: 'Purple', value: 'purple' }
|
||||
];
|
||||
|
||||
this.pets = ['cat', 'dog'];
|
||||
}
|
||||
|
||||
compareFn(option1: any, option2: any) {
|
||||
return option1.value === option2.value;
|
||||
}
|
||||
|
||||
monthChange(val: any) {
|
||||
console.log('Month Change:', val);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
|
||||
<!-- Icons right of text -->
|
||||
<ion-tabs tabs-only tabsLayout="icon-right" selectedIndex="0" color="light">
|
||||
<ion-tabs tabs-only tabsLayout="icon-end" selectedIndex="0" color="light">
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root" tabBadge="4" tabBadgeStyle="secondary"></ion-tab>
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
|
||||
<!-- Icons left of text -->
|
||||
<ion-tabs tabs-only tabsLayout="icon-left" color="dark">
|
||||
<ion-tabs tabs-only tabsLayout="icon-start" color="dark">
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root" tabBadge="1" tabBadgeStyle="danger"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
</ion-buttons>
|
||||
<ion-title>Solid</ion-title>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-right solid color="secondary">
|
||||
<button ion-button icon-end solid color="secondary">
|
||||
Help
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
</button>
|
||||
@@ -69,7 +69,7 @@
|
||||
</button>
|
||||
</ion-buttons>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-right outline color="secondary">
|
||||
<button ion-button icon-end outline color="secondary">
|
||||
Help
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
</ion-buttons>
|
||||
<ion-title>Solid</ion-title>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-right solid color="secondary">
|
||||
<button ion-button icon-end solid color="secondary">
|
||||
Help
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
</button>
|
||||
@@ -69,7 +69,7 @@
|
||||
</button>
|
||||
</ion-buttons>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-right outline color="secondary">
|
||||
<button ion-button icon-end outline color="secondary">
|
||||
Help
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
</button>
|
||||
|
||||
35
package.json
35
package.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "ionic2",
|
||||
"version": "3.2.1",
|
||||
"description": "A powerful framework for building mobile and progressive web apps with JavaScript and Angular 2",
|
||||
"version": "3.4.2",
|
||||
"description": "A powerful framework for building mobile and progressive web apps with JavaScript and Angular",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
"framework",
|
||||
@@ -17,25 +17,26 @@
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/driftyco/ionic.git"
|
||||
"url": "https://github.com/ionic-team/ionic.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "gulp validate",
|
||||
"test:generators": "jasmine-node ./tooling/spec",
|
||||
"link": "gulp release.prepareReleasePackage && cd dist/ionic-angular && npm link"
|
||||
"link": "gulp release.prepareReleasePackage && cd dist/ionic-angular && npm link",
|
||||
"tsc": "tsc --outdir .tmp"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/common": "4.1.2",
|
||||
"@angular/compiler": "4.1.2",
|
||||
"@angular/compiler-cli": "4.1.2",
|
||||
"@angular/core": "4.1.2",
|
||||
"@angular/forms": "4.1.2",
|
||||
"@angular/http": "4.1.2",
|
||||
"@angular/platform-browser": "4.1.2",
|
||||
"@angular/platform-browser-dynamic": "4.1.2",
|
||||
"@angular/common": "4.1.3",
|
||||
"@angular/compiler": "4.1.3",
|
||||
"@angular/compiler-cli": "4.1.3",
|
||||
"@angular/core": "4.1.3",
|
||||
"@angular/forms": "4.1.3",
|
||||
"@angular/http": "4.1.3",
|
||||
"@angular/platform-browser": "4.1.3",
|
||||
"@angular/platform-browser-dynamic": "4.1.3",
|
||||
"ionicons": "~3.0.0",
|
||||
"rxjs": "5.1.1",
|
||||
"zone.js": "^0.8.10"
|
||||
"rxjs": "5.4.0",
|
||||
"zone.js": "0.8.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ionic/app-scripts": "1.3.7",
|
||||
@@ -131,8 +132,8 @@
|
||||
"through2": "2.0.1",
|
||||
"ts-node": "1.3.0",
|
||||
"tslint": "3.15.1",
|
||||
"tslint-ionic-rules": "0.0.7",
|
||||
"typescript": "~2.3.2",
|
||||
"tslint-ionic-rules": "0.0.8",
|
||||
"typescript": "~2.3.3",
|
||||
"vinyl": "1.2.0",
|
||||
"webpack": "^2.1.0-beta.27",
|
||||
"yargs": "5.0.0"
|
||||
@@ -146,4 +147,4 @@
|
||||
"pre-push#master": [
|
||||
"test"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ All of these commands require you to run `npm install` first. To see a full list
|
||||
|
||||
### Committing
|
||||
|
||||
Please follow the commit message format in [CONTRIBUTING.md](https://github.com/driftyco/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format).
|
||||
Please follow the commit message format in [CONTRIBUTING.md](https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format).
|
||||
|
||||
|
||||
### Installing Nightly Version
|
||||
@@ -110,6 +110,12 @@ It does not work for windows, linux, or non retina macs.
|
||||
|
||||
- `--dev` runs a dev build when building the e2e tests. This build takes much less time than a production build, so it is advisable to use this when doing quick validation.
|
||||
|
||||
#### Errors
|
||||
|
||||
If you are having getting an error running snapshot such as `SessionNotCreatedError: session not created exception` or `UnknownError: Connection refused` the solution is to download the chromedriver from here: http://chromedriver.storage.googleapis.com/index.html?path=2.24/ and then move it into your `protractor/selenium` folder
|
||||
|
||||
Running `webdriver-manager help` should show you what directory the webdriver is at under the options. For example, yours may be at `/usr/local/lib/node_modules/protractor/selenium` or if you use nvm `/Users/{username}/.nvm/versions/node/v7.5.0/lib/node_modules/protractor/selenium`.
|
||||
|
||||
### Running Tests
|
||||
|
||||
1. `gulp validate`
|
||||
@@ -119,7 +125,7 @@ It does not work for windows, linux, or non retina macs.
|
||||
|
||||
**Requires Ruby. Skip this step entirely if you are unable to install Ruby.**
|
||||
|
||||
1. See the [Sass Guidelines](https://github.com/driftyco/ionic/blob/master/.github/CONTRIBUTING.md#sass-changes) for editing the Sass.
|
||||
1. See the [Sass Guidelines](https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#sass-changes) for editing the Sass.
|
||||
2. Install the linter: `gem install scss_lint`
|
||||
3. Run `gulp lint.sass` and fix any linter errors.
|
||||
|
||||
@@ -160,13 +166,13 @@ It does not work for windows, linux, or non retina macs.
|
||||
|
||||
### Releasing Component Demos
|
||||
|
||||
Ionic Component demos are automatically compiled and deployed to the [ionic staging site](http://ionic-site-staging.herokuapp.com/) on every commit in [ionic-preview-app](https://github.com/driftyco/ionic-preview-app). No action is necessary.
|
||||
Ionic Component demos are automatically compiled and deployed to the [ionic staging site](http://ionic-site-staging.herokuapp.com/) on every commit in [ionic-preview-app](https://github.com/ionic-team/ionic-preview-app). No action is necessary.
|
||||
|
||||
If you'd like to manually update the demos, follow the steps on the preview app for [running locally on the site](https://github.com/driftyco/ionic-preview-app#running-locally-on-the-site).
|
||||
If you'd like to manually update the demos, follow the steps on the preview app for [running locally on the site](https://github.com/ionic-team/ionic-preview-app#running-locally-on-the-site).
|
||||
|
||||
|
||||
### Releasing API Demos
|
||||
|
||||
Ionic API demos are automatically compiled and deployed to the [ionic staging site](http://ionic-site-staging.herokuapp.com/) on every commit. No action is necessary.
|
||||
|
||||
If you'd like to manually update the demos, clone the [`ionic-site`](https://github.com/driftyco/ionic-site) repo as a sibling of `ionic`. From `ionic` run `gulp demos` and then `gulp docs`, and it'll compile and copy the demos to the `ionic-site` repo, ready for testing.
|
||||
If you'd like to manually update the demos, clone the [`ionic-site`](https://github.com/ionic-team/ionic-site) repo as a sibling of `ionic`. From `ionic` run `gulp demos` and then `gulp docs`, and it'll compile and copy the demos to the `ionic-site` repo, ready for testing.
|
||||
|
||||
@@ -4,7 +4,7 @@ var path = require('path');
|
||||
module.exports = {
|
||||
copyAssets: {
|
||||
src: [path.join(path.dirname(process.env.IONIC_APP_ENTRY_POINT), '..', 'assets', '**', '*')],
|
||||
dest: '{{WWW}}/assets'
|
||||
dest: path.join('{{WWW}}', 'assets')
|
||||
},
|
||||
copyIndexContent: {
|
||||
src: [path.join(process.cwd(), 'scripts', 'demos', 'index.html')],
|
||||
@@ -12,7 +12,7 @@ module.exports = {
|
||||
},
|
||||
copyFonts: {
|
||||
src: [`${process.cwd()}/node_modules/ionicons/dist/fonts/**/*`, `${process.cwd()}/src/fonts/**/*`],
|
||||
dest: '{{WWW}}/assets/fonts'
|
||||
dest: path.join('{{WWW}}', 'assets', 'fonts')
|
||||
},
|
||||
copyPolyfills: {
|
||||
src: [path.join(process.cwd(), 'dist', 'demos', 'polyfills', 'polyfills.js')],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var path = require('path');
|
||||
|
||||
var watch = require('../../node_modules/@ionic/app-scripts/dist/watch');
|
||||
var watch = require(path.join('..', '..', 'node_modules', '@ionic', 'app-scripts', 'dist', 'watch'));
|
||||
|
||||
var entryPointDirectory = path.dirname(process.env.IONIC_APP_ENTRY_POINT)
|
||||
|
||||
@@ -9,7 +9,7 @@ module.exports = {
|
||||
paths: [path.join(entryPointDirectory, '..', '**', '*.(ts|html|s(c|a)ss)')],
|
||||
options: { ignored: [path.join(entryPointDirectory, '..', '**', '*.spec.ts'),
|
||||
path.join(entryPointDirectory, '..', '**', '*.e2e.ts'),
|
||||
'**/*.DS_Store'] },
|
||||
path.join('**', '*.DS_Store')] },
|
||||
callback: watch.buildUpdate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,10 +63,10 @@ function run {
|
||||
# if no changes, don't commit
|
||||
if [[ "$CHANGES" == "" ]]; then
|
||||
echo "-- No changes detected for the following commit, docs not updated."
|
||||
echo "https://github.com/driftyco/$CIRCLE_PROJECT_REPONAME/commit/$CIRCLE_SHA1"
|
||||
echo "https://github.com/ionic-team/$CIRCLE_PROJECT_REPONAME/commit/$CIRCLE_SHA1"
|
||||
else
|
||||
git add -A
|
||||
git commit -am "Automated build of ionic v$VERSION driftyco/$CIRCLE_PROJECT_REPONAME@$CIRCLE_SHA1"
|
||||
git commit -am "Automated build of ionic v$VERSION ionic-team/$CIRCLE_PROJECT_REPONAME@$CIRCLE_SHA1"
|
||||
# in case a different commit was pushed to ionic-site during doc/demo gen,
|
||||
# try to rebase around it before pushing
|
||||
git fetch
|
||||
|
||||
@@ -87,8 +87,8 @@ module.exports = function(gulp, flags) {
|
||||
}));
|
||||
callback();
|
||||
}).on('end', function() {
|
||||
gutil.log("Writing to file at", gutil.colors.cyan("/driftyco/ionic/" + outputFile));
|
||||
gutil.log("Place this file in", gutil.colors.cyan("/driftyco/ionic-site/" + config.v2DocsDir + "/theming/overriding-ionic-variables/"), "in order to update the docs");
|
||||
gutil.log("Writing to file at", gutil.colors.cyan("/ionic-team/ionic/" + outputFile));
|
||||
gutil.log("Place this file in", gutil.colors.cyan("/ionic-team/ionic-site/" + config.v2DocsDir + "/theming/overriding-ionic-variables/"), "in order to update the docs");
|
||||
mkdirp.sync('tmp');
|
||||
fs.writeFileSync(outputFile, JSON.stringify(variables));
|
||||
}));
|
||||
|
||||
@@ -7,7 +7,7 @@ path: ""
|
||||
category: api
|
||||
id: api
|
||||
title: Javascript
|
||||
header_sub_title: Extend Ionic even further with the power of AngularJS
|
||||
header_sub_title: Extend Ionic even further with the power of Angular
|
||||
searchable: false
|
||||
---
|
||||
|
||||
@@ -15,9 +15,6 @@ searchable: false
|
||||
|
||||
<img class="section-header" src="/img/docs/api-intro-header.png" />
|
||||
|
||||
|
||||
Ionic takes everything you know and loved about Ionic V1, and builds on top of it to provide a much more flexible framework.
|
||||
|
||||
In the API docs, you'll find two kinds of doc pages: Component and Service APIs.
|
||||
|
||||
The Component APIs include classes like `Checkbox`, `Toggle` or `Item` and show you how to use them, in addition to listing their selectors, available properties and events.
|
||||
|
||||
2
scripts/docs/templates/common.template.html
vendored
2
scripts/docs/templates/common.template.html
vendored
@@ -225,7 +225,7 @@ Delegate: <$ doc.delegate $>
|
||||
|
||||
</h1>
|
||||
|
||||
<a class="improve-v2-docs" href="http://github.com/driftyco/ionic/edit/master/<$ doc.fileInfo.projectRelativePath $>#L<$ doc.location.start.line $>">
|
||||
<a class="improve-v2-docs" href="http://github.com/ionic-team/ionic/edit/master/<$ doc.fileInfo.projectRelativePath $>#L<$ doc.location.start.line $>">
|
||||
Improve this doc
|
||||
</a>
|
||||
|
||||
|
||||
@@ -4,15 +4,15 @@ var path = require('path');
|
||||
module.exports = {
|
||||
copyAssets: {
|
||||
src: [path.join(path.dirname(process.env.IONIC_APP_ENTRY_POINT), '..', 'assets', '**', '*')],
|
||||
dest: '{{WWW}}/assets'
|
||||
dest: path.join('{{WWW}}', 'assets')
|
||||
},
|
||||
copyIndexContent: {
|
||||
src: [path.join(process.cwd(), 'scripts', 'e2e', 'index.html')],
|
||||
dest: '{{WWW}}'
|
||||
},
|
||||
copyFonts: {
|
||||
src: [`${process.cwd()}/node_modules/ionicons/dist/fonts/**/*`, `${process.cwd()}/src/fonts/**/*`],
|
||||
dest: '{{WWW}}/assets/fonts'
|
||||
src: [path.join(process.cwd(), 'node_modules', 'ionicons', 'dist', 'fonts', '**', '*'), path.join(process.cwd(), 'src', 'fonts', '**', '*')],
|
||||
dest: path.join('{{WWW}}', 'assets', 'fonts')
|
||||
},
|
||||
copyPolyfills: {
|
||||
src: [path.join(process.cwd(), 'dist', 'e2e', 'polyfills', 'polyfills.ng.js')],
|
||||
|
||||
@@ -4,7 +4,7 @@ module.exports = function(options) {
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var request = require('request');
|
||||
var inputDir = path.join(__dirname, '../../dist/e2e/tests');
|
||||
var inputDir = path.join(__dirname, '..', '..' , 'dist', 'e2e', 'tests');
|
||||
var uploadQueue = [];
|
||||
|
||||
var ignoreFiles = /(\/test\/|\/ts\/|\/q\/|\/ionic-site\/|\/docs\/|\/examples\/|\/inquirer\/|\/lodash\/|\/tooling\/|\/colors\/|\/bin\/|\.ts$|\.bin|\.map$|\.md$|\.git|\.scss$|\.yml$|\.yaml$|\.dart$|\.txt|\.npm|bower|DS_Store|LICENSE)/i;
|
||||
@@ -13,15 +13,15 @@ module.exports = function(options) {
|
||||
fs.readdir(dir, function(err, list) {
|
||||
|
||||
list.forEach(function(file) {
|
||||
var url = urlPath + '/' + file;
|
||||
var url = path.join(urlPath, file);
|
||||
|
||||
|
||||
fs.stat(dir + '/' + file, function(err, stat) {
|
||||
fs.stat(path.join(dir, file), function(err, stat) {
|
||||
if (stat && stat.isDirectory()) {
|
||||
uploadFiles(dir + '/' + file, urlPath + '/' + file);
|
||||
uploadFiles(path.join(dir, file), path.join(urlPath, file);
|
||||
} else {
|
||||
if ( shouldProcessPath (url) ){
|
||||
uploadFile(url, dir + '/' + file);
|
||||
uploadFile(url, path.join(dir, file));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,7 +31,15 @@ $colors: (
|
||||
light: #f4f4f4,
|
||||
dark: #222,
|
||||
vibrant: rebeccapurple,
|
||||
bright: #ffc125
|
||||
bright: #ffc125,
|
||||
greyYellow: (
|
||||
base:#49606e,
|
||||
contrast:#fbb636
|
||||
),
|
||||
greyWhite: (
|
||||
base:#49606e,
|
||||
contrast:#fff
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ function run {
|
||||
git config --global user.email "hi@ionicframework.com"
|
||||
git config --global user.name "Ionitron"
|
||||
|
||||
git clone git@github.com:driftyco/$REPOSITORY.git $DIRECTORY $ARGS
|
||||
git clone git@github.com:ionic-team/$REPOSITORY.git $DIRECTORY $ARGS
|
||||
cd $DIRECTORY
|
||||
git fetch origin --tags
|
||||
cd ../
|
||||
|
||||
@@ -20,7 +20,7 @@ export const BUNDLES = 'bundles';
|
||||
export const SITE_NAME = 'ionic-site';
|
||||
|
||||
// File Paths
|
||||
export const PROJECT_ROOT = join(__dirname, '../..');
|
||||
export const PROJECT_ROOT = join(__dirname, '..', '..');
|
||||
export const DEMOS_ROOT = join(PROJECT_ROOT, DEMOS_NAME);
|
||||
export const DEMOS_SRC_ROOT = join(DEMOS_ROOT, SRC_NAME);
|
||||
export const DIST_ROOT = join(PROJECT_ROOT, DIST_NAME);
|
||||
@@ -45,7 +45,7 @@ export const WORKERS_SRC = join(SCRIPTS_ROOT, 'workers');
|
||||
|
||||
// NPM
|
||||
export const NPM_VENDOR_FILES = [
|
||||
'@angular', 'core-js/client', 'rxjs', 'systemjs/dist', 'zone.js/dist'
|
||||
'@angular', join('core-js', 'client'), 'rxjs', join('systemjs', 'dist'), join('zone.js', 'dist')
|
||||
];
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { task } from 'gulp';
|
||||
import { join } from 'path';
|
||||
import { DIST_BUILD_ROOT, DIST_BUILD_ES2015_ROOT, DIST_BUILD_UMD_ROOT, ES5, ES_2015, PROJECT_ROOT, UMD_MODULE } from '../constants';
|
||||
import { copySourceToDest, createTempTsConfig, deleteFiles, runNgc, runTsc } from '../util';
|
||||
|
||||
@@ -7,8 +8,8 @@ export function buildIonicAngularUmd(excludeSpec: boolean, stripDebug: boolean,
|
||||
const stream = copySourceToDest(DIST_BUILD_UMD_ROOT, excludeSpec, true, stripDebug);
|
||||
stream.on('end', () => {
|
||||
// the source files are copied, copy over a tsconfig from
|
||||
createTempTsConfig(['./**/*.ts'], ES5, UMD_MODULE, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_UMD_ROOT}/tsconfig.json`);
|
||||
runNgc(`${DIST_BUILD_UMD_ROOT}/tsconfig.json`, (err) => {
|
||||
createTempTsConfig([join('.', '**', '*.ts')], ES5, UMD_MODULE, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'));
|
||||
runNgc(join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'), (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
return;
|
||||
@@ -27,8 +28,8 @@ export function buildIonicAngularUmdTsc(excludeSpec: boolean, stripDebug: boolea
|
||||
const stream = copySourceToDest(DIST_BUILD_UMD_ROOT, excludeSpec, true, stripDebug);
|
||||
stream.on('end', () => {
|
||||
// the source files are copied, copy over a tsconfig from
|
||||
createTempTsConfig(['./**/*.ts'], ES5, UMD_MODULE, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_UMD_ROOT}/tsconfig.json`);
|
||||
runTsc(`${DIST_BUILD_UMD_ROOT}/tsconfig.json`, (err) => {
|
||||
createTempTsConfig([join('.', '**', '*.ts')], ES5, UMD_MODULE, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'));
|
||||
runTsc(join(DIST_BUILD_UMD_ROOT, 'tsconfig.json'), (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
return;
|
||||
@@ -48,8 +49,8 @@ export function buildIonicAngularEsm(stripDebug: boolean, done: Function) {
|
||||
const stream = copySourceToDest(DIST_BUILD_ROOT, true, true, stripDebug);
|
||||
stream.on('end', () => {
|
||||
// the source files are copied, copy over a tsconfig from
|
||||
createTempTsConfig(['./**/*.ts'], ES5, ES_2015, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_ROOT}/tsconfig.json`);
|
||||
runNgc(`${DIST_BUILD_ROOT}/tsconfig.json`, (err) => {
|
||||
createTempTsConfig([join('.', '**', '*.ts')], ES5, ES_2015, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_ROOT, 'tsconfig.json'));
|
||||
runNgc(join(DIST_BUILD_ROOT, 'tsconfig.json'), (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
return;
|
||||
@@ -67,8 +68,8 @@ export function buildIonicPureEs6(stripDebug: boolean, done: Function) {
|
||||
const stream = copySourceToDest(DIST_BUILD_ES2015_ROOT, true, true, stripDebug);
|
||||
stream.on('end', () => {
|
||||
// the source files are copied, copy over a tsconfig from
|
||||
createTempTsConfig(['./**/*.ts'], ES_2015, ES_2015, `${PROJECT_ROOT}/tsconfig.json`, `${DIST_BUILD_ES2015_ROOT}/tsconfig.json`);
|
||||
runNgc(`${DIST_BUILD_ES2015_ROOT}/tsconfig.json`, (err) => {
|
||||
createTempTsConfig([join('.', '**', '*.ts')], ES_2015, ES_2015, join(PROJECT_ROOT, 'tsconfig.json'), join(DIST_BUILD_ES2015_ROOT, 'tsconfig.json'));
|
||||
runNgc(join(DIST_BUILD_ES2015_ROOT, 'tsconfig.json'), (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
return;
|
||||
|
||||
@@ -11,14 +11,14 @@ task('demos.watch', ['demos.prepare'], (done: Function) => {
|
||||
done(new Error(`Usage: gulp e2e.watch --folder modal`));
|
||||
}
|
||||
|
||||
serveDemo(folderInfo.componentName).then(() => {
|
||||
serveDemo(folderInfo.componentName, folderInfo.devApp).then(() => {
|
||||
done();
|
||||
}).catch((err: Error) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
function serveDemo(folderName: any) {
|
||||
function serveDemo(folderName: any, devApp: boolean) {
|
||||
|
||||
const ionicAngularDir = join(PROJECT_ROOT, 'src');
|
||||
const srcTestRoot = join(DEMOS_ROOT, 'src', folderName);
|
||||
@@ -40,5 +40,5 @@ function serveDemo(folderName: any) {
|
||||
const appNgModulePath = join(srcTestRoot, 'app', 'app.module.ts');
|
||||
const distDir = join(distDemoRoot, 'www');
|
||||
|
||||
return runAppScriptsServe(folderName, appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath, watchConfigPath);
|
||||
return runAppScriptsServe(folderName, appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath, watchConfigPath, devApp);
|
||||
}
|
||||
|
||||
@@ -132,8 +132,8 @@ task('docs.sassVariables', () => {
|
||||
callback();
|
||||
}).on('end', () => {
|
||||
const config = require('../../config.json');
|
||||
console.log(`Writing to file at /driftyco/ionic/${outputFile}`);
|
||||
console.log(`Place this file in /driftyco/ionic-site/${config.v2DocsDir}/theming/overriding-ionic-variables in order to update the docs`);
|
||||
console.log(`Writing to file at /ionic-team/ionic/${outputFile}`);
|
||||
console.log(`Place this file in /ionic-team/ionic-site/${config.v2DocsDir}/theming/overriding-ionic-variables in order to update the docs`);
|
||||
mkdirp.sync('tmp');
|
||||
writeFileSync(outputFile, JSON.stringify(variables));
|
||||
}));
|
||||
|
||||
@@ -13,14 +13,14 @@ task('e2e.watch', ['e2e.prepare'], (done: Function) => {
|
||||
return;
|
||||
}
|
||||
|
||||
serveTest(folderInfo).then(() => {
|
||||
serveTest(folderInfo, folderInfo.devApp).then(() => {
|
||||
done();
|
||||
}).catch((err: Error) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
function serveTest(folderInfo: any) {
|
||||
function serveTest(folderInfo: any, devApp: boolean) {
|
||||
|
||||
const ionicAngularDir = join(PROJECT_ROOT, 'src');
|
||||
const srcTestRoot = join(PROJECT_ROOT, 'src', 'components', folderInfo.componentName, 'test', folderInfo.componentTest);
|
||||
@@ -47,5 +47,5 @@ function serveTest(folderInfo: any) {
|
||||
const appNgModulePath = join(dirname(appEntryPoint), 'app.module.ts');
|
||||
const distDir = join(distTestRoot, 'www');
|
||||
|
||||
return runAppScriptsServe(folderInfo.componentName + '/' + folderInfo.componentTest, appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath, null);
|
||||
return runAppScriptsServe(join(folderInfo.componentName, folderInfo.componentTest), appEntryPoint, appNgModulePath, ionicAngularDir, distDir, pathToWriteFile, ionicAngularDir, sassConfigPath, copyConfigPath, null, devApp);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ task('e2e.prepare', (done: Function) => {
|
||||
|
||||
task('e2e.prepareSass', (done: Function) => {
|
||||
const version = `E2E-${createTimestamp()}`;
|
||||
writeFileSync(join(SRC_ROOT, 'themes/version.scss'), `$ionic-version: "${version}";`);
|
||||
writeFileSync(join(SRC_ROOT, 'themes', 'version.scss'), `$ionic-version: "${version}";`);
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@ task('e2e.prod', ['e2e.prepare'], (done: Function) => {
|
||||
});
|
||||
|
||||
function e2eComponentExists(folderInfo: any): boolean {
|
||||
let componentPath = `${SRC_COMPONENTS_ROOT}/${folderInfo.componentName}/test/${folderInfo.componentTest}/app`;
|
||||
let componentPath = join(SRC_COMPONENTS_ROOT, folderInfo.componentName, 'test', folderInfo.componentTest, 'app');
|
||||
|
||||
try {
|
||||
accessSync(componentPath);
|
||||
@@ -62,11 +62,11 @@ function filterE2eTestfiles() {
|
||||
const folderInfo = getFolderInfo();
|
||||
if (folderInfo && folderInfo.componentName && folderInfo.componentTest) {
|
||||
if (!e2eComponentExists(folderInfo)) {
|
||||
console.log(`Can't find E2E test "${folderInfo.componentName}/test/${folderInfo.componentTest}". Make sure that the test exists and you are passing the correct folder.`);
|
||||
console.log('Cannot find E2E test ', join(folderInfo.componentName, 'test', folderInfo.componentTest), '. Make sure that the test exists and you are passing the correct folder.');
|
||||
return [];
|
||||
}
|
||||
const filtered = entryPoints.filter(entryPoint => {
|
||||
return entryPoint.indexOf(`${folderInfo.componentName}/test/${folderInfo.componentTest}`) >= 0;
|
||||
return entryPoint.indexOf(join(folderInfo.componentName, 'test', folderInfo.componentTest)) >= 0;
|
||||
});
|
||||
return filtered;
|
||||
}
|
||||
@@ -121,7 +121,7 @@ function buildTest(filePath: string) {
|
||||
const relativePathFromComponents = relative(dirname(SRC_COMPONENTS_ROOT), srcTestRoot);
|
||||
const distTestRoot = join(process.cwd(), 'dist', 'e2e', relativePathFromComponents);
|
||||
|
||||
const includeGlob = [ join(ionicAngularDir, '**', '*.ts')];
|
||||
const includeGlob = [join(ionicAngularDir, '**', '*.ts')];
|
||||
const pathToWriteFile = join(distTestRoot, 'tsconfig.json');
|
||||
const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
|
||||
|
||||
@@ -154,7 +154,7 @@ function copyProtractorTestContent(filePaths: string[]): Promise<any> {
|
||||
}
|
||||
|
||||
function applyTemplate(filePathContent: Map<string, string>) {
|
||||
const buildConfig = require('../../build/config');
|
||||
const buildConfig = require(join('..', '..', 'build', 'config'));
|
||||
const templateFileContent = readFileSync(join(SCRIPTS_ROOT, 'e2e', 'e2e.template.js'));
|
||||
const templater = template(templateFileContent.toString());
|
||||
const modifiedMap = new Map<string, string>();
|
||||
@@ -235,7 +235,7 @@ task('e2e.polyfill', (done: Function) => {
|
||||
return done();
|
||||
}
|
||||
|
||||
writePolyfills('dist/e2e/polyfills').then(() => {
|
||||
writePolyfills(join('dist', 'e2e', 'polyfills')).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
@@ -249,9 +249,8 @@ task('e2e.openProd', (done: Function) => {
|
||||
task('e2e.open', (done: Function) => {
|
||||
const folderInfo = getFolderInfo();
|
||||
if (folderInfo && folderInfo.componentName && folderInfo.componentTest) {
|
||||
const filePath = `${folderInfo.componentName}/test/${folderInfo.componentTest}/www/index.html`;
|
||||
const fullPath = join(DIST_E2E_COMPONENTS_ROOT, filePath);
|
||||
const spawnedCommand = spawn('open', [fullPath]);
|
||||
const filePath = join(DIST_E2E_COMPONENTS_ROOT, folderInfo.componentName, 'test', folderInfo.componentTest, 'www', 'index.html');
|
||||
const spawnedCommand = spawn('open', [filePath]);
|
||||
|
||||
spawnedCommand.on('close', (code: number) => {
|
||||
done();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { task } from 'gulp';
|
||||
import { writePolyfills } from '../util';
|
||||
import { join } from 'path';
|
||||
|
||||
|
||||
task('src.polyfill', (done: Function) => {
|
||||
writePolyfills('scripts/polyfill').then(() => {
|
||||
writePolyfills(join('scripts', 'polyfills')).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { task, src, dest } from 'gulp';
|
||||
import { writePolyfills } from '../util';
|
||||
import { join } from 'path';
|
||||
|
||||
task('polyfill', ['polyfill.copy-readme', 'polyfill.write']);
|
||||
|
||||
task('polyfill.write', (done: Function) => {
|
||||
writePolyfills('dist/ionic-angular/polyfills').then(() => {
|
||||
writePolyfills(join('dist', 'ionic-angular', 'polyfills')).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
@@ -12,6 +13,6 @@ task('polyfill.write', (done: Function) => {
|
||||
});
|
||||
|
||||
task('polyfill.copy-readme', (done: Function) => {
|
||||
return src('scripts/polyfill/readme.md')
|
||||
.pipe(dest('dist/ionic-angular/polyfills/'), done);
|
||||
return src(join('scripts', 'polyfill', 'readme.md'))
|
||||
.pipe(dest(join('dist', 'ionic-angular', 'polyfills')), done);
|
||||
});
|
||||
|
||||
@@ -86,7 +86,7 @@ task('release.publishGithubRelease', (done: Function) => {
|
||||
})
|
||||
.pipe(obj(function(file, enc, cb){
|
||||
github.releases.createRelease({
|
||||
owner: 'driftyco',
|
||||
owner: 'ionic-team',
|
||||
repo: 'ionic',
|
||||
target_commitish: 'master',
|
||||
tag_name: 'v' + packageJSON.version,
|
||||
|
||||
@@ -77,7 +77,9 @@ function protractor(callback, args, testId: string) {
|
||||
|
||||
console.log(`Serving ${process.cwd()} on http://localhost:${buildConfig.protractorPort}`);
|
||||
|
||||
const child = spawn('protractor', args, {
|
||||
let spawnCommand = process.platform === 'win32' ? 'protractor.cmd' : 'protractor';
|
||||
|
||||
const child = spawn(spawnCommand, args, {
|
||||
stdio: [process.stdin, process.stdout, 'pipe']
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn } from 'child_process';
|
||||
import { spawn } from 'cross-spawn';
|
||||
import { NODE_MODULES_ROOT, SRC_ROOT } from './constants';
|
||||
import { src, dest } from 'gulp';
|
||||
import { dirname, join } from 'path';
|
||||
@@ -60,7 +60,9 @@ export function createTempTsConfig(includeGlob: string[], target: string, module
|
||||
config.compilerOptions = Object.assign(config.compilerOptions, overrideCompileOptions);
|
||||
}
|
||||
|
||||
// TS represents paths internally with '/' and expects the tsconfig path to be in this format
|
||||
let json = JSON.stringify(config, null, 2);
|
||||
json = json.replace(/\\\\/g, '/');
|
||||
|
||||
const dirToCreate = dirname(pathToWriteFile);
|
||||
ensureDirSync(dirToCreate);
|
||||
@@ -188,7 +190,7 @@ export function runWebpack(pathToWebpackConfig: string, done: Function) {
|
||||
});
|
||||
}
|
||||
|
||||
export function runAppScriptsServe(testOrDemoName: string, appEntryPoint: string, appNgModulePath: string, srcDir: string, distDir: string, tsConfig: string, ionicAngularDir: string, sassConfigPath: string, copyConfigPath: string, watchConfigPath: string) {
|
||||
export function runAppScriptsServe(testOrDemoName: string, appEntryPoint: string, appNgModulePath: string, srcDir: string, distDir: string, tsConfig: string, ionicAngularDir: string, sassConfigPath: string, copyConfigPath: string, watchConfigPath: string, devApp: boolean) {
|
||||
console.log('Running ionic-app-scripts serve with', testOrDemoName);
|
||||
const deepLinksDir = dirname(dirname(appNgModulePath));
|
||||
let scriptArgs = [
|
||||
@@ -205,6 +207,9 @@ export function runAppScriptsServe(testOrDemoName: string, appEntryPoint: string
|
||||
'--copy', copyConfigPath,
|
||||
'--enableLint', 'false'
|
||||
];
|
||||
if (devApp) {
|
||||
scriptArgs.push('--bonjour');
|
||||
}
|
||||
|
||||
if (watchConfigPath) {
|
||||
scriptArgs.push('--watch');
|
||||
@@ -217,9 +222,11 @@ export function runAppScriptsServe(testOrDemoName: string, appEntryPoint: string
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const args = ['./node_modules/.bin/ionic-app-scripts'].concat(scriptArgs);
|
||||
console.log(`node ${args.join(' ')}`);
|
||||
const spawnedCommand = spawn('node', args, {stdio: 'inherit'});
|
||||
let pathToAppScripts = join(NODE_MODULES_ROOT, '.bin', 'ionic-app-scripts');
|
||||
pathToAppScripts = process.platform === 'win32' ? pathToAppScripts + '.cmd' : pathToAppScripts;
|
||||
|
||||
const spawnedCommand = spawn(pathToAppScripts, scriptArgs, {stdio: 'inherit'});
|
||||
console.log(`${pathToAppScripts} ${scriptArgs.join(' ')}`);
|
||||
|
||||
spawnedCommand.on('close', (code: number) => {
|
||||
if (code === 0) {
|
||||
@@ -345,9 +352,11 @@ export function getFolderInfo() {
|
||||
componentName = folderSplit[0];
|
||||
componentTest = (folderSplit.length > 1 ? folderSplit[1] : 'basic');
|
||||
}
|
||||
const devApp = argv.devapp !== undefined;
|
||||
return {
|
||||
componentName: componentName,
|
||||
componentTest: componentTest
|
||||
componentTest: componentTest,
|
||||
devApp: devApp
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -95,4 +95,4 @@ export function config(config) {
|
||||
singleRun: true
|
||||
});
|
||||
|
||||
};
|
||||
};
|
||||
@@ -5,7 +5,7 @@
|
||||
"keywords": [],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/driftyco/ionic.git"
|
||||
"url": "https://github.com/ionic-team/ionic.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "umd/index.js",
|
||||
|
||||
@@ -38,7 +38,7 @@ weak maps / weak sets
|
||||
|
||||
## polyfills.ng.js
|
||||
|
||||
Only the required polyfill for Angular 2. This does not come with any ES6 polyfills. Note that all polyfill files listed here included the required polyfills for Angular 2 to work correctly.
|
||||
Only the required polyfill for Angular. This does not come with any ES6 polyfills. Note that all polyfill files listed here included the required polyfills for Angular to work correctly.
|
||||
|
||||
### Targets:
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { $CLASSNAME } from './$FILENAME';
|
||||
|
||||
@NgModule({
|
||||
@@ -7,7 +7,7 @@ import { $CLASSNAME } from './$FILENAME';
|
||||
$CLASSNAME,
|
||||
],
|
||||
imports: [
|
||||
IonicPageModule.forChild($CLASSNAME),
|
||||
IonicModule,
|
||||
],
|
||||
exports: [
|
||||
$CLASSNAME
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'rxjs/add/operator/map';
|
||||
Generated class for the $CLASSNAME provider.
|
||||
|
||||
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
|
||||
for more info on providers and Angular 2 DI.
|
||||
for more info on providers and Angular DI.
|
||||
*/
|
||||
@Injectable()
|
||||
export class $CLASSNAME {
|
||||
|
||||
@@ -22,13 +22,13 @@ import { ViewController } from '../../navigation/view-controller';
|
||||
'<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 ion-button="action-sheet-button" (click)="click(b)" *ngFor="let b of d.buttons" class="disable-hover" [attr.icon-left]="b.icon ? \'\' : null" [ngClass]="b.cssClass">' +
|
||||
'<button ion-button="action-sheet-button" (click)="click(b)" *ngFor="let b of d.buttons" class="disable-hover" [attr.icon-start]="b.icon ? \'\' : null" [ngClass]="b.cssClass">' +
|
||||
'<ion-icon [name]="b.icon" *ngIf="b.icon" class="action-sheet-icon"></ion-icon>' +
|
||||
'{{b.text}}' +
|
||||
'</button>' +
|
||||
'</div>' +
|
||||
'<div class="action-sheet-group" *ngIf="cancelButton">' +
|
||||
'<button ion-button="action-sheet-button" (click)="click(cancelButton)" class="action-sheet-cancel disable-hover" [attr.icon-left]="cancelButton.icon ? \'\' : null" [ngClass]="cancelButton.cssClass">' +
|
||||
'<button ion-button="action-sheet-button" (click)="click(cancelButton)" class="action-sheet-cancel disable-hover" [attr.icon-start]="cancelButton.icon ? \'\' : null" [ngClass]="cancelButton.cssClass">' +
|
||||
'<ion-icon [name]="cancelButton.icon" *ngIf="cancelButton.icon" class="action-sheet-icon"></ion-icon>' +
|
||||
'{{cancelButton.text}}' +
|
||||
'</button>' +
|
||||
@@ -117,8 +117,6 @@ export class ActionSheetCmp {
|
||||
}
|
||||
|
||||
ionViewDidEnter() {
|
||||
this._plt.focusOutActiveElement();
|
||||
|
||||
const focusableEle = this._elementRef.nativeElement.querySelector('button');
|
||||
if (focusableEle) {
|
||||
focusableEle.focus();
|
||||
|
||||
@@ -97,16 +97,15 @@ $action-sheet-ios-button-cancel-font-weight: 600 !default;
|
||||
|
||||
.action-sheet-ios .action-sheet-group {
|
||||
@include border-radius($action-sheet-ios-border-radius);
|
||||
@include margin(null, null, $action-sheet-ios-group-margin-bottom - 2, null);
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
margin-bottom: $action-sheet-ios-group-margin-bottom - 2;
|
||||
|
||||
background: $action-sheet-ios-background;
|
||||
}
|
||||
|
||||
.action-sheet-ios .action-sheet-group:last-child {
|
||||
margin-bottom: $action-sheet-ios-group-margin-bottom;
|
||||
@include margin(null, null, $action-sheet-ios-group-margin-bottom, null);
|
||||
}
|
||||
|
||||
.action-sheet-ios .action-sheet-title {
|
||||
@@ -137,7 +136,7 @@ $action-sheet-ios-button-cancel-font-weight: 600 !default;
|
||||
}
|
||||
|
||||
.action-sheet-ios .action-sheet-button.activated {
|
||||
margin-top: -$action-sheet-ios-button-border-width;
|
||||
@include margin(-$action-sheet-ios-button-border-width, null, null, null);
|
||||
|
||||
border-top: $action-sheet-ios-button-border-width $action-sheet-ios-button-border-style $action-sheet-ios-button-background-activated;
|
||||
border-bottom-color: $action-sheet-ios-button-background-activated;
|
||||
|
||||
@@ -24,6 +24,7 @@ ion-action-sheet {
|
||||
.action-sheet-wrapper {
|
||||
@include position(null, 0, 0, 0);
|
||||
@include margin(auto);
|
||||
@include transform(translate3d(0, 100%, 0));
|
||||
|
||||
position: absolute;
|
||||
z-index: $z-index-overlay-wrapper;
|
||||
@@ -31,8 +32,6 @@ ion-action-sheet {
|
||||
|
||||
width: $action-sheet-width;
|
||||
max-width: $action-sheet-max-width;
|
||||
|
||||
transform: translate3d(0, 100%, 0);
|
||||
}
|
||||
|
||||
.action-sheet-button {
|
||||
|
||||
@@ -84,6 +84,7 @@ export class AlertCmp {
|
||||
msgId: string;
|
||||
subHdrId: string;
|
||||
mode: string;
|
||||
keyboardResizes: boolean;
|
||||
gestureBlocker: BlockerDelegate;
|
||||
|
||||
constructor(
|
||||
@@ -99,6 +100,7 @@ export class AlertCmp {
|
||||
this.gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
|
||||
this.d = params.data;
|
||||
this.mode = this.d.mode || config.get('mode');
|
||||
this.keyboardResizes = config.getBoolean('keyboardResizes', false);
|
||||
_renderer.setElementClass(_elementRef.nativeElement, `alert-${this.mode}`, true);
|
||||
|
||||
if (this.d.cssClass) {
|
||||
@@ -178,7 +180,7 @@ export class AlertCmp {
|
||||
}
|
||||
|
||||
const hasTextInput = (this.d.inputs.length && this.d.inputs.some(i => !(NON_TEXT_INPUT_REGEX.test(i.type))));
|
||||
if (hasTextInput && this._plt.is('mobile')) {
|
||||
if (!this.keyboardResizes && hasTextInput && this._plt.is('mobile')) {
|
||||
// this alert has a text input and it's on a mobile device so we should align
|
||||
// the alert up high because we need to leave space for the virtual keboard
|
||||
// this also helps prevent the layout getting all messed up from
|
||||
@@ -192,18 +194,10 @@ export class AlertCmp {
|
||||
}
|
||||
|
||||
ionViewDidLeave() {
|
||||
this._plt.focusOutActiveElement();
|
||||
this.gestureBlocker.unblock();
|
||||
}
|
||||
|
||||
ionViewWillLeave() {
|
||||
this._plt.focusOutActiveElement();
|
||||
}
|
||||
|
||||
ionViewDidEnter() {
|
||||
// focus out of the active element
|
||||
this._plt.focusOutActiveElement();
|
||||
|
||||
// set focus on the first input or button in the alert
|
||||
// note that this does not always work and bring up the keyboard on
|
||||
// devices since the focus command must come from the user's touch event
|
||||
@@ -316,6 +310,11 @@ export class AlertCmp {
|
||||
return this.d.inputs.filter(i => i.checked).map(i => i.value);
|
||||
}
|
||||
|
||||
if (this.d.inputs.length === 0) {
|
||||
// this is an alert without any options/inputs at all
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// this is an alert with text inputs
|
||||
// return an object of all the values with the input name as the key
|
||||
const values: {[k: string]: string} = {};
|
||||
|
||||
@@ -193,8 +193,10 @@ $alert-ios-radio-min-width: 30px !default;
|
||||
/// @prop - Top of the icon in the radio alert
|
||||
$alert-ios-radio-icon-top: -7px !default;
|
||||
|
||||
/// @prop - Left of the icon in the radio alert
|
||||
// deprecated
|
||||
$alert-ios-radio-icon-left: 7px !default;
|
||||
/// @prop - Start of the icon in the radio alert
|
||||
$alert-ios-radio-icon-start: $alert-ios-radio-icon-left !default;
|
||||
|
||||
/// @prop - Width of the icon in the radio alert
|
||||
$alert-ios-radio-icon-width: 6px !default;
|
||||
@@ -277,8 +279,10 @@ $alert-ios-checkbox-background-color-on: color($colors-ios, primary) !def
|
||||
/// @prop - Top of the icon in the checkbox alert
|
||||
$alert-ios-checkbox-icon-top: 4px !default;
|
||||
|
||||
/// @prop - Left of the icon in the checkbox alert
|
||||
// deprecated
|
||||
$alert-ios-checkbox-icon-left: 7px !default;
|
||||
/// @prop - Start of the icon in the checkbox alert
|
||||
$alert-ios-checkbox-icon-start: $alert-ios-checkbox-icon-left !default;
|
||||
|
||||
/// @prop - Width of the icon in the checkbox alert
|
||||
$alert-ios-checkbox-icon-width: 4px !default;
|
||||
@@ -324,7 +328,7 @@ $alert-ios-checkbox-icon-transform: rotate(45deg) !default;
|
||||
}
|
||||
|
||||
.alert-ios .alert-title {
|
||||
margin-top: $alert-ios-title-margin-top;
|
||||
@include margin($alert-ios-title-margin-top, null, null, null);
|
||||
|
||||
font-size: $alert-ios-title-font-size;
|
||||
font-weight: $alert-ios-title-font-weight;
|
||||
@@ -446,7 +450,7 @@ $alert-ios-checkbox-icon-transform: rotate(45deg) !default;
|
||||
// -----------------------------------------
|
||||
|
||||
.alert-ios [aria-checked=true] .alert-radio-inner {
|
||||
@include position($alert-ios-radio-icon-top, null, null, $alert-ios-radio-icon-left);
|
||||
@include position($alert-ios-radio-icon-top, null, null, $alert-ios-radio-icon-start);
|
||||
|
||||
position: absolute;
|
||||
|
||||
@@ -519,7 +523,7 @@ $alert-ios-checkbox-icon-transform: rotate(45deg) !default;
|
||||
// -----------------------------------------
|
||||
|
||||
.alert-ios [aria-checked=true] .alert-checkbox-inner {
|
||||
@include position($alert-ios-checkbox-icon-top, null, null, $alert-ios-checkbox-icon-left);
|
||||
@include position($alert-ios-checkbox-icon-top, null, null, $alert-ios-checkbox-icon-start);
|
||||
|
||||
position: absolute;
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ $alert-md-input-margin-bottom: 5px !default;
|
||||
// deprecated
|
||||
$alert-md-input-margin-left: 0 !default;
|
||||
/// @prop - Margin start of the alert input
|
||||
$alert-md-input-margin-start: $alert-md-input-margin-left;
|
||||
$alert-md-input-margin-start: $alert-md-input-margin-left !default;
|
||||
|
||||
/// @prop - Flex wrap of the alert button group
|
||||
$alert-md-button-group-flex-wrap: wrap-reverse !default;
|
||||
@@ -249,8 +249,10 @@ $alert-md-radio-border-color-on: $alert-md-button-text-color !defau
|
||||
/// @prop - Top of the icon in the alert radio
|
||||
$alert-md-radio-icon-top: 2px !default;
|
||||
|
||||
/// @prop - Left of the icon in the alert radio
|
||||
// deprecated
|
||||
$alert-md-radio-icon-left: 2px !default;
|
||||
/// @prop - Start of the icon in the radio alert
|
||||
$alert-md-radio-icon-start: $alert-md-radio-icon-left !default;
|
||||
|
||||
/// @prop - Width of the icon in the alert radio
|
||||
$alert-md-radio-icon-width: 8px !default;
|
||||
@@ -323,8 +325,10 @@ $alert-md-checkbox-border-color-on: $alert-md-button-text-color !defau
|
||||
/// @prop - Top of the icon in the checkbox alert
|
||||
$alert-md-checkbox-icon-top: 0 !default;
|
||||
|
||||
/// @prop - Left of the icon in the checkbox alert
|
||||
// deprecated
|
||||
$alert-md-checkbox-icon-left: 3px !default;
|
||||
/// @prop - Start of the icon in the checkbox alert
|
||||
$alert-md-checkbox-icon-start: $alert-md-checkbox-icon-left !default;
|
||||
|
||||
/// @prop - Width of the icon in the checkbox alert
|
||||
$alert-md-checkbox-icon-width: 6px !default;
|
||||
@@ -410,7 +414,7 @@ $alert-md-checkbox-icon-transform: rotate(45deg) !default;
|
||||
}
|
||||
|
||||
.alert-md .alert-input:focus {
|
||||
margin-bottom: $alert-md-input-margin-bottom - 1;
|
||||
@include margin(null, null, $alert-md-input-margin-bottom - 1, null);
|
||||
|
||||
border-bottom: $alert-md-input-border-width-focused $alert-md-input-border-style-focused $alert-md-input-border-color-focused;
|
||||
}
|
||||
@@ -481,7 +485,7 @@ $alert-md-checkbox-icon-transform: rotate(45deg) !default;
|
||||
// ---------------------------------------------------
|
||||
|
||||
.alert-md .alert-radio-inner {
|
||||
@include position($alert-md-radio-icon-top, null, null, $alert-md-radio-icon-left);
|
||||
@include position($alert-md-radio-icon-top, null, null, $alert-md-radio-icon-start);
|
||||
@include border-radius($alert-md-radio-icon-border-radius);
|
||||
|
||||
position: absolute;
|
||||
@@ -559,7 +563,7 @@ $alert-md-checkbox-icon-transform: rotate(45deg) !default;
|
||||
}
|
||||
|
||||
.alert-md [aria-checked=true] .alert-checkbox-inner {
|
||||
@include position($alert-md-checkbox-icon-top, null, null, $alert-md-checkbox-icon-left);
|
||||
@include position($alert-md-checkbox-icon-top, null, null, $alert-md-checkbox-icon-start);
|
||||
|
||||
position: absolute;
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ ion-alert {
|
||||
}
|
||||
|
||||
ion-alert.alert-top {
|
||||
align-items: flex-start;
|
||||
@include padding(50px, null, null, null);
|
||||
|
||||
padding-top: 50px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
ion-alert input {
|
||||
|
||||
@@ -262,8 +262,10 @@ $alert-wp-radio-border-color: $input-wp-border-color !default;
|
||||
/// @prop - Top of the icon in the radio alert
|
||||
$alert-wp-radio-icon-top: 2px !default;
|
||||
|
||||
/// @prop - Left of the icon in the radio alert
|
||||
// deprecated
|
||||
$alert-wp-radio-icon-left: 2px !default;
|
||||
/// @prop - Start of the icon in the radio alert
|
||||
$alert-wp-radio-icon-start: $alert-wp-radio-icon-left !default;
|
||||
|
||||
/// @prop - Width of the icon in the radio alert
|
||||
$alert-wp-radio-icon-width: 8px !default;
|
||||
@@ -328,8 +330,10 @@ $alert-wp-checkbox-background-on: color($colors-wp, primary) !defau
|
||||
/// @prop - Top of the icon in the checkbox alert
|
||||
$alert-wp-checkbox-icon-top: -2px !default;
|
||||
|
||||
/// @prop - Left of the icon in the checkbox alert
|
||||
// deprecated
|
||||
$alert-wp-checkbox-icon-left: 3px !default;
|
||||
/// @prop - Start of the icon in the checkbox alert
|
||||
$alert-wp-checkbox-icon-start: $alert-wp-checkbox-icon-left !default;
|
||||
|
||||
/// @prop - Width of the icon in the checkbox alert
|
||||
$alert-wp-checkbox-icon-width: 6px !default;
|
||||
@@ -495,7 +499,7 @@ $alert-wp-checkbox-icon-transform: rotate(45deg) !default;
|
||||
// ---------------------------------------------------
|
||||
|
||||
.alert-wp .alert-radio-inner {
|
||||
@include position($alert-wp-radio-icon-top, null, null, $alert-wp-radio-icon-left);
|
||||
@include position($alert-wp-radio-icon-top, null, null, $alert-wp-radio-icon-start);
|
||||
@include border-radius($alert-wp-radio-icon-border-radius);
|
||||
|
||||
position: absolute;
|
||||
@@ -575,7 +579,7 @@ $alert-wp-checkbox-icon-transform: rotate(45deg) !default;
|
||||
// --------------------------------------------------
|
||||
|
||||
.alert-wp [aria-checked=true] .alert-checkbox-inner {
|
||||
@include position($alert-wp-checkbox-icon-top, null, null, $alert-wp-checkbox-icon-left);
|
||||
@include position($alert-wp-checkbox-icon-top, null, null, $alert-wp-checkbox-icon-start);
|
||||
|
||||
position: absolute;
|
||||
|
||||
@@ -604,7 +608,7 @@ $alert-wp-checkbox-icon-transform: rotate(45deg) !default;
|
||||
}
|
||||
|
||||
.alert-wp .alert-button-group-vertical .alert-button {
|
||||
margin-top: $alert-wp-button-group-vertical-margin-top;
|
||||
@include margin($alert-wp-button-group-vertical-margin-top, null, null, null);
|
||||
|
||||
width: $alert-wp-button-group-vertical-width;
|
||||
}
|
||||
|
||||
@@ -145,8 +145,7 @@ h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 1.6rem;
|
||||
margin-bottom: 1rem;
|
||||
@include margin(1.6rem, null, 1rem, null);
|
||||
|
||||
font-weight: $headings-font-weight;
|
||||
line-height: $headings-line-height;
|
||||
@@ -160,7 +159,7 @@ h6 {
|
||||
h5,
|
||||
h6 {
|
||||
&:first-child {
|
||||
margin-top: -.3rem;
|
||||
@include margin(-.3rem, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,17 +167,17 @@ h6 {
|
||||
h1 + h2,
|
||||
h1 + h3,
|
||||
h2 + h3 {
|
||||
margin-top: -.3rem;
|
||||
@include margin(-.3rem, null, null, null);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 2rem;
|
||||
@include margin(2rem, null, null, null);
|
||||
|
||||
font-size: $h1-font-size;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 1.8rem;
|
||||
@include margin(1.8rem, null, null, null);
|
||||
|
||||
font-size: $h2-font-size;
|
||||
}
|
||||
@@ -412,31 +411,19 @@ ion-footer {
|
||||
// Provide `[float-{bp}]` attributes for floating the element based
|
||||
// on the breakpoint
|
||||
[float#{$infix}-left] {
|
||||
// scss-lint:disable ImportantRule, PropertySpelling
|
||||
float: left !important;
|
||||
@include float(left, !important);
|
||||
}
|
||||
|
||||
[float#{$infix}-right] {
|
||||
// scss-lint:disable ImportantRule, PropertySpelling
|
||||
float: right !important;
|
||||
@include float(right, !important);
|
||||
}
|
||||
|
||||
[float#{$infix}-start] {
|
||||
// scss-lint:disable ImportantRule, PropertySpelling
|
||||
float: left !important;
|
||||
|
||||
@include rtl() {
|
||||
float: right !important;
|
||||
}
|
||||
@include float(start, !important);
|
||||
}
|
||||
|
||||
[float#{$infix}-end] {
|
||||
// scss-lint:disable ImportantRule, PropertySpelling
|
||||
float: right !important;
|
||||
|
||||
@include rtl() {
|
||||
float: left !important;
|
||||
}
|
||||
@include float(end, !important);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@ import * as Constants from './app-constants';
|
||||
import { ClickBlock } from './click-block';
|
||||
import { runInDev, assert } from '../../util/util';
|
||||
import { Config } from '../../config/config';
|
||||
import { isNav, NavOptions, DIRECTION_FORWARD, DIRECTION_BACK } from '../../navigation/nav-util';
|
||||
import { NavOptions, DIRECTION_FORWARD, DIRECTION_BACK, isTabs } from '../../navigation/nav-util';
|
||||
import { MenuController } from './menu-controller';
|
||||
import { NavController } from '../../navigation/nav-controller';
|
||||
import { NavigationContainer } from '../../navigation/navigation-container';
|
||||
import { NavControllerBase } from '../../navigation/nav-controller-base';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
import { IOSTransition } from '../../transitions/transition-ios';
|
||||
@@ -28,8 +29,9 @@ export class App {
|
||||
private _scrollTime: number = 0;
|
||||
private _title: string = '';
|
||||
private _titleSrv: Title = new Title(DOCUMENT);
|
||||
private _rootNav: NavController = null;
|
||||
private _rootNavs = new Map<string, NavigationContainer>();
|
||||
private _disableScrollAssist: boolean;
|
||||
private _didScroll = false;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
@@ -87,6 +89,11 @@ export class App {
|
||||
_plt.registerBackButtonAction(this.goBack.bind(this));
|
||||
this._disableScrollAssist = _config.getBoolean('disableScrollAssist', false);
|
||||
|
||||
const blurring = _config.getBoolean('inputBlurring', false);
|
||||
if (blurring) {
|
||||
this._enableInputBlurring();
|
||||
}
|
||||
|
||||
runInDev(() => {
|
||||
// During developement, navPop can be triggered by calling
|
||||
const win = <any>_plt.win();
|
||||
@@ -179,6 +186,7 @@ export class App {
|
||||
*/
|
||||
setScrolling() {
|
||||
this._scrollTime = Date.now() + ACTIVE_SCROLLING_TIME;
|
||||
this._didScroll = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,26 +208,59 @@ export class App {
|
||||
/**
|
||||
* @return {NavController} Returns the active NavController. Using this method is preferred when we need access to the top-level navigation controller while on the outside views and handlers like `registerBackButtonAction()`
|
||||
*/
|
||||
getActiveNav(): NavController {
|
||||
getActiveNav(navId?: string): NavControllerBase {
|
||||
const portal = this._appRoot._getPortal(Constants.PORTAL_MODAL);
|
||||
if (portal.length() > 0) {
|
||||
return findTopNav(portal);
|
||||
return <NavControllerBase> findTopNav(portal);
|
||||
}
|
||||
return findTopNav(this._rootNav || null);
|
||||
if (!this._rootNavs || !this._rootNavs.size) {
|
||||
return null;
|
||||
}
|
||||
if (this._rootNavs.size === 1) {
|
||||
return <NavControllerBase> findTopNav(this._rootNavs.values().next().value);
|
||||
}
|
||||
return <NavControllerBase> findTopNav(this.getRootNavById(navId));
|
||||
}
|
||||
|
||||
getRootNav(): any {
|
||||
console.warn('(getRootNav) is deprecated and will be removed in the next major release. Use getRootNavById instead.');
|
||||
const rootNavs = this.getRootNavs();
|
||||
if (rootNavs.length === 0) {
|
||||
return null;
|
||||
} else if (rootNavs.length > 1) {
|
||||
console.warn('(getRootNav) there are multiple root navs, use getRootNavs instead');
|
||||
}
|
||||
return rootNavs[0];
|
||||
}
|
||||
|
||||
getRootNavs(): any[] {
|
||||
const navs: NavigationContainer[] = [];
|
||||
this._rootNavs.forEach(nav => navs.push(nav));
|
||||
return navs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {NavController} Returns the root NavController
|
||||
*/
|
||||
getRootNav(): NavController {
|
||||
return this._rootNav;
|
||||
getRootNavById(navId: string): NavigationContainer {
|
||||
return this._rootNavs.get(navId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
_setRootNav(nav: any) {
|
||||
this._rootNav = nav;
|
||||
registerRootNav(nav: NavigationContainer) {
|
||||
this._rootNavs.set(nav.id, nav);
|
||||
}
|
||||
|
||||
|
||||
getActiveNavContainers(): NavigationContainer[] {
|
||||
// for each root nav container, get it's active nav
|
||||
const list: NavigationContainer[] = [];
|
||||
this._rootNavs.forEach((container: NavigationContainer) => {
|
||||
list.push(findTopNav(container));
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,7 +275,6 @@ export class App {
|
||||
// TODO: move _setNav() to the earlier stages of NavController. _queueTrns()
|
||||
enteringView._setNav(portal);
|
||||
|
||||
opts.keyboardClose = false;
|
||||
opts.direction = DIRECTION_FORWARD;
|
||||
|
||||
if (!opts.animation) {
|
||||
@@ -242,7 +282,7 @@ export class App {
|
||||
}
|
||||
|
||||
enteringView.setLeavingOpts({
|
||||
keyboardClose: false,
|
||||
keyboardClose: opts.keyboardClose,
|
||||
direction: DIRECTION_BACK,
|
||||
animation: enteringView.getTransitionName(DIRECTION_BACK),
|
||||
ev: opts.ev
|
||||
@@ -260,7 +300,7 @@ export class App {
|
||||
}
|
||||
|
||||
const navPromise = this.navPop();
|
||||
if (navPromise === null) {
|
||||
if (!navPromise) {
|
||||
// no views to go back to
|
||||
// let's exit the app
|
||||
if (this._config.getBoolean('navExitApp', true)) {
|
||||
@@ -275,7 +315,7 @@ export class App {
|
||||
* @hidden
|
||||
*/
|
||||
navPop(): Promise<any> {
|
||||
if (!this._rootNav || !this.isEnabled()) {
|
||||
if (!this._rootNavs || this._rootNavs.size === 0 || !this.isEnabled()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@@ -284,43 +324,112 @@ export class App {
|
||||
if (portal.length() > 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
// next get the active nav, check itself and climb up all
|
||||
// of its parent navs until it finds a nav that can pop
|
||||
return recursivePop(this.getActiveNav());
|
||||
|
||||
let navToPop: NavControllerBase = null;
|
||||
let mostRecentVC: ViewController = null;
|
||||
this._rootNavs.forEach((navContainer: NavigationContainer) => {
|
||||
const activeNav = this.getActiveNav(navContainer.id);
|
||||
const poppable = getPoppableNav(activeNav);
|
||||
if (poppable) {
|
||||
const topViewController = poppable.last();
|
||||
if (poppable._isPortal || (topViewController && poppable.length() > 1 && (!mostRecentVC || topViewController._ts >= mostRecentVC._ts))) {
|
||||
mostRecentVC = topViewController;
|
||||
navToPop = poppable;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (navToPop) {
|
||||
return navToPop.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
_enableInputBlurring() {
|
||||
console.debug('App: _enableInputBlurring');
|
||||
let focused = true;
|
||||
const self = this;
|
||||
const platform = this._plt;
|
||||
|
||||
platform.registerListener(platform.doc(), 'focusin', onFocusin, { capture: true, zone: false, passive: true });
|
||||
platform.registerListener(platform.doc(), 'touchend', onTouchend, { capture: false, zone: false, passive: true });
|
||||
|
||||
function onFocusin(ev: any) {
|
||||
focused = true;
|
||||
}
|
||||
function onTouchend(ev: any) {
|
||||
// if app did scroll return early
|
||||
if (self._didScroll) {
|
||||
self._didScroll = false;
|
||||
return;
|
||||
}
|
||||
const active = <HTMLElement> self._plt.getActiveElement();
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
// only blur if the active element is a text-input or a textarea
|
||||
if (SKIP_BLURRING.indexOf(active.tagName) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the selected target is the active element, do not blur
|
||||
const tapped = ev.target;
|
||||
if (tapped === active) {
|
||||
return;
|
||||
}
|
||||
if (SKIP_BLURRING.indexOf(tapped.tagName) >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// skip if div is a cover
|
||||
if (tapped.classList.contains('input-cover')) {
|
||||
return;
|
||||
}
|
||||
|
||||
focused = false;
|
||||
// TODO: find a better way, why 50ms?
|
||||
platform.timeout(() => {
|
||||
if (!focused) {
|
||||
active.blur();
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function recursivePop(nav: any): Promise<any> {
|
||||
|
||||
function getPoppableNav(nav: NavControllerBase): NavControllerBase {
|
||||
if (!nav) {
|
||||
return null;
|
||||
}
|
||||
if (isNav(nav)) {
|
||||
var len = nav.length();
|
||||
if (len > 1 || (nav._isPortal && len > 0)) {
|
||||
// this nav controller has more than one view
|
||||
// pop the current view on this nav and we're done here
|
||||
console.debug('app, goBack pop nav');
|
||||
return nav.pop();
|
||||
}
|
||||
|
||||
if (isTabs(nav)) {
|
||||
// tabs aren't a nav, so just call this function again immediately on the parent on tabs
|
||||
return getPoppableNav(nav.parent);
|
||||
}
|
||||
const len = nav.length();
|
||||
if (len > 1 || (nav._isPortal && len > 0)) {
|
||||
// this nav controller has more than one view
|
||||
// use this nav!
|
||||
return nav;
|
||||
}
|
||||
// try again using the parent nav (if there is one)
|
||||
return recursivePop(nav.parent);
|
||||
return getPoppableNav(nav.parent);
|
||||
}
|
||||
|
||||
function findTopNav(nav: NavController) {
|
||||
var activeChildNav: any;
|
||||
|
||||
function findTopNav(nav: NavigationContainer): NavigationContainer {
|
||||
while (nav) {
|
||||
activeChildNav = nav.getActiveChildNav();
|
||||
if (!activeChildNav) {
|
||||
const childNav = nav.getActiveChildNav();
|
||||
if (!childNav) {
|
||||
break;
|
||||
}
|
||||
nav = activeChildNav;
|
||||
nav = childNav;
|
||||
}
|
||||
|
||||
return nav;
|
||||
}
|
||||
|
||||
const SKIP_BLURRING = ['INPUT', 'TEXTAREA', 'ION-INPUT', 'ION-TEXTAREA'];
|
||||
const ACTIVE_SCROLLING_TIME = 100;
|
||||
const CLICK_BLOCK_BUFFER_IN_MILLIS = 64;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { removeArrayItem, assert } from '../../util/util';
|
||||
/**
|
||||
* @name MenuController
|
||||
* @description
|
||||
* The MenuController is a provider which makes it easy to control a [Menu](../Menu).
|
||||
* The MenuController is a provider which makes it easy to control a [Menu](../../Menu/Menu/).
|
||||
* Its methods can be used to display the menu, enable the menu, toggle the menu, and more.
|
||||
* The controller will grab a reference to the menu by the `side`, `id`, or, if neither
|
||||
* of these are passed to it, it will grab the first menu it finds.
|
||||
@@ -14,7 +14,7 @@ import { removeArrayItem, assert } from '../../util/util';
|
||||
*
|
||||
* @usage
|
||||
*
|
||||
* Add a basic menu component to start with. See the [Menu](../Menu) API docs
|
||||
* Add a basic menu component to start with. See the [Menu](../../Menu/Menu/) API docs
|
||||
* for more information on adding menu components.
|
||||
*
|
||||
* ```html
|
||||
|
||||
@@ -5,8 +5,8 @@ import { Config } from '../../config/config';
|
||||
import { DeepLinker } from '../../navigation/deep-linker';
|
||||
import { DomController } from '../../platform/dom-controller';
|
||||
import { GestureController } from '../../gestures/gesture-controller';
|
||||
import { Keyboard } from '../../platform/keyboard';
|
||||
import { NavControllerBase } from '../../navigation/nav-controller-base';
|
||||
import { NavigationContainer } from '../../navigation/navigation-container';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { TransitionController } from '../../transitions/transition-controller';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
@@ -17,12 +17,11 @@ import { ViewController } from '../../navigation/view-controller';
|
||||
@Directive({
|
||||
selector: '[overlay-portal]',
|
||||
})
|
||||
export class OverlayPortal extends NavControllerBase {
|
||||
export class OverlayPortal extends NavControllerBase implements NavigationContainer {
|
||||
constructor(
|
||||
@Inject(forwardRef(() => App)) app: App,
|
||||
config: Config,
|
||||
plt: Platform,
|
||||
keyboard: Keyboard,
|
||||
elementRef: ElementRef,
|
||||
zone: NgZone,
|
||||
renderer: Renderer,
|
||||
@@ -34,7 +33,7 @@ export class OverlayPortal extends NavControllerBase {
|
||||
domCtrl: DomController,
|
||||
errHandler: ErrorHandler
|
||||
) {
|
||||
super(null, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl, errHandler);
|
||||
super(null, app, config, plt, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl, errHandler);
|
||||
this._isPortal = true;
|
||||
this._init = true;
|
||||
this.setViewport(viewPort);
|
||||
@@ -57,4 +56,17 @@ export class OverlayPortal extends NavControllerBase {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
/*
|
||||
* @private
|
||||
*/
|
||||
getType() {
|
||||
return 'portal';
|
||||
}
|
||||
|
||||
/*
|
||||
* @private
|
||||
*/
|
||||
getSecondaryIdentifier(): string {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,12 @@ describe('App', () => {
|
||||
describe('goBack', () => {
|
||||
|
||||
it('should not select the previous tab', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
let tabs = mockTabs();
|
||||
let tab1 = mockTab(tabs);
|
||||
let tab2 = mockTab(tabs);
|
||||
const tabs = mockTabs();
|
||||
const tab1 = mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
|
||||
tab1.root = 'Page1';
|
||||
tab2.root = 'Page2';
|
||||
@@ -44,71 +44,79 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
it('should pop from the active tab, when tabs is nested is the root nav', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
let tabs = mockTabs();
|
||||
mockTab(tabs);
|
||||
let tab2 = mockTab(tabs);
|
||||
const tabs = mockTabs();
|
||||
mockTab(tabs);
|
||||
nav.registerChildNav(tabs);
|
||||
|
||||
const tab1 = mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
|
||||
tab2.setSelected(true);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(tab2, 'pop');
|
||||
spyOn(tab1, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(tab2, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(portal, 'pop');
|
||||
|
||||
let view1 = mockView();
|
||||
let view2 = mockView();
|
||||
const view1 = mockView();
|
||||
const view2 = mockView();
|
||||
tab2._views = [view1, view2];
|
||||
tab1._views = [mockView()];
|
||||
|
||||
app.goBack();
|
||||
|
||||
expect(tab1.pop).not.toHaveBeenCalled();
|
||||
expect(tab2.pop).toHaveBeenCalled();
|
||||
expect(portal.pop).not.toHaveBeenCalled();
|
||||
expect(plt.exitApp).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should pop from the active tab, when tabs is the root', () => {
|
||||
let tabs = mockTabs();
|
||||
const tabs = mockTabs();
|
||||
mockTab(tabs);
|
||||
let tab2 = mockTab(tabs);
|
||||
mockTab(tabs);
|
||||
app._setRootNav(tabs);
|
||||
app.registerRootNav(tabs);
|
||||
|
||||
const tab1 = mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
|
||||
tab2.setSelected(true);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(tab2, 'pop');
|
||||
spyOn(tab1, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(tab2, 'pop').and.returnValue(Promise.resolve());
|
||||
|
||||
let view1 = mockView();
|
||||
let view2 = mockView();
|
||||
const view1 = mockView();
|
||||
const view2 = mockView();
|
||||
tab2._views = [view1, view2];
|
||||
|
||||
app.goBack();
|
||||
|
||||
expect(tab1.pop).not.toHaveBeenCalled();
|
||||
expect(tab2.pop).toHaveBeenCalled();
|
||||
expect(plt.exitApp).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should pop the root nav when nested nav has less than 2 views', () => {
|
||||
let rootNav = mockNavController();
|
||||
let nestedNav = mockNavController();
|
||||
rootNav.registerChildNav(nestedNav);
|
||||
const rootNav = mockNavController();
|
||||
app.registerRootNav(rootNav);
|
||||
|
||||
const nestedNav = mockNavController();
|
||||
nestedNav.parent = rootNav;
|
||||
app._setRootNav(rootNav);
|
||||
rootNav.registerChildNav(nestedNav);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(rootNav, 'pop');
|
||||
spyOn(nestedNav, 'pop');
|
||||
spyOn(portal, 'pop');
|
||||
spyOn(rootNav, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(nestedNav, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(portal, 'pop').and.returnValue(Promise.resolve());
|
||||
|
||||
let rootView1 = mockView();
|
||||
let rootView2 = mockView();
|
||||
const rootView1 = mockView();
|
||||
const rootView2 = mockView();
|
||||
mockViews(rootNav, [rootView1, rootView2]);
|
||||
|
||||
let nestedView1 = mockView();
|
||||
const nestedView1 = mockView();
|
||||
mockViews(nestedNav, [nestedView1]);
|
||||
|
||||
app.goBack();
|
||||
@@ -120,22 +128,22 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
it('should pop a view from the nested nav that has more than 1 view', () => {
|
||||
let rootNav = mockNavController();
|
||||
let nestedNav = mockNavController();
|
||||
app._setRootNav(rootNav);
|
||||
const rootNav = mockNavController();
|
||||
const nestedNav = mockNavController();
|
||||
app.registerRootNav(rootNav);
|
||||
rootNav.registerChildNav(nestedNav);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(rootNav, 'pop');
|
||||
spyOn(nestedNav, 'pop');
|
||||
spyOn(nestedNav, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(portal, 'pop');
|
||||
|
||||
let rootView1 = mockView();
|
||||
let rootView2 = mockView();
|
||||
const rootView1 = mockView();
|
||||
const rootView2 = mockView();
|
||||
mockViews(rootNav, [rootView1, rootView2]);
|
||||
|
||||
let nestedView1 = mockView();
|
||||
let nestedView2 = mockView();
|
||||
const nestedView1 = mockView();
|
||||
const nestedView2 = mockView();
|
||||
mockViews(nestedNav, [nestedView1, nestedView2]);
|
||||
|
||||
app.goBack();
|
||||
@@ -147,18 +155,18 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
it('should pop the overlay in the portal of the root nav', (done: Function) => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(nav, 'pop');
|
||||
spyOn(portal, 'pop').and.returnValue(Promise.resolve());
|
||||
|
||||
let view1 = mockView();
|
||||
let view2 = mockView();
|
||||
const view1 = mockView();
|
||||
const view2 = mockView();
|
||||
mockViews(nav, [view1, view2]);
|
||||
|
||||
let overlay1 = mockView();
|
||||
const overlay1 = mockView();
|
||||
mockViews(portal, [overlay1]);
|
||||
|
||||
app.goBack().then(() => {
|
||||
@@ -173,15 +181,15 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
it('should pop the second view in the root nav', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(nav, 'pop');
|
||||
spyOn(nav, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(portal, 'pop');
|
||||
|
||||
let view1 = mockView();
|
||||
let view2 = mockView();
|
||||
const view1 = mockView();
|
||||
const view2 = mockView();
|
||||
mockViews(nav, [view1, view2]);
|
||||
|
||||
app.goBack();
|
||||
@@ -192,17 +200,17 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
it('should exit app when only one view in the root nav', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(nav, 'pop');
|
||||
spyOn(portal, 'pop');
|
||||
|
||||
let view1 = mockView();
|
||||
const view1 = mockView();
|
||||
mockViews(nav, [view1]);
|
||||
|
||||
expect(app.getActiveNav()).toBe(nav);
|
||||
expect(app.getActiveNav(nav.id)).toBe(nav);
|
||||
expect(nav.first()).toBe(view1);
|
||||
|
||||
app.goBack();
|
||||
@@ -213,8 +221,8 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
it('should not exit app when only one view in the root nav, but navExitApp config set', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(nav, 'pop');
|
||||
@@ -222,10 +230,10 @@ describe('App', () => {
|
||||
|
||||
config.set('navExitApp', false);
|
||||
|
||||
let view1 = mockView();
|
||||
const view1 = mockView();
|
||||
mockViews(nav, [view1]);
|
||||
|
||||
expect(app.getActiveNav()).toBe(nav);
|
||||
expect(app.getActiveNav(nav.id)).toBe(nav);
|
||||
expect(nav.first()).toBe(view1);
|
||||
|
||||
app.goBack();
|
||||
@@ -236,14 +244,14 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
it('should not go back if app is not enabled', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(nav, 'pop');
|
||||
spyOn(portal, 'pop');
|
||||
|
||||
let view1 = mockView();
|
||||
const view1 = mockView();
|
||||
mockViews(nav, [view1]);
|
||||
|
||||
app.setEnabled(false, 10000);
|
||||
@@ -263,101 +271,208 @@ describe('App', () => {
|
||||
expect(plt.exitApp).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should first pop the from the nav controller with the most recent view, then pop subsequent views, and eventually exit the app when there isnt anything left to pop', () => {
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
const navTwo = mockNavController();
|
||||
app.registerRootNav(navTwo);
|
||||
|
||||
spyOn(plt, 'exitApp');
|
||||
spyOn(nav, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(navTwo, 'pop').and.returnValue(Promise.resolve());
|
||||
spyOn(portal, 'pop');
|
||||
|
||||
const view1 = mockView();
|
||||
const view2 = mockView();
|
||||
mockViews(nav, [view1, view2]);
|
||||
|
||||
const view3 = mockView();
|
||||
view3._ts = view3._ts + 1000;
|
||||
const view4 = mockView();
|
||||
view4._ts = view4._ts + 1000;
|
||||
mockViews(navTwo, [view3, view4]);
|
||||
|
||||
app.goBack();
|
||||
|
||||
mockViews(navTwo, [view3]);
|
||||
|
||||
expect(portal.pop).not.toHaveBeenCalled();
|
||||
expect(nav.pop).not.toHaveBeenCalled();
|
||||
expect(navTwo.pop).toHaveBeenCalled();
|
||||
expect(plt.exitApp).not.toHaveBeenCalled();
|
||||
|
||||
app.goBack();
|
||||
expect(nav.pop).toHaveBeenCalled();
|
||||
|
||||
mockViews(nav, [view1]);
|
||||
|
||||
app.goBack();
|
||||
expect(plt.exitApp).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getActiveNav', () => {
|
||||
|
||||
it('should get active NavController when using tabs with nested nav', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
let tabs = mockTabs();
|
||||
let tab1 = mockTab(tabs);
|
||||
let tab2 = mockTab(tabs);
|
||||
const tabs = mockTabs();
|
||||
const tab1 = mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
nav.registerChildNav(tabs);
|
||||
|
||||
tab2.setSelected(true);
|
||||
let nav2 = mockNavController();
|
||||
let nav3 = mockNavController();
|
||||
let nav4 = mockNavController();
|
||||
const nav2 = mockNavController();
|
||||
const nav3 = mockNavController();
|
||||
const nav4 = mockNavController();
|
||||
tab1.registerChildNav(nav4);
|
||||
tab2.registerChildNav(nav2);
|
||||
tab2.registerChildNav(nav3);
|
||||
|
||||
expect(app.getActiveNav()).toBe(nav3);
|
||||
expect(app.getActiveNav(nav.id)).toBe(nav3);
|
||||
});
|
||||
|
||||
it('should get active NavController when using tabs, nested in a root nav', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
let tabs = mockTabs();
|
||||
const tabs = mockTabs();
|
||||
mockTab(tabs);
|
||||
let tab2 = mockTab(tabs);
|
||||
let tab3 = mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
const tab3 = mockTab(tabs);
|
||||
nav.registerChildNav(tabs);
|
||||
|
||||
tab2.setSelected(true);
|
||||
|
||||
expect(app.getActiveNav()).toBe(tab2);
|
||||
expect(app.getActiveNav(nav.id)).toBe(tab2);
|
||||
|
||||
tab2.setSelected(false);
|
||||
tab3.setSelected(true);
|
||||
expect(app.getActiveNav()).toBe(tab3);
|
||||
expect(app.getActiveNav(nav.id)).toBe(tab3);
|
||||
});
|
||||
|
||||
it('should get active tab NavController when using tabs, and tabs is the root', () => {
|
||||
let tabs = mockTabs();
|
||||
const tabs = mockTabs();
|
||||
mockTab(tabs);
|
||||
let tab2 = mockTab(tabs);
|
||||
let tab3 = mockTab(tabs);
|
||||
app._setRootNav(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
const tab3 = mockTab(tabs);
|
||||
app.registerRootNav(tabs);
|
||||
|
||||
tab2.setSelected(true);
|
||||
|
||||
expect(app.getActiveNav()).toBe(tab2);
|
||||
expect(app.getActiveNav(tabs.id)).toBe(tab2);
|
||||
|
||||
tab2.setSelected(false);
|
||||
tab3.setSelected(true);
|
||||
expect(app.getActiveNav()).toBe(tab3);
|
||||
expect(app.getActiveNav(tabs.id)).toBe(tab3);
|
||||
});
|
||||
|
||||
it('should get active NavController when nested 3 deep', () => {
|
||||
let nav1 = mockNavController();
|
||||
let nav2 = mockNavController();
|
||||
let nav3 = mockNavController();
|
||||
app._setRootNav(nav1);
|
||||
const nav1 = mockNavController();
|
||||
const nav2 = mockNavController();
|
||||
const nav3 = mockNavController();
|
||||
app.registerRootNav(nav1);
|
||||
|
||||
nav1.registerChildNav(nav2);
|
||||
nav2.registerChildNav(nav3);
|
||||
|
||||
expect(app.getActiveNav()).toBe(nav3);
|
||||
expect(app.getActiveNav(nav1.id)).toBe(nav3);
|
||||
});
|
||||
|
||||
it('should get active NavController when nested 2 deep', () => {
|
||||
let nav1 = mockNavController();
|
||||
let nav2 = mockNavController();
|
||||
app._setRootNav(nav1);
|
||||
const nav1 = mockNavController();
|
||||
const nav2 = mockNavController();
|
||||
app.registerRootNav(nav1);
|
||||
|
||||
nav1.registerChildNav(nav2);
|
||||
expect(app.getActiveNav()).toBe(nav2);
|
||||
|
||||
const activeNav = app.getActiveNav(nav1.id);
|
||||
|
||||
expect(activeNav).toBe(nav2);
|
||||
});
|
||||
|
||||
it('should get active NavController when only one nav controller', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
expect(app.getActiveNav()).toBe(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
expect(app.getActiveNav(nav.id)).toBe(nav);
|
||||
});
|
||||
|
||||
it('should set/get the root nav controller', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
expect(app.getRootNav()).toBe(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
expect(app.getRootNavById(nav.id)).toBe(nav);
|
||||
});
|
||||
|
||||
it('should not get an active NavController if there is not root set', () => {
|
||||
expect(app.getActiveNav()).toBeNull();
|
||||
expect(app.getRootNav()).toBeNull();
|
||||
const activeNav = app.getActiveNav('');
|
||||
const rootNav = app.getRootNavById('');
|
||||
expect(activeNav).toBeFalsy();
|
||||
expect(rootNav).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should just work when there are multiple active navs', () => {
|
||||
const rootNavOne = mockNavController();
|
||||
const rootNavTwo = mockNavController();
|
||||
|
||||
app.registerRootNav(rootNavOne);
|
||||
app.registerRootNav(rootNavTwo);
|
||||
|
||||
const childNavOne = mockNavController();
|
||||
const childNavTwo = mockNavController();
|
||||
|
||||
rootNavOne.registerChildNav(childNavOne);
|
||||
rootNavTwo.registerChildNav(childNavTwo);
|
||||
|
||||
const activeNavOne = app.getActiveNav(rootNavOne.id);
|
||||
const activeNavTwo = app.getActiveNav(rootNavTwo.id);
|
||||
|
||||
expect(activeNavOne).toBe(childNavOne);
|
||||
expect(activeNavTwo).toBe(childNavTwo);
|
||||
});
|
||||
|
||||
it('should get the active nav when no id is provided assuming there is one nav', () => {
|
||||
const rootNavOne = mockNavController();
|
||||
app.registerRootNav(rootNavOne);
|
||||
|
||||
const childNavOne = mockNavController();
|
||||
rootNavOne.registerChildNav(childNavOne);
|
||||
|
||||
const result = app.getActiveNav();
|
||||
|
||||
expect(result).toEqual(childNavOne);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRootNavs', () => {
|
||||
it('should return an array of navs', () => {
|
||||
const rootNavOne = mockNavController();
|
||||
app.registerRootNav(rootNavOne);
|
||||
const rootNavTwo = mockNavController();
|
||||
app.registerRootNav(rootNavTwo);
|
||||
|
||||
const results = app.getRootNavs();
|
||||
expect(results.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRootNav', () => {
|
||||
it('should return the single root nav', () => {
|
||||
const rootNavOne = mockNavController();
|
||||
app.registerRootNav(rootNavOne);
|
||||
const result = app.getRootNav();
|
||||
expect(result).toEqual(rootNavOne);
|
||||
});
|
||||
|
||||
it('should return the first nav in the list for backwards compatibility', () => {
|
||||
const rootNavOne = mockNavController();
|
||||
app.registerRootNav(rootNavOne);
|
||||
const rootNavTwo = mockNavController();
|
||||
app.registerRootNav(rootNavTwo);
|
||||
|
||||
const result = app.getRootNav();
|
||||
expect(result).toEqual(rootNavOne);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -381,7 +496,7 @@ describe('App', () => {
|
||||
|
||||
it('should enable click block when false is passed with duration', () => {
|
||||
// arrange
|
||||
let mockClickBlock: any = {
|
||||
const mockClickBlock: any = {
|
||||
activate: () => {}
|
||||
};
|
||||
|
||||
@@ -398,7 +513,7 @@ describe('App', () => {
|
||||
|
||||
it('should enable click block when false is passed w/o duration', () => {
|
||||
// arrange
|
||||
let mockClickBlock: any = {
|
||||
const mockClickBlock: any = {
|
||||
activate: () => {}
|
||||
};
|
||||
|
||||
@@ -416,7 +531,7 @@ describe('App', () => {
|
||||
|
||||
it('should enable click block when false is passed with a duration of 0 and with a minDuration', () => {
|
||||
// arrange
|
||||
let mockClickBlock: any = {
|
||||
const mockClickBlock: any = {
|
||||
activate: () => {}
|
||||
};
|
||||
|
||||
@@ -433,7 +548,7 @@ describe('App', () => {
|
||||
|
||||
it('should enable click block when false is passed with a null duration and a minDuration', () => {
|
||||
// arrange
|
||||
let mockClickBlock: any = {
|
||||
const mockClickBlock: any = {
|
||||
activate: () => {}
|
||||
};
|
||||
|
||||
@@ -450,7 +565,7 @@ describe('App', () => {
|
||||
|
||||
it('should enable click block when false is passed with a duration and a minDuration', () => {
|
||||
// arrange
|
||||
let mockClickBlock: any = {
|
||||
const mockClickBlock: any = {
|
||||
activate: () => {}
|
||||
};
|
||||
|
||||
@@ -466,10 +581,10 @@ describe('App', () => {
|
||||
});
|
||||
});
|
||||
|
||||
var app: App;
|
||||
var config: Config;
|
||||
var plt: MockPlatform;
|
||||
var portal: OverlayPortal;
|
||||
let app: App;
|
||||
let config: Config;
|
||||
let plt: MockPlatform;
|
||||
let portal: OverlayPortal;
|
||||
|
||||
beforeEach(() => {
|
||||
config = mockConfig();
|
||||
|
||||
@@ -60,51 +60,51 @@
|
||||
</ion-row>
|
||||
|
||||
<div class="float-elements-row">
|
||||
<div pull-left>pull-left</div>
|
||||
<div pull-sm-left>pull-sm-left</div>
|
||||
<div pull-md-left>pull-md-left</div>
|
||||
<div pull-lg-left>pull-lg-left</div>
|
||||
<div pull-xl-left>pull-xl-left</div>
|
||||
<div float-left>float-left</div>
|
||||
<div float-sm-left>float-sm-left</div>
|
||||
<div float-md-left>float-md-left</div>
|
||||
<div float-lg-left>float-lg-left</div>
|
||||
<div float-xl-left>float-xl-left</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row">
|
||||
<div pull-right>pull-right</div>
|
||||
<div pull-sm-right>pull-sm-right</div>
|
||||
<div pull-md-right>pull-md-right</div>
|
||||
<div pull-lg-right>pull-lg-right</div>
|
||||
<div pull-xl-right>pull-xl-right</div>
|
||||
<div float-right>float-right</div>
|
||||
<div float-sm-right>float-sm-right</div>
|
||||
<div float-md-right>float-md-right</div>
|
||||
<div float-lg-right>float-lg-right</div>
|
||||
<div float-xl-right>float-xl-right</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row">
|
||||
<div pull-start>pull-start</div>
|
||||
<div pull-sm-start>pull-sm-start</div>
|
||||
<div pull-md-start>pull-md-start</div>
|
||||
<div pull-lg-start>pull-lg-start</div>
|
||||
<div pull-xl-start>pull-xl-start</div>
|
||||
<div float-start>float-start</div>
|
||||
<div float-sm-start>float-sm-start</div>
|
||||
<div float-md-start>float-md-start</div>
|
||||
<div float-lg-start>float-lg-start</div>
|
||||
<div float-xl-start>float-xl-start</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row">
|
||||
<div pull-end>pull-end</div>
|
||||
<div pull-sm-end>pull-sm-end</div>
|
||||
<div pull-md-end>pull-md-end</div>
|
||||
<div pull-lg-end>pull-lg-end</div>
|
||||
<div pull-xl-end>pull-xl-end</div>
|
||||
<div float-end>float-end</div>
|
||||
<div float-sm-end>float-sm-end</div>
|
||||
<div float-md-end>float-md-end</div>
|
||||
<div float-lg-end>float-lg-end</div>
|
||||
<div float-xl-end>float-xl-end</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row" dir="rtl">
|
||||
<div pull-start>pull-start</div>
|
||||
<div pull-sm-start>pull-sm-start</div>
|
||||
<div pull-md-start>pull-md-start</div>
|
||||
<div pull-lg-start>pull-lg-start</div>
|
||||
<div pull-xl-start>pull-xl-start</div>
|
||||
<div float-start>float-start</div>
|
||||
<div float-sm-start>float-sm-start</div>
|
||||
<div float-md-start>float-md-start</div>
|
||||
<div float-lg-start>float-lg-start</div>
|
||||
<div float-xl-start>float-xl-start</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row" dir="rtl">
|
||||
<div pull-end>pull-end</div>
|
||||
<div pull-sm-end>pull-sm-end</div>
|
||||
<div pull-md-end>pull-md-end</div>
|
||||
<div pull-lg-end>pull-lg-end</div>
|
||||
<div pull-xl-end>pull-xl-end</div>
|
||||
<div float-end>float-end</div>
|
||||
<div float-sm-end>float-sm-end</div>
|
||||
<div float-md-end>float-md-end</div>
|
||||
<div float-lg-end>float-lg-end</div>
|
||||
<div float-xl-end>float-xl-end</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[icon-left] ion-icon {
|
||||
[icon-left] ion-icon, // deprecated
|
||||
[icon-start] ion-icon {
|
||||
@include button-icon;
|
||||
|
||||
@include padding-horizontal(null, .3em);
|
||||
}
|
||||
|
||||
[icon-right] ion-icon {
|
||||
[icon-right] ion-icon, // deprecated
|
||||
[icon-end] ion-icon {
|
||||
@include button-icon;
|
||||
|
||||
@include padding-horizontal(.4em, null);
|
||||
|
||||
@@ -470,8 +470,8 @@ $button-md-strong-font-weight: bold !default;
|
||||
// it's display none, and .md sets to display block.
|
||||
|
||||
.button-effect {
|
||||
@include position(0, null, null, 0);
|
||||
@include border-radius(50%);
|
||||
@include transform-origin(center, center);
|
||||
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
@@ -480,13 +480,19 @@ $button-md-strong-font-weight: bold !default;
|
||||
background-color: $button-md-ripple-background-color;
|
||||
opacity: .2;
|
||||
|
||||
transform-origin: center center;
|
||||
transition-timing-function: ease-in-out;
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
@include multi-dir() {
|
||||
// scss-lint:disable PropertySpelling
|
||||
top: 0;
|
||||
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.md .button-effect {
|
||||
.md button .button-effect {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,12 +42,12 @@ import { isTrueProperty } from '../../util/util';
|
||||
* <button ion-button round outline>Outline + Round</button>
|
||||
*
|
||||
* <!-- Icons -->
|
||||
* <button ion-button icon-left>
|
||||
* <button ion-button icon-start>
|
||||
* <ion-icon name="star"></ion-icon>
|
||||
* Left Icon
|
||||
* </button>
|
||||
*
|
||||
* <button ion-button icon-right>
|
||||
* <button ion-button icon-end>
|
||||
* Right Icon
|
||||
* <ion-icon name="star"></ion-icon>
|
||||
* </button>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a ion-button block href="#" icon-left><ion-icon name="help-circle"></ion-icon> a[ion-button][block] icon</a>
|
||||
<button ion-button block icon-left><ion-icon name="help-circle"></ion-icon> button[ion-button][block] icon</button>
|
||||
<a ion-button block href="#" icon-start><ion-icon name="help-circle"></ion-icon> a[ion-button][block] icon</a>
|
||||
<button ion-button block icon-start><ion-icon name="help-circle"></ion-icon> button[ion-button][block] icon</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a ion-button full href="#" icon-left>
|
||||
<a ion-button full href="#" icon-start>
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
a[ion-button][full] + icon
|
||||
</a>
|
||||
<button ion-button full icon-left>
|
||||
<button ion-button full icon-start>
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
button[ion-button][full] + icon
|
||||
</button>
|
||||
|
||||
@@ -10,22 +10,22 @@
|
||||
<ion-content padding>
|
||||
|
||||
<div>
|
||||
<button ion-button icon-left>
|
||||
<button ion-button icon-start>
|
||||
<ion-icon name="home"></ion-icon>
|
||||
Left Icon
|
||||
</button>
|
||||
<a ion-button icon-left>
|
||||
<a ion-button icon-start>
|
||||
<ion-icon name="home"></ion-icon>
|
||||
Left Icon
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button ion-button icon-right>
|
||||
<button ion-button icon-end>
|
||||
Right Icon
|
||||
<ion-icon name="star"></ion-icon>
|
||||
</button>
|
||||
<a ion-button icon-right>
|
||||
<a ion-button icon-end>
|
||||
Right Icon
|
||||
<ion-icon name="star"></ion-icon>
|
||||
</a>
|
||||
@@ -41,22 +41,22 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button ion-button large icon-left>
|
||||
<button ion-button large icon-start>
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
Left, Large
|
||||
</button>
|
||||
<a ion-button large icon-left>
|
||||
<a ion-button large icon-start>
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
Left, Large
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button ion-button large icon-right>
|
||||
<button ion-button large icon-end>
|
||||
Right, Large
|
||||
<ion-icon name="settings"></ion-icon>
|
||||
</button>
|
||||
<a ion-button large icon-right>
|
||||
<a ion-button large icon-end>
|
||||
Right, Large
|
||||
<ion-icon name="settings"></ion-icon>
|
||||
</a>
|
||||
@@ -72,22 +72,22 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button ion-button small icon-left>
|
||||
<button ion-button small icon-start>
|
||||
<ion-icon name="checkmark"></ion-icon>
|
||||
Left, Small
|
||||
</button>
|
||||
<a ion-button small icon-left>
|
||||
<a ion-button small icon-start>
|
||||
<ion-icon name="checkmark"></ion-icon>
|
||||
Left, Small
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button ion-button small icon-right>
|
||||
<button ion-button small icon-end>
|
||||
Right, Small
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
<a ion-button small icon-right>
|
||||
<a ion-button small icon-end>
|
||||
Right, Small
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</a>
|
||||
|
||||
@@ -17,7 +17,7 @@ $card-ios-margin-bottom: 12px !default;
|
||||
// deprecated
|
||||
$card-ios-margin-left: 12px !default;
|
||||
/// @prop - Margin start of the card
|
||||
$card-ios-margin-start: $card-ios-margin-left;
|
||||
$card-ios-margin-start: $card-ios-margin-left !default;
|
||||
|
||||
/// @prop - Padding top of the card
|
||||
$card-ios-padding-top: 13px !default;
|
||||
@@ -25,7 +25,7 @@ $card-ios-padding-top: 13px !default;
|
||||
// deprecated
|
||||
$card-ios-padding-right: 16px !default;
|
||||
/// @prop - Padding end of the card
|
||||
$card-ios-padding-end: $card-ios-padding-right;
|
||||
$card-ios-padding-end: $card-ios-padding-right !default;
|
||||
|
||||
/// @prop - Padding bottom of the card
|
||||
$card-ios-padding-bottom: 14px !default;
|
||||
@@ -33,7 +33,7 @@ $card-ios-padding-bottom: 14px !default;
|
||||
// deprecated
|
||||
$card-ios-padding-left: 16px !default;
|
||||
/// @prop - Padding start of the card
|
||||
$card-ios-padding-start: $card-ios-padding-left;
|
||||
$card-ios-padding-start: $card-ios-padding-left !default;
|
||||
|
||||
/// @prop - Padding top of the media on the card
|
||||
$card-ios-padding-media-top: 10px !default;
|
||||
@@ -133,7 +133,7 @@ $card-ios-header-color: #333 !default;
|
||||
}
|
||||
|
||||
.card-ios ion-list {
|
||||
margin-bottom: 0;
|
||||
@include margin(null, null, 0, null);
|
||||
}
|
||||
|
||||
.card-ios > .item:last-child,
|
||||
@@ -165,7 +165,7 @@ $card-ios-header-color: #333 !default;
|
||||
|
||||
.card-header-ios + .card-content-ios,
|
||||
.card-ios .item + .card-content-ios {
|
||||
padding-top: 0;
|
||||
@include padding(0, null, null, null);
|
||||
}
|
||||
|
||||
.card .note-ios {
|
||||
@@ -220,7 +220,7 @@ $card-ios-header-color: #333 !default;
|
||||
}
|
||||
|
||||
.card-ios + ion-card {
|
||||
margin-top: 0;
|
||||
@include margin(0, null, null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ $card-md-margin-bottom: 10px !default;
|
||||
// deprecated
|
||||
$card-md-margin-left: 10px !default;
|
||||
/// @prop - Margin start of the card
|
||||
$card-md-margin-start: $card-md-margin-left;
|
||||
$card-md-margin-start: $card-md-margin-left !default;
|
||||
|
||||
|
||||
/// @prop - Padding top of the card
|
||||
@@ -26,7 +26,7 @@ $card-md-padding-top: 13px !default;
|
||||
// deprecated
|
||||
$card-md-padding-right: 16px !default;
|
||||
/// @prop - Padding right of the card
|
||||
$card-md-padding-end: $card-md-padding-right;
|
||||
$card-md-padding-end: $card-md-padding-right !default;
|
||||
|
||||
/// @prop - Padding bottom of the card
|
||||
$card-md-padding-bottom: 13px !default;
|
||||
@@ -34,7 +34,7 @@ $card-md-padding-bottom: 13px !default;
|
||||
// deprecated
|
||||
$card-md-padding-left: 16px !default;
|
||||
/// @prop - Padding start of the card
|
||||
$card-md-padding-start: $card-md-padding-left;
|
||||
$card-md-padding-start: $card-md-padding-left !default;
|
||||
|
||||
/// @prop - Padding top of the media on the card
|
||||
$card-md-padding-media-top: 10px !default;
|
||||
@@ -138,7 +138,7 @@ $card-md-header-color: #222 !default;
|
||||
}
|
||||
|
||||
.card-md ion-list {
|
||||
margin-bottom: 0;
|
||||
@include margin(null, null, 0, null);
|
||||
}
|
||||
|
||||
.card-md > .item:last-child,
|
||||
@@ -169,7 +169,7 @@ $card-md-header-color: #222 !default;
|
||||
|
||||
.card-header-md + .card-content-md,
|
||||
.card-md .item + .card-content-md {
|
||||
padding-top: 0;
|
||||
@include padding(0, null, null, null);
|
||||
}
|
||||
|
||||
.card .note-md {
|
||||
@@ -229,7 +229,7 @@ $card-md-header-color: #222 !default;
|
||||
}
|
||||
|
||||
.card-md + ion-card {
|
||||
margin-top: 0;
|
||||
@include margin(0, null, null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ $card-wp-margin-bottom: 8px !default;
|
||||
// deprecated
|
||||
$card-wp-margin-left: 8px !default;
|
||||
/// @prop - Margin start of the card
|
||||
$card-wp-margin-start: $card-wp-margin-left;
|
||||
$card-wp-margin-start: $card-wp-margin-left !default;
|
||||
|
||||
/// @prop - Padding top of the card
|
||||
$card-wp-padding-top: 13px !default;
|
||||
@@ -25,7 +25,7 @@ $card-wp-padding-top: 13px !default;
|
||||
// deprecated
|
||||
$card-wp-padding-right: 16px !default;
|
||||
/// @prop - Padding end of the card
|
||||
$card-wp-padding-end: $card-wp-padding-right;
|
||||
$card-wp-padding-end: $card-wp-padding-right !default;
|
||||
|
||||
/// @prop - Padding bottom of the card
|
||||
$card-wp-padding-bottom: 13px !default;
|
||||
@@ -33,7 +33,7 @@ $card-wp-padding-bottom: 13px !default;
|
||||
// deprecated
|
||||
$card-wp-padding-left: 16px !default;
|
||||
/// @prop - Padding start of the card
|
||||
$card-wp-padding-start: $card-wp-padding-left;
|
||||
$card-wp-padding-start: $card-wp-padding-left !default;
|
||||
|
||||
/// @prop - Padding top of the media on the card
|
||||
$card-wp-padding-media-top: 10px !default;
|
||||
@@ -139,7 +139,7 @@ $card-wp-header-color: #222 !default;
|
||||
}
|
||||
|
||||
.card-wp ion-list {
|
||||
margin-bottom: 0;
|
||||
@include margin(null, null, 0, null);
|
||||
}
|
||||
|
||||
.card-wp > .item:last-child,
|
||||
@@ -171,7 +171,7 @@ $card-wp-header-color: #222 !default;
|
||||
|
||||
.card-header-wp + .card-content-wp,
|
||||
.card-wp .item + .card-content-wp {
|
||||
padding-top: 0;
|
||||
@include padding(0, null, null, null);
|
||||
}
|
||||
|
||||
.card .note-wp {
|
||||
@@ -231,7 +231,7 @@ $card-wp-header-color: #222 !default;
|
||||
}
|
||||
|
||||
.card-wp + ion-card {
|
||||
margin-top: 0;
|
||||
@include margin(0, null, null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col no-padding>
|
||||
<button ion-button icon-left clear small>
|
||||
<button ion-button icon-start clear small>
|
||||
<ion-icon name="star"></ion-icon>
|
||||
Star
|
||||
</button>
|
||||
</ion-col>
|
||||
<ion-col no-padding text-right>
|
||||
<button ion-button icon-left clear small class="activated">
|
||||
<button ion-button icon-start clear small class="activated">
|
||||
<ion-icon name="share"></ion-icon>
|
||||
Activated
|
||||
</button>
|
||||
@@ -66,13 +66,13 @@
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col no-padding>
|
||||
<button ion-button icon-left clear small>
|
||||
<button ion-button icon-start clear small>
|
||||
<ion-icon name="star"></ion-icon>
|
||||
Favorite
|
||||
</button>
|
||||
</ion-col>
|
||||
<ion-col no-padding text-center>
|
||||
<button ion-button icon-left clear small>
|
||||
<button ion-button icon-start clear small>
|
||||
<ion-icon name="musical-notes"></ion-icon>
|
||||
Listen
|
||||
</button>
|
||||
@@ -99,20 +99,20 @@
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col no-padding>
|
||||
<button ion-button icon-left clear small dark>
|
||||
<button ion-button icon-start clear small dark>
|
||||
<ion-icon name="star"></ion-icon>
|
||||
Favorite
|
||||
</button>
|
||||
</ion-col>
|
||||
|
||||
<ion-col no-padding text-center>
|
||||
<button ion-button icon-left clear small dark>
|
||||
<button ion-button icon-start clear small dark>
|
||||
<ion-icon name="musical-notes"></ion-icon>
|
||||
Listen
|
||||
</button>
|
||||
</ion-col>
|
||||
<ion-col no-padding text-right>
|
||||
<button ion-button icon-left clear small dark>
|
||||
<button ion-button icon-start clear small dark>
|
||||
<ion-icon name="share-alt"></ion-icon>
|
||||
Share
|
||||
</button>
|
||||
|
||||
@@ -71,13 +71,13 @@
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col no-padding>
|
||||
<button ion-button icon-left clear small color="danger">
|
||||
<button ion-button icon-start clear small color="danger">
|
||||
<ion-icon name="star"></ion-icon>
|
||||
Danger
|
||||
</button>
|
||||
</ion-col>
|
||||
<ion-col no-padding text-right>
|
||||
<button ion-button icon-left clear small color="dark">
|
||||
<button ion-button icon-start clear small color="dark">
|
||||
<ion-icon name="share"></ion-icon>
|
||||
Dark
|
||||
</button>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<ion-item>
|
||||
<span item-start>18 min</span>
|
||||
<span item-start>(2.6 mi)</span>
|
||||
<button ion-button icon-left primary clear item-end>
|
||||
<button ion-button icon-start primary clear item-end>
|
||||
<ion-icon name="navigate"></ion-icon>
|
||||
Start
|
||||
</button>
|
||||
@@ -61,7 +61,7 @@
|
||||
<ion-item>
|
||||
<span item-start>3 hr</span>
|
||||
<span item-start>(4.8 mi)</span>
|
||||
<button ion-button icon-left danger clear item-end>
|
||||
<button ion-button icon-start danger clear item-end>
|
||||
<ion-icon name="navigate"></ion-icon>
|
||||
Start
|
||||
</button>
|
||||
@@ -91,7 +91,7 @@
|
||||
<ion-item>
|
||||
<span item-start secondary>26 min</span>
|
||||
<span item-start>(8.1 mi)</span>
|
||||
<button ion-button icon-left secondary clear item-end>
|
||||
<button ion-button icon-start secondary clear item-end>
|
||||
<ion-icon name="navigate"></ion-icon>
|
||||
Start
|
||||
</button>
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
</ion-card-content>
|
||||
|
||||
<ion-item>
|
||||
<button ion-button icon-left primary clear item-start>
|
||||
<button ion-button icon-start primary clear item-start>
|
||||
<ion-icon name="thumbs-up"></ion-icon>
|
||||
<div>12 Likes</div>
|
||||
</button>
|
||||
<button ion-button icon-left primary clear item-start>
|
||||
<button ion-button icon-start primary clear item-start>
|
||||
<ion-icon name="text"></ion-icon>
|
||||
<div>4 Comments</div>
|
||||
</button>
|
||||
@@ -59,11 +59,11 @@
|
||||
</ion-card-content>
|
||||
|
||||
<ion-item>
|
||||
<button ion-button icon-left primary clear item-start>
|
||||
<button ion-button icon-start primary clear item-start>
|
||||
<ion-icon name="thumbs-up"></ion-icon>
|
||||
<div>30 Likes</div>
|
||||
</button>
|
||||
<button ion-button icon-left primary clear item-start>
|
||||
<button ion-button icon-start primary clear item-start>
|
||||
<ion-icon name="text"></ion-icon>
|
||||
<div>64 Comments</div>
|
||||
</button>
|
||||
@@ -91,11 +91,11 @@
|
||||
</ion-card-content>
|
||||
|
||||
<ion-item>
|
||||
<button ion-button icon-left primary clear item-start>
|
||||
<button ion-button icon-start primary clear item-start>
|
||||
<ion-icon name="thumbs-up"></ion-icon>
|
||||
<div>46 Likes</div>
|
||||
</button>
|
||||
<button ion-button icon-left primary clear item-start>
|
||||
<button ion-button icon-start primary clear item-start>
|
||||
<ion-icon name="text"></ion-icon>
|
||||
<div>66 Comments</div>
|
||||
</button>
|
||||
|
||||
@@ -15,7 +15,7 @@ import { Item } from '../item/item';
|
||||
* The Checkbox is a simple component styled based on the mode. It can be
|
||||
* placed in an `ion-item` or used as a stand-alone checkbox.
|
||||
*
|
||||
* See the [Angular 2 Docs](https://angular.io/docs/ts/latest/guide/forms.html)
|
||||
* See the [Angular Docs](https://angular.io/docs/ts/latest/guide/forms.html)
|
||||
* for more info on forms and inputs.
|
||||
*
|
||||
*
|
||||
@@ -65,7 +65,7 @@ import { Item } from '../item/item';
|
||||
* cucumber: boolean;
|
||||
*
|
||||
* updateCucumber() {
|
||||
* console.log("Cucumbers new state:" + this.cucumber);
|
||||
* console.log('Cucumbers new state:' + this.cucumber);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
@@ -118,13 +118,6 @@ export class Checkbox extends BaseInput<boolean> implements IonicTapInput, OnDes
|
||||
super(config, elementRef, renderer, 'checkbox', false, form, item, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
initFocus() {
|
||||
this._elementRef.nativeElement.querySelector('button').focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
@@ -145,8 +138,8 @@ export class Checkbox extends BaseInput<boolean> implements IonicTapInput, OnDes
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
_inputCheckHasValue(val: boolean) {
|
||||
this._item && this._item.setElementClass('item-checkbox-checked', val);
|
||||
_inputUpdated() {
|
||||
this._item && this._item.setElementClass('item-checkbox-checked', this._value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import { Ion } from '../ion';
|
||||
*
|
||||
* <ion-chip>
|
||||
* <ion-avatar>
|
||||
* <img src="img/my-img.png">
|
||||
* <img src="assets/img/my-img.png">
|
||||
* </ion-avatar>
|
||||
* <ion-label>Default</ion-label>
|
||||
* </ion-chip>
|
||||
|
||||
@@ -58,6 +58,10 @@ ion-content.js-scroll > .scroll-content {
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
ion-content.has-refresher > .scroll-content {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
|
||||
// Fixed Content (ion-fixed and ion-fab)
|
||||
// --------------------------------------------------
|
||||
@@ -94,7 +98,7 @@ ion-app [no-padding] .scroll-content {
|
||||
|
||||
ion-app.#{$mode} [padding-top],
|
||||
ion-app.#{$mode} [padding-top] .scroll-content {
|
||||
padding-top: $content-padding;
|
||||
@include padding($content-padding, null, null, null);
|
||||
}
|
||||
|
||||
ion-app.#{$mode} [padding-left],
|
||||
@@ -109,13 +113,12 @@ ion-app [no-padding] .scroll-content {
|
||||
|
||||
ion-app.#{$mode} [padding-bottom],
|
||||
ion-app.#{$mode} [padding-bottom] .scroll-content {
|
||||
padding-bottom: $content-padding;
|
||||
@include padding(null, null, $content-padding, null);
|
||||
}
|
||||
|
||||
ion-app.#{$mode} [padding-vertical],
|
||||
ion-app.#{$mode} [padding-vertical] .scroll-content {
|
||||
padding-top: $content-padding;
|
||||
padding-bottom: $content-padding;
|
||||
@include padding($content-padding, null, $content-padding, null);
|
||||
}
|
||||
|
||||
ion-app.#{$mode} [padding-horizontal],
|
||||
@@ -141,7 +144,7 @@ ion-app [no-margin] .scroll-content {
|
||||
|
||||
ion-app.#{$mode} [margin-top],
|
||||
ion-app.#{$mode} [margin-top] .scroll-content {
|
||||
margin-top: $content-margin;
|
||||
@include margin($content-margin, null, null, null);
|
||||
}
|
||||
|
||||
ion-app.#{$mode} [margin-left],
|
||||
@@ -168,13 +171,12 @@ ion-app [no-margin] .scroll-content {
|
||||
|
||||
ion-app.#{$mode} [margin-bottom],
|
||||
ion-app.#{$mode} [margin-bottom] .scroll-content {
|
||||
margin-bottom: $content-margin;
|
||||
@include margin(null, null, $content-margin, null);
|
||||
}
|
||||
|
||||
ion-app.#{$mode} [margin-vertical],
|
||||
ion-app.#{$mode} [margin-vertical] .scroll-content {
|
||||
margin-top: $content-margin;
|
||||
margin-bottom: $content-margin;
|
||||
@include margin($content-margin, null, $content-margin, null);
|
||||
}
|
||||
|
||||
ion-app.#{$mode} [margin-horizontal],
|
||||
|
||||
@@ -63,7 +63,44 @@ export class EventEmitterProxy<T> extends EventEmitter<T> {
|
||||
*
|
||||
* @advanced
|
||||
*
|
||||
* Resizing the content. If the height of `ion-header`, `ion-footer` or `ion-tabbar`
|
||||
* ### Sroll Events
|
||||
*
|
||||
* Scroll events happen outside of Angular's Zones. This is for performance reasons. So
|
||||
* if you're trying to bind a value to any scroll event, it will need to be wrapped in
|
||||
* a `zone.run()`
|
||||
*
|
||||
* ```ts
|
||||
* import { Component, NgZone } from '@angular/core';
|
||||
* @Component({
|
||||
* template: `
|
||||
* <ion-header>
|
||||
* <ion-navbar>
|
||||
* <ion-title>{{scrollAmount}}</ion-title>
|
||||
* </ion-navbar>
|
||||
* </ion-header>
|
||||
* <ion-content (ionScroll)="scrollHandler($event)">
|
||||
* <p> Some realllllllly long content </p>
|
||||
* </ion-content>
|
||||
* `})
|
||||
* class E2EPage {
|
||||
* public scrollAmount = 0;
|
||||
* constructor( public zone: NgZone){}
|
||||
* scrollHandler(event) {
|
||||
* console.log(`ScrollEvent: ${event}`)
|
||||
* this.zone.run(()=>{
|
||||
* // since scrollAmount is data-binded,
|
||||
* // the update needs to happen in zone
|
||||
* this.scrollAmount++
|
||||
* })
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* This goes for any scroll event, not just `ionScroll`.
|
||||
*
|
||||
* ### Resizing the content
|
||||
*
|
||||
* If the height of `ion-header`, `ion-footer` or `ion-tabbar`
|
||||
* changes dynamically, `content.resize()` has to be called in order to update the
|
||||
* layout of `Content`.
|
||||
*
|
||||
@@ -130,7 +167,8 @@ export class EventEmitterProxy<T> extends EventEmitter<T> {
|
||||
'</div>' +
|
||||
'<ng-content select="ion-refresher"></ng-content>',
|
||||
host: {
|
||||
'[class.statusbar-padding]': 'statusbarPadding'
|
||||
'[class.statusbar-padding]': 'statusbarPadding',
|
||||
'[class.has-refresher]': '_hasRefresher'
|
||||
},
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
@@ -175,6 +213,8 @@ export class Content extends Ion implements OnDestroy, AfterViewInit, IContent {
|
||||
/** @internal */
|
||||
_fullscreen: boolean;
|
||||
/** @internal */
|
||||
_hasRefresher: boolean = false;
|
||||
/** @internal */
|
||||
_footerEle: HTMLElement;
|
||||
/** @internal */
|
||||
_dirty: boolean;
|
||||
@@ -745,6 +785,11 @@ export class Content extends Ion implements OnDestroy, AfterViewInit, IContent {
|
||||
this._cBottom += this._tabbarHeight;
|
||||
}
|
||||
|
||||
// Refresher uses a border which should be hidden unless pulled
|
||||
if (this._hasRefresher) {
|
||||
this._cTop -= 1;
|
||||
}
|
||||
|
||||
// Fixed content shouldn't include content padding
|
||||
this._fTop = this._cTop;
|
||||
this._fBottom = this._cBottom;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-navbar style="opacity: 0.8">
|
||||
<ion-title>Page 4</ion-title>
|
||||
<ion-buttons right>
|
||||
<button ion-button icon-right [navPush]="tabsPage">
|
||||
<button ion-button icon-end [navPush]="tabsPage">
|
||||
Next
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-navbar style="opacity: 0.8">
|
||||
<ion-title>Page 3</ion-title>
|
||||
<ion-buttons right>
|
||||
<button ion-button icon-right [navPush]="page4">
|
||||
<button ion-button icon-end [navPush]="page4">
|
||||
Next
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-navbar style="opacity: 0.8">
|
||||
<ion-title>Main</ion-title>
|
||||
<ion-buttons right>
|
||||
<button ion-button icon-right [navPush]="page1">
|
||||
<button ion-button icon-end [navPush]="page1">
|
||||
Next
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-navbar style="opacity: 0.8">
|
||||
<ion-title>Page 2</ion-title>
|
||||
<ion-buttons right>
|
||||
<button ion-button icon-right [navPush]="page3">
|
||||
<button ion-button icon-end [navPush]="page3">
|
||||
Next
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-navbar style="opacity: 0.8">
|
||||
<ion-title>Page 4</ion-title>
|
||||
<ion-buttons right>
|
||||
<button ion-button icon-right [navPush]="tabsPage">
|
||||
<button ion-button icon-end [navPush]="tabsPage">
|
||||
Next
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-navbar style="opacity: 0.8">
|
||||
<ion-title>Page 3</ion-title>
|
||||
<ion-buttons right>
|
||||
<button ion-button icon-right [navPush]="page4">
|
||||
<button ion-button icon-end [navPush]="page4">
|
||||
Next
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-navbar style="opacity: 0.8">
|
||||
<ion-title>Main</ion-title>
|
||||
<ion-buttons right>
|
||||
<button ion-button icon-right [navPush]="page1">
|
||||
<button ion-button icon-end [navPush]="page1">
|
||||
Next
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-navbar style="opacity: 0.8">
|
||||
<ion-title>Page 2</ion-title>
|
||||
<ion-buttons right>
|
||||
<button ion-button icon-right [navPush]="page3">
|
||||
<button ion-button icon-end [navPush]="page3">
|
||||
Next
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</button>
|
||||
|
||||
@@ -9,7 +9,7 @@ $datetime-ios-padding-top: $item-ios-padding-top !default;
|
||||
// deprecated
|
||||
$datetime-ios-padding-right: ($item-ios-padding-end / 2) !default;
|
||||
/// @prop - Padding end of the DateTime component
|
||||
$datetime-ios-padding-end: $datetime-ios-padding-right;
|
||||
$datetime-ios-padding-end: $datetime-ios-padding-right !default;
|
||||
|
||||
/// @prop - Padding bottom of the DateTime component
|
||||
$datetime-ios-padding-bottom: $item-ios-padding-bottom !default;
|
||||
@@ -17,7 +17,7 @@ $datetime-ios-padding-bottom: $item-ios-padding-bottom !default;
|
||||
// deprecated
|
||||
$datetime-ios-padding-left: $item-ios-padding-start !default;
|
||||
/// @prop - Padding start of the DateTime component
|
||||
$datetime-ios-padding-start: $datetime-ios-padding-left;
|
||||
$datetime-ios-padding-start: $datetime-ios-padding-left !default;
|
||||
|
||||
/// @prop - Color of the DateTime placeholder
|
||||
$datetime-ios-placeholder-color: #999 !default;
|
||||
|
||||
@@ -9,7 +9,7 @@ $datetime-md-padding-top: $item-md-padding-top !default;
|
||||
// deprecated
|
||||
$datetime-md-padding-right: ($item-md-padding-end / 2) !default;
|
||||
/// @prop - Padding end of the DateTime component
|
||||
$datetime-md-padding-end: $datetime-md-padding-right;
|
||||
$datetime-md-padding-end: $datetime-md-padding-right !default;
|
||||
|
||||
/// @prop - Padding bottom of the DateTime component
|
||||
$datetime-md-padding-bottom: $item-md-padding-bottom !default;
|
||||
@@ -17,7 +17,7 @@ $datetime-md-padding-bottom: $item-md-padding-bottom !default;
|
||||
// deprecated
|
||||
$datetime-md-padding-left: $item-md-padding-start !default;
|
||||
/// @prop - Padding start of the DateTime component
|
||||
$datetime-md-padding-start: $datetime-md-padding-left;
|
||||
$datetime-md-padding-start: $datetime-md-padding-left !default;
|
||||
|
||||
/// @prop - Color of the DateTime placeholder
|
||||
$datetime-md-placeholder-color: #999 !default;
|
||||
|
||||
@@ -448,6 +448,7 @@ export class DateTime extends BaseInput<DateTimeData> implements AfterContentIni
|
||||
* @hidden
|
||||
*/
|
||||
_inputUpdated() {
|
||||
super._inputUpdated();
|
||||
this.updateText();
|
||||
}
|
||||
|
||||
@@ -475,10 +476,6 @@ export class DateTime extends BaseInput<DateTimeData> implements AfterContentIni
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
_click(ev: UIEvent) {
|
||||
// do not continue if the click event came from a form submit
|
||||
if (ev.detail === 0) {
|
||||
return;
|
||||
}
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.open();
|
||||
|
||||
@@ -12,7 +12,7 @@ $datetime-wp-padding-top: $item-wp-padding-top !default;
|
||||
// deprecated
|
||||
$datetime-wp-padding-right: ($item-wp-padding-end / 2) !default;
|
||||
/// @prop - Padding end of the DateTime component
|
||||
$datetime-wp-padding-end: $datetime-wp-padding-right;
|
||||
$datetime-wp-padding-end: $datetime-wp-padding-right !default;
|
||||
|
||||
/// @prop - Padding bottom of the DateTime component
|
||||
$datetime-wp-padding-bottom: $item-wp-padding-bottom !default;
|
||||
@@ -20,7 +20,7 @@ $datetime-wp-padding-bottom: $item-wp-padding-bottom !default;
|
||||
// deprecated
|
||||
$datetime-wp-padding-left: $item-wp-padding-start !default;
|
||||
/// @prop - Padding start of the DateTime component
|
||||
$datetime-wp-padding-start: $datetime-wp-padding-left;
|
||||
$datetime-wp-padding-start: $datetime-wp-padding-left !default;
|
||||
|
||||
/// @prop - Border width of the DateTime component
|
||||
$datetime-wp-border-width: 2px !default;
|
||||
@@ -48,7 +48,7 @@ $datetime-wp-placeholder-color: $input-wp-border-color !default;
|
||||
}
|
||||
|
||||
.item-datetime .datetime-wp ion-label[floating] {
|
||||
transform: translate3d(8px, 41px, 0);
|
||||
@include transform(translate3d(8px, 41px, 0));
|
||||
}
|
||||
|
||||
.datetime-wp .datetime-placeholder {
|
||||
|
||||
@@ -79,14 +79,13 @@ ion-fab {
|
||||
|
||||
&[center] {
|
||||
@include position(null, null, null, 50%);
|
||||
|
||||
@include margin-horizontal(-$fab-size / 2, null);
|
||||
}
|
||||
|
||||
&[middle] {
|
||||
top: 50%;
|
||||
@include margin(-$fab-size / 2, null, null, null);
|
||||
|
||||
margin-top: -$fab-size / 2;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
&[top] {
|
||||
@@ -95,7 +94,9 @@ ion-fab {
|
||||
|
||||
&[right] {
|
||||
// scss-lint:disable PropertySpelling
|
||||
right: $fab-content-margin;
|
||||
@include multi-dir() {
|
||||
right: $fab-content-margin;
|
||||
}
|
||||
}
|
||||
|
||||
&[end] {
|
||||
@@ -108,7 +109,9 @@ ion-fab {
|
||||
|
||||
&[left] {
|
||||
// scss-lint:disable PropertySpelling
|
||||
left: $fab-content-margin;
|
||||
@include multi-dir() {
|
||||
left: $fab-content-margin;
|
||||
}
|
||||
}
|
||||
|
||||
&[start] {
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
</ion-list>
|
||||
|
||||
<p>
|
||||
<button ion-button icon-left (click)="updateIcon()">
|
||||
<button ion-button icon-start (click)="updateIcon()">
|
||||
<ion-icon [name]="btnIcon"></ion-icon>
|
||||
Update icon
|
||||
</button>
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
</ion-list>
|
||||
|
||||
<p>
|
||||
<button ion-button icon-left (click)="updateIcon()">
|
||||
<button ion-button icon-start (click)="updateIcon()">
|
||||
<ion-icon [name]="btnIcon"></ion-icon>
|
||||
Update icon
|
||||
</button>
|
||||
|
||||
@@ -20,7 +20,7 @@ $text-input-ios-margin-bottom: $item-ios-padding-bottom !default;
|
||||
// deprecated
|
||||
$text-input-ios-margin-left: 0 !default;
|
||||
/// @prop - Margin start of the input
|
||||
$text-input-ios-margin-start: $text-input-ios-margin-left;
|
||||
$text-input-ios-margin-start: $text-input-ios-margin-left !default;
|
||||
|
||||
/// @prop - Width of the icon used to clear the input
|
||||
$text-input-ios-input-clear-icon-width: 30px !default;
|
||||
@@ -85,12 +85,17 @@ $text-input-ios-highlight-color-invalid: $text-input-highlight-color-invalid !
|
||||
@if ($text-input-ios-show-focus-highlight) {
|
||||
// In order to get a 2px border we need to add an inset
|
||||
// box-shadow 1px (this is to avoid the div resizing)
|
||||
|
||||
// TODO remove all uses of input-has-focus in v4
|
||||
// TODO remove all uses of input-has-value in v4
|
||||
.item-ios.item-input.item-input-has-focus .item-inner,
|
||||
.item-ios.item-input.input-has-focus .item-inner {
|
||||
@include ios-input-highlight($text-input-ios-highlight-color);
|
||||
}
|
||||
|
||||
// The last item in a list has a border on the item, not the
|
||||
// inner item, so add it to the item itself
|
||||
.list-ios .item-input.item-input-has-focus:last-child,
|
||||
.list-ios .item-input.input-has-focus:last-child {
|
||||
@include ios-input-highlight($text-input-ios-highlight-color);
|
||||
|
||||
@@ -102,11 +107,13 @@ $text-input-ios-highlight-color-invalid: $text-input-highlight-color-invalid !
|
||||
|
||||
// Show the valid highlight when it has the .ng-valid class and a value
|
||||
@if ($text-input-ios-show-valid-highlight) {
|
||||
.item-ios.item-input.ng-valid.input-has-value:not(.input-has-focus) .item-inner {
|
||||
.item-ios.item-input.ng-valid.item-input-has-value:not(.input-has-focus):not(.item-input-has-focus) .item-inner,
|
||||
.item-ios.item-input.ng-valid.input-has-value:not(.input-has-focus):not(.item-input-has-focus) .item-inner {
|
||||
@include ios-input-highlight($text-input-ios-highlight-color-valid);
|
||||
}
|
||||
|
||||
.list-ios .item-input.ng-valid.input-has-value:not(.input-has-focus):last-child {
|
||||
.list-ios .item-input.ng-valid.item-input-has-value:not(.input-has-focus):not(.item-input-has-focus):last-child,
|
||||
.list-ios .item-input.ng-valid.input-has-value:not(.input-has-focus):not(.item-input-has-focus):last-child {
|
||||
@include ios-input-highlight($text-input-ios-highlight-color-valid);
|
||||
|
||||
.item-inner {
|
||||
@@ -117,11 +124,11 @@ $text-input-ios-highlight-color-invalid: $text-input-highlight-color-invalid !
|
||||
|
||||
// Show the invalid highlight when it has the invalid class and has been touched
|
||||
@if ($text-input-ios-show-invalid-highlight) {
|
||||
.item-ios.item-input.ng-invalid.ng-touched:not(.input-has-focus) .item-inner {
|
||||
.item-ios.item-input.ng-invalid.ng-touched:not(.input-has-focus):not(.item-input-has-focus) .item-inner {
|
||||
@include ios-input-highlight($text-input-ios-highlight-color-invalid);
|
||||
}
|
||||
|
||||
.list-ios .item-input.ng-invalid.ng-touched:not(.input-has-focus):last-child {
|
||||
.list-ios .item-input.ng-invalid.ng-touched:not(.input-has-focus):not(.item-input-has-focus):last-child {
|
||||
@include ios-input-highlight($text-input-ios-highlight-color-invalid);
|
||||
|
||||
.item-inner {
|
||||
|
||||
@@ -86,12 +86,16 @@ $text-input-md-highlight-color-invalid: $text-input-highlight-color-invalid
|
||||
@if ($text-input-md-show-focus-highlight) {
|
||||
// In order to get a 2px border we need to add an inset
|
||||
// box-shadow 1px (this is to avoid the div resizing)
|
||||
|
||||
// TODO remove all uses of input-has-focus in v4
|
||||
.item-md.item-input.item-input-has-focus .item-inner,
|
||||
.item-md.item-input.input-has-focus .item-inner {
|
||||
@include md-input-highlight($text-input-md-highlight-color);
|
||||
}
|
||||
|
||||
// The last item in a list has a border on the item, not the
|
||||
// inner item, so add it to the item itself
|
||||
.list-md .item-input.item-input-has-focus:last-child,
|
||||
.list-md .item-input.input-has-focus:last-child {
|
||||
@include md-input-highlight($text-input-md-highlight-color);
|
||||
|
||||
@@ -103,11 +107,15 @@ $text-input-md-highlight-color-invalid: $text-input-highlight-color-invalid
|
||||
|
||||
// Show the valid highlight when it has the .ng-valid class and a value
|
||||
@if ($text-input-md-show-valid-highlight) {
|
||||
.item-md.item-input.ng-valid.input-has-value:not(.input-has-focus) .item-inner {
|
||||
// TODO remove all uses of input-has-focus in v4
|
||||
// TODO remove all uses of input-has-value in v4
|
||||
.item-md.item-input.ng-valid.item-input-has-value:not(.input-has-focus):not(.item-input-has-focus) .item-inner,
|
||||
.item-md.item-input.ng-valid.input-has-value:not(.input-has-focus):not(.item-input-has-focus) .item-inner {
|
||||
@include md-input-highlight($text-input-md-highlight-color-valid);
|
||||
}
|
||||
|
||||
.list-md .item-input.ng-valid.input-has-value:not(.input-has-focus):last-child {
|
||||
.list-md .item-input.ng-valid.item-input-has-value:not(.input-has-focus):not(.item-input-has-focus):last-child,
|
||||
.list-md .item-input.ng-valid.input-has-value:not(.input-has-focus):not(.item-input-has-focus):last-child {
|
||||
@include md-input-highlight($text-input-md-highlight-color-valid);
|
||||
|
||||
.item-inner {
|
||||
@@ -118,11 +126,11 @@ $text-input-md-highlight-color-invalid: $text-input-highlight-color-invalid
|
||||
|
||||
// Show the invalid highlight when it has the invalid class and has been touched
|
||||
@if ($text-input-md-show-invalid-highlight) {
|
||||
.item-md.item-input.ng-invalid.ng-touched:not(.input-has-focus) .item-inner {
|
||||
.item-md.item-input.ng-invalid.ng-touched:not(.input-has-focus):not(.item-input-has-focus) .item-inner {
|
||||
@include md-input-highlight($text-input-md-highlight-color-invalid);
|
||||
}
|
||||
|
||||
.list-md .item-input.ng-invalid.ng-touched:not(.input-has-focus):last-child {
|
||||
.list-md .item-input.ng-invalid.ng-touched:not(.input-has-focus):not(.item-input-has-focus):last-child {
|
||||
@include md-input-highlight($text-input-md-highlight-color-invalid);
|
||||
|
||||
.item-inner {
|
||||
|
||||
@@ -93,6 +93,8 @@ input.text-input:-webkit-autofill {
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.input[disabled] .input-cover {
|
||||
@@ -104,49 +106,36 @@ input.text-input:-webkit-autofill {
|
||||
// --------------------------------------------------
|
||||
// When the input has focus, then the input cover should be hidden
|
||||
|
||||
// TODO remove all uses of input-has-focus in v4
|
||||
.item-input-has-focus .input-cover,
|
||||
.input-has-focus .input-cover {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.item-input-has-focus,
|
||||
.input-has-focus {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.item-input-has-focus input,
|
||||
.input-has-focus input,
|
||||
.item-input-has-focus textarea,
|
||||
.input-has-focus textarea,
|
||||
.item-input-has-focus a,
|
||||
.input-has-focus a,
|
||||
.item-input-has-focus button,
|
||||
.input-has-focus button {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
|
||||
// Scroll Assist Input
|
||||
// --------------------------------------------------
|
||||
// This input is used to help the app handle
|
||||
// Next and Previous input tabbing
|
||||
|
||||
[next-input] {
|
||||
@include padding(0);
|
||||
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
|
||||
border: 0;
|
||||
background: transparent;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
// Clear Input Icon
|
||||
// --------------------------------------------------
|
||||
|
||||
.text-input-clear-icon {
|
||||
@include margin(0);
|
||||
@include padding(0);
|
||||
@include background-position(center);
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -155,9 +144,11 @@ input.text-input:-webkit-autofill {
|
||||
height: 100%;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
// TODO remove all uses of input-has-focus in v4
|
||||
// TODO remove all uses of input-has-value in v4
|
||||
.item-input-has-focus.item-input-has-value .text-input-clear-icon,
|
||||
.input-has-focus.input-has-value .text-input-clear-icon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -96,6 +96,9 @@ $text-input-wp-highlight-color-invalid: $text-input-highlight-color-invalid
|
||||
|
||||
// Show the focus highlight when the input has focus
|
||||
@if ($text-input-wp-show-focus-highlight) {
|
||||
// TODO remove all uses of input-has-focus in v4
|
||||
// TODO remove all uses of input-has-value in v4
|
||||
.item-wp.item-input.item-input-has-focus .text-input,
|
||||
.item-wp.item-input.input-has-focus .text-input {
|
||||
border-color: $text-input-wp-highlight-color;
|
||||
}
|
||||
@@ -103,14 +106,15 @@ $text-input-wp-highlight-color-invalid: $text-input-highlight-color-invalid
|
||||
|
||||
// Show the valid highlight when it has the .ng-valid class and a value
|
||||
@if ($text-input-wp-show-valid-highlight) {
|
||||
.item-wp.item-input.ng-valid.input-has-value:not(.input-has-focus) .text-input {
|
||||
.item-wp.item-input.ng-valid.item-input-has-value:not(.input-has-focus):not(.item-input-has-focus) .text-input,
|
||||
.item-wp.item-input.ng-valid.input-has-value:not(.input-has-focus):not(.item-input-has-focus) .text-input {
|
||||
border-color: $text-input-wp-highlight-color-valid;
|
||||
}
|
||||
}
|
||||
|
||||
// Show the invalid highlight when it has the invalid class and has been touched
|
||||
@if ($text-input-wp-show-invalid-highlight) {
|
||||
.item-wp.item-input.ng-invalid.ng-touched:not(.input-has-focus) .text-input {
|
||||
.item-wp.item-input.ng-invalid.ng-touched:not(.input-has-focus):not(.item-input-has-focus) .text-input {
|
||||
border-color: $text-input-wp-highlight-color-invalid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,242 +0,0 @@
|
||||
import { Directive, ElementRef, EventEmitter, HostListener, Output, Renderer } from '@angular/core';
|
||||
import { NgControl } from '@angular/forms';
|
||||
|
||||
import { Config } from '../../config/config';
|
||||
import { Platform } from '../../platform/platform';
|
||||
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
@Directive({
|
||||
selector: '.text-input'
|
||||
})
|
||||
export class NativeInput {
|
||||
_relocated: boolean;
|
||||
_clone: boolean;
|
||||
_blurring: boolean;
|
||||
_unrefBlur: Function;
|
||||
|
||||
@Output() focusChange: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
@Output() valueChange: EventEmitter<string> = new EventEmitter<string>();
|
||||
@Output() keydown: EventEmitter<string> = new EventEmitter<string>();
|
||||
|
||||
constructor(
|
||||
public _elementRef: ElementRef,
|
||||
public _renderer: Renderer,
|
||||
config: Config,
|
||||
private _plt: Platform,
|
||||
public ngControl: NgControl
|
||||
) {
|
||||
this._clone = config.getBoolean('inputCloning', false);
|
||||
this._blurring = config.getBoolean('inputBlurring', false);
|
||||
}
|
||||
|
||||
@HostListener('input', ['$event'])
|
||||
_change(ev: any) {
|
||||
this.valueChange.emit(ev.target.value);
|
||||
}
|
||||
|
||||
@HostListener('keydown', ['$event'])
|
||||
_keyDown(ev: any) {
|
||||
if (ev) {
|
||||
ev.target && this.keydown.emit(ev.target.value);
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('focus')
|
||||
_focus() {
|
||||
var self = this;
|
||||
|
||||
self.focusChange.emit(true);
|
||||
|
||||
if (self._blurring) {
|
||||
// automatically blur input if:
|
||||
// 1) this input has focus
|
||||
// 2) the newly tapped document element is not an input
|
||||
console.debug(`native-input, blurring enabled`);
|
||||
|
||||
var unregTouchEnd = this._plt.registerListener(this._plt.doc(), 'touchend', (ev: TouchEvent) => {
|
||||
var tapped = <HTMLElement>ev.target;
|
||||
if (tapped && self.element()) {
|
||||
if (tapped.tagName !== 'INPUT' && tapped.tagName !== 'TEXTAREA' && !tapped.classList.contains('input-cover')) {
|
||||
self.element().blur();
|
||||
}
|
||||
}
|
||||
}, {
|
||||
capture: true,
|
||||
zone: false
|
||||
});
|
||||
|
||||
self._unrefBlur = function() {
|
||||
console.debug(`native-input, blurring disabled`);
|
||||
unregTouchEnd();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('blur')
|
||||
_blur() {
|
||||
this.focusChange.emit(false);
|
||||
this.hideFocus(false);
|
||||
|
||||
this._unrefBlur && this._unrefBlur();
|
||||
this._unrefBlur = null;
|
||||
}
|
||||
|
||||
labelledBy(val: string) {
|
||||
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'aria-labelledby', val);
|
||||
}
|
||||
|
||||
isDisabled(val: boolean) {
|
||||
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'disabled', val ? '' : null);
|
||||
}
|
||||
|
||||
setFocus() {
|
||||
// let's set focus to the element
|
||||
// but only if it does not already have focus
|
||||
if (this._plt.getActiveElement() !== this.element()) {
|
||||
this.element().focus();
|
||||
}
|
||||
}
|
||||
|
||||
beginFocus(shouldFocus: boolean, inputRelativeY: number) {
|
||||
if (this._relocated !== shouldFocus) {
|
||||
const focusedInputEle = this.element();
|
||||
if (shouldFocus) {
|
||||
// we should focus into this element
|
||||
|
||||
if (this._clone) {
|
||||
// this platform needs the input to be cloned
|
||||
// this allows for the actual input to receive the focus from
|
||||
// the user's touch event, but before it receives focus, it
|
||||
// moves the actual input to a location that will not screw
|
||||
// up the app's layout, and does not allow the native browser
|
||||
// to attempt to scroll the input into place (messing up headers/footers)
|
||||
// the cloned input fills the area of where native input should be
|
||||
// while the native input fakes out the browser by relocating itself
|
||||
// before it receives the actual focus event
|
||||
cloneInputComponent(this._plt, focusedInputEle);
|
||||
|
||||
// move the native input to a location safe to receive focus
|
||||
// according to the browser, the native input receives focus in an
|
||||
// area which doesn't require the browser to scroll the input into place
|
||||
(<any>focusedInputEle.style)[this._plt.Css.transform] = `translate3d(-9999px,${inputRelativeY}px,0)`;
|
||||
focusedInputEle.style.opacity = '0';
|
||||
}
|
||||
|
||||
// let's now set focus to the actual native element
|
||||
// at this point it is safe to assume the browser will not attempt
|
||||
// to scroll the input into view itself (screwing up headers/footers)
|
||||
this.setFocus();
|
||||
|
||||
} else {
|
||||
// should remove the focus
|
||||
if (this._clone) {
|
||||
// should remove the cloned node
|
||||
removeClone(this._plt, focusedInputEle);
|
||||
}
|
||||
}
|
||||
|
||||
this._relocated = shouldFocus;
|
||||
}
|
||||
}
|
||||
|
||||
hideFocus(shouldHideFocus: boolean) {
|
||||
let focusedInputEle = this.element();
|
||||
|
||||
console.debug(`native-input, hideFocus, shouldHideFocus: ${shouldHideFocus}, input value: ${focusedInputEle.value}`);
|
||||
|
||||
if (shouldHideFocus) {
|
||||
cloneInputComponent(this._plt, focusedInputEle);
|
||||
(<any>focusedInputEle.style)[this._plt.Css.transform] = 'scale(0)';
|
||||
|
||||
} else {
|
||||
removeClone(this._plt, focusedInputEle);
|
||||
}
|
||||
}
|
||||
|
||||
setValue(val: any) {
|
||||
this._elementRef.nativeElement['value'] = val;
|
||||
}
|
||||
|
||||
getValue(): string {
|
||||
return this.element().value;
|
||||
}
|
||||
|
||||
setMin(val: any) {
|
||||
this._elementRef.nativeElement['min'] = val;
|
||||
}
|
||||
|
||||
setMax(val: any) {
|
||||
this._elementRef.nativeElement['max'] = val;
|
||||
}
|
||||
|
||||
setStep(val: any) {
|
||||
this._elementRef.nativeElement['step'] = val;
|
||||
}
|
||||
|
||||
setElementClass(cssClass: string, shouldAdd: boolean) {
|
||||
this._renderer.setElementClass(this._elementRef.nativeElement, cssClass, shouldAdd);
|
||||
}
|
||||
|
||||
element(): HTMLInputElement {
|
||||
return this._elementRef.nativeElement;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._unrefBlur && this._unrefBlur();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function cloneInputComponent(plt: Platform, srcNativeInputEle: HTMLInputElement) {
|
||||
// given a native <input> or <textarea> element
|
||||
// find its parent wrapping component like <ion-input> or <ion-textarea>
|
||||
// then clone the entire component
|
||||
const srcComponentEle = <HTMLElement>srcNativeInputEle.closest('ion-input,ion-textarea');
|
||||
if (srcComponentEle) {
|
||||
// DOM READ
|
||||
const srcTop = srcComponentEle.offsetTop;
|
||||
const srcLeft = srcComponentEle.offsetLeft;
|
||||
const srcWidth = srcComponentEle.offsetWidth;
|
||||
const srcHeight = srcComponentEle.offsetHeight;
|
||||
|
||||
// DOM WRITE
|
||||
// not using deep clone so we don't pull in unnecessary nodes
|
||||
const clonedComponentEle = <HTMLElement>srcComponentEle.cloneNode(false);
|
||||
clonedComponentEle.classList.add('cloned-input');
|
||||
clonedComponentEle.setAttribute('aria-hidden', 'true');
|
||||
clonedComponentEle.style.pointerEvents = 'none';
|
||||
clonedComponentEle.style.position = 'absolute';
|
||||
clonedComponentEle.style.top = srcTop + 'px';
|
||||
clonedComponentEle.style.left = srcLeft + 'px';
|
||||
clonedComponentEle.style.width = srcWidth + 'px';
|
||||
clonedComponentEle.style.height = srcHeight + 'px';
|
||||
|
||||
const clonedNativeInputEle = <HTMLInputElement>srcNativeInputEle.cloneNode(false);
|
||||
clonedNativeInputEle.value = srcNativeInputEle.value;
|
||||
clonedNativeInputEle.tabIndex = -1;
|
||||
|
||||
clonedComponentEle.appendChild(clonedNativeInputEle);
|
||||
srcComponentEle.parentNode.appendChild(clonedComponentEle);
|
||||
|
||||
srcComponentEle.style.pointerEvents = 'none';
|
||||
}
|
||||
|
||||
(<any>srcNativeInputEle.style)[plt.Css.transform] = 'scale(0)';
|
||||
}
|
||||
|
||||
function removeClone(plt: Platform, srcNativeInputEle: HTMLElement) {
|
||||
const srcComponentEle = <HTMLElement>srcNativeInputEle.closest('ion-input,ion-textarea');
|
||||
if (srcComponentEle && srcComponentEle.parentElement) {
|
||||
const clonedInputEles = srcComponentEle.parentElement.querySelectorAll('.cloned-input');
|
||||
for (var i = 0; i < clonedInputEles.length; i++) {
|
||||
clonedInputEles[i].parentNode.removeChild(clonedInputEles[i]);
|
||||
}
|
||||
|
||||
srcComponentEle.style.pointerEvents = '';
|
||||
}
|
||||
(<any>srcNativeInputEle.style)[plt.Css.transform] = '';
|
||||
srcNativeInputEle.style.opacity = '';
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Directive, EventEmitter, HostListener, Output } from '@angular/core';
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[next-input]'
|
||||
})
|
||||
export class NextInput {
|
||||
@Output() focused: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
|
||||
@HostListener('focus')
|
||||
receivedFocus() {
|
||||
console.debug('native-input, next-input received focus');
|
||||
this.focused.emit(true);
|
||||
}
|
||||
|
||||
}
|
||||
10
src/components/input/test/attributes/app/app.component.ts
Normal file
10
src/components/input/test/attributes/app/app.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { RootPage } from '../pages/root-page/root-page';
|
||||
|
||||
@Component({
|
||||
template: '<ion-nav [root]="root"></ion-nav>'
|
||||
})
|
||||
export class AppComponent {
|
||||
root = RootPage;
|
||||
}
|
||||
19
src/components/input/test/attributes/app/app.module.ts
Normal file
19
src/components/input/test/attributes/app/app.module.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule } from '../../../../..';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { RootPageModule } from '../pages/root-page/root-page.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
IonicModule.forRoot(AppComponent),
|
||||
RootPageModule
|
||||
],
|
||||
bootstrap: [IonicApp]
|
||||
})
|
||||
export class AppModule {}
|
||||
0
src/components/input/test/attributes/e2e.ts
Normal file
0
src/components/input/test/attributes/e2e.ts
Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user