mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
112 Commits
ld/datetim
...
v3.6.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
318737535f | ||
|
|
04fe92cd58 | ||
|
|
b809665944 | ||
|
|
4d786b30ba | ||
|
|
4f49f27824 | ||
|
|
7e8bd5a8fe | ||
|
|
f4539aacc9 | ||
|
|
4911d9f01a | ||
|
|
6e64b8d915 | ||
|
|
e3216da03e | ||
|
|
bd0c265978 | ||
|
|
846eb09991 | ||
|
|
ac4a043314 | ||
|
|
106950533c | ||
|
|
295fe783b0 | ||
|
|
0a6bb3bb21 | ||
|
|
1b9c3daef1 | ||
|
|
26b09f1d49 | ||
|
|
1e9539b9df | ||
|
|
17b3a39f0d | ||
|
|
475b722c7d | ||
|
|
50beafae6a | ||
|
|
f605f0a74c | ||
|
|
e401997a42 | ||
|
|
16f2ebe241 | ||
|
|
584afd040f | ||
|
|
de0f9d5f28 | ||
|
|
4596dbe5c0 | ||
|
|
400aa549d4 | ||
|
|
add0c4ecfe | ||
|
|
519d657e6e | ||
|
|
a8ceee467b | ||
|
|
97f9522110 | ||
|
|
961bfc3ebb | ||
|
|
5b9fe5e81a | ||
|
|
c4e7552b56 | ||
|
|
cec718c6c7 | ||
|
|
ab511c4744 | ||
|
|
2d49e10da4 | ||
|
|
ce46c24413 | ||
|
|
f7fce5fa16 | ||
|
|
d23b9f7d49 | ||
|
|
4c13535416 | ||
|
|
889b49f372 | ||
|
|
acb6facc7b | ||
|
|
2153940de8 | ||
|
|
6d8da0ae32 | ||
|
|
347c260950 | ||
|
|
9ffc52b582 | ||
|
|
08be9dc58b | ||
|
|
ad25cd1cd7 | ||
|
|
693c1c56d1 | ||
|
|
b5aa304e7e | ||
|
|
3e3a00b2fb | ||
|
|
923e3b2e26 | ||
|
|
e079f7777f | ||
|
|
5a4b351794 | ||
|
|
d22d77b485 | ||
|
|
efd54750bf | ||
|
|
eb830d4202 | ||
|
|
3f39e14f76 | ||
|
|
fce4422ab1 | ||
|
|
04e78d8c22 | ||
|
|
48b3243689 | ||
|
|
486bff036d | ||
|
|
a7e5fa7ea7 | ||
|
|
5771543c3b | ||
|
|
048af1b329 | ||
|
|
a92d805e89 | ||
|
|
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 |
5
.github/ISSUE_TEMPLATE.md
vendored
5
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,3 +1,6 @@
|
||||
**Resources:**
|
||||
Before submitting an issue, please consult our troubleshooting guide (http://ionicframework.com/docs/troubleshooting/) and developer resources (http://ionicframework.com/docs/developer-resources/)
|
||||
|
||||
**Ionic version:** (check one with "x")
|
||||
[ ] **1.x** (For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1)
|
||||
[ ] **2.x**
|
||||
@@ -19,7 +22,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:**
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,6 +9,7 @@ log.txt
|
||||
*.sublime-workspace
|
||||
|
||||
.idea/
|
||||
.sourcemaps/
|
||||
.vscode/
|
||||
.sass-cache/
|
||||
.versions/
|
||||
|
||||
272
CHANGELOG.md
272
CHANGELOG.md
@@ -1,3 +1,275 @@
|
||||
<a name="3.6.0"></a>
|
||||
# [3.6.0](https://github.com/ionic-team/ionic/compare/v3.5.3...v3.6.0) (2017-07-27)
|
||||
|
||||
|
||||
### Upgrade Instructions
|
||||
|
||||
`ionic-angular` 3.6.0 requires developer's to update to the latest version of the `Ionic CLI` and `@ionic/app-scripts`.
|
||||
|
||||
To upgrade, please run
|
||||
|
||||
```
|
||||
npm install -g ionic@latest
|
||||
npm install @ionic/app-scripts@latest --save-dev
|
||||
npm install ionic-angular@latest --save
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
The URL when using deep linking is shortened and improved in this release. Due to a limitation in our nav system, if you're using `ion-tabs` and have a tab name that matches a segment, meaning you have a tab name of `schedule` and a segment of `schedule`, there could potentially be issues. To mitigate these issues, make sure you set the `tabUrlPath` property on the `ion-tab` and give it a unique name. This limitation will require an API change to fix so it will be resolved in `ionic-angular` 4.x.
|
||||
|
||||
|
||||
The upgrades include necessary changes to generators that add back lazy loading functionality, as well as an improved way of generating component/directives/and pipes.
|
||||
|
||||
### New Generators
|
||||
|
||||
The release adds back the functionality to generate lazy loaded pages.
|
||||
To generate a lazy loaded page, run:
|
||||
|
||||
```bash
|
||||
ionic g page <Page-Name>
|
||||
```
|
||||
|
||||
This will include a `.module.ts` file in the page directory created. If you do not want to generate a lazy loaded page, you can run:
|
||||
|
||||
```bash
|
||||
ionic g page <Page-Name> --no-module
|
||||
```
|
||||
|
||||
This will also generate lazy loaded tabs as well, accepting the `--no-module` flag as well to disable it.
|
||||
|
||||
|
||||
For pipes/components/components, we now generate a shared common module for each of these.
|
||||
|
||||
So running:
|
||||
|
||||
```bash
|
||||
ionic g component music-card
|
||||
```
|
||||
|
||||
Will create a `components/components.module.ts` file that declares and exports the `music-card` component.
|
||||
We think that this will allow developers to get up and running with custom components much faster and will less overhead.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **list:** remove margin of MD buttons in ion-item-options ([#12263](https://github.com/ionic-team/ionic/issues/12263)) ([97f9522](https://github.com/ionic-team/ionic/commit/97f9522))
|
||||
* **nav:** make call to setPages return the promise so if it rejects it doesn't get lost ([de0f9d5](https://github.com/ionic-team/ionic/commit/de0f9d5))
|
||||
* **navigation:** account for race conditions in developer's code ([4596dbe](https://github.com/ionic-team/ionic/commit/4596dbe))
|
||||
* **navigation:** fix bug where that occurred when tab identifier and segment had the exact same string ([add0c4e](https://github.com/ionic-team/ionic/commit/add0c4e))
|
||||
* **navigation:** fix null pointer exceptions that would occur when destroying a nav controller while its transitioning ([584afd0](https://github.com/ionic-team/ionic/commit/584afd0))
|
||||
* **navigation:** reduce urls to minimum set of fields ([a8ceee4](https://github.com/ionic-team/ionic/commit/a8ceee4))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **generators:** refactor generators ([400aa54](https://github.com/ionic-team/ionic/commit/400aa54))
|
||||
|
||||
|
||||
|
||||
<a name="3.5.3"></a>
|
||||
## [3.5.3](https://github.com/ionic-team/ionic/compare/v3.5.2...v3.5.3) (2017-07-14)
|
||||
|
||||
## Upgrade Instructions
|
||||
`ionic-angular@3.5.3` is a drop-in replacement for `3.5.2`. To install it, simply run `npm install ionic-angular@3.5.3 --save --save-exact`.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **app:** restore getActiveNav api ([2d49e10](https://github.com/ionic-team/ionic/commit/2d49e10))
|
||||
|
||||
|
||||
|
||||
<a name="3.5.2"></a>
|
||||
## [3.5.2](https://github.com/ionic-team/ionic/compare/v3.5.1...v3.5.2) (2017-07-13)
|
||||
|
||||
## Upgrade Instructions
|
||||
`ionic-angular@3.5.2` is a drop-in replacement for `3.5.1`. To install it, simply run `npm install ionic-angular@3.5.2 --save --save-exact`.
|
||||
|
||||
We have released a new version of our build process for `ionic-angular` apps, `@ionic/app-scripts` in conjunction with this release of `ionic-angular`. While it's not a required update, we recommend it because we have greatly improved the developer experience. Incremental, or update builds while developing are much faster now. We've also added `scope hoisting` for better start-up performance on production builds.
|
||||
|
||||
To upgrade to `@ionic/app-scripts`, run the following command:
|
||||
|
||||
```
|
||||
rm -rf node_modules
|
||||
npm install @ionic/app-scripts@2.0.2 --save-dev --save-exact
|
||||
```
|
||||
|
||||
After installing the update, you'll need to make a minor change to the `src/index.html` file to include a new `<script>` tag for `build/vendor.js`. The reason for this breaking change in `@ionic/app-scripts` is for faster builds. By separating out the `node_modules` dependencies into a `vendor.js` file, the incremental build is faster.
|
||||
|
||||
```
|
||||
...
|
||||
<body>
|
||||
|
||||
<!-- Ionic's root component and where the app will load -->
|
||||
<ion-app></ion-app>
|
||||
|
||||
<!-- cordova.js required for cordova apps -->
|
||||
<script src="cordova.js"></script>
|
||||
|
||||
<!-- The polyfills js is generated during the build process -->
|
||||
<script src="build/polyfills.js"></script>
|
||||
|
||||
<!-- The vendor js is generated during the build process
|
||||
and includes all files in the node_modules directory -->
|
||||
<script src="build/vendor.js"></script>
|
||||
|
||||
<!-- The bundle js is generated during the build process -->
|
||||
<script src="build/main.js"></script>
|
||||
|
||||
</body>
|
||||
...
|
||||
```
|
||||
|
||||
If you're customizing `@ionic/app-scripts`, we recommend you review the [changelog](https://github.com/ionic-team/ionic-app-scripts/blob/master/CHANGELOG.md), and update any of your configs accordingly.
|
||||
|
||||
## Notes
|
||||
`3.5.2` is the same as `3.5.1`. We had a small publishing error.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **navigation:** fix swipe-to-go-back ([04e78d8](https://github.com/ionic-team/ionic/commit/04e78d8))
|
||||
* **navigation:** mark as not transitioning on success in addition to '_transitionFinish', provide no ([48b3243](https://github.com/ionic-team/ionic/commit/48b3243))
|
||||
* **navigation:** navs can have n child navs instead of just one ([fce4422](https://github.com/ionic-team/ionic/commit/fce4422))
|
||||
* **navigation:** restore getActiveChildNav method to maintain old API, add deprecation notice ([d22d77b](https://github.com/ionic-team/ionic/commit/d22d77b))
|
||||
* **navigation:** ts2.4 compatibility ([08be9dc](https://github.com/ionic-team/ionic/commit/08be9dc)), closes [#12233](https://github.com/ionic-team/ionic/issues/12233) [#12235](https://github.com/ionic-team/ionic/issues/12235)
|
||||
* **select:** not activated on enter in input field ([ad25cd1](https://github.com/ionic-team/ionic/commit/ad25cd1)), closes [#12202](https://github.com/ionic-team/ionic/issues/12202)
|
||||
* **sliding-item:** ionSwipe event is fired ([#12157](https://github.com/ionic-team/ionic/issues/12157)) ([b5aa304](https://github.com/ionic-team/ionic/commit/b5aa304)), closes [#12146](https://github.com/ionic-team/ionic/issues/12146)
|
||||
* **tabs:** have tabs behavior match nav when navigating back/forth via the url ([3f39e14](https://github.com/ionic-team/ionic/commit/3f39e14))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **navigation:** support for named ion-nav/ion-tabs to improve url in the short term ([486bff0](https://github.com/ionic-team/ionic/commit/486bff0))
|
||||
|
||||
|
||||
<a name="3.5.1"></a>
|
||||
## [3.5.1](https://github.com/ionic-team/ionic/compare/v3.5.0...v3.5.1) (2017-07-13)
|
||||
|
||||
See the [3.5.2](https://github.com/ionic-team/ionic/blob/master/CHANGELOG.md#352-2017-07-13) changelog. We had a publishing error here.
|
||||
|
||||
<a name="3.5.0"></a>
|
||||
# [3.5.0](https://github.com/ionic-team/ionic/compare/v3.4.2...v3.5.0) (2017-06-28)
|
||||
|
||||
### Steps to Upgrade
|
||||
|
||||
`ionic-angular` should be set to version `3.5.0`.
|
||||
|
||||
```
|
||||
npm install ionic-angular@3.5.0 --save --save-exact
|
||||
```
|
||||
|
||||
### Notes
|
||||
There were major improvements made to navigation in this release of `ionic-angular`. Specifically, we updated Ionic to support a concept of `n` root navigation elements, instead of just one. This will enable first-class url support for things `split-pane`. Before `3.5.0`, only one section of the screen could be represented in the URL. With these changes, multiple sections can be. Another large change was improving the behavior surrounding browser behaviors, such as the back-and-forward buttons, as well as refresh. In general, Ionic should work much more intuitively in a web browser now.
|
||||
|
||||
As a result of these improvements, if you're using deep linking, the urls of the application will be different with `3.5.0` than they were with previous Ionic releases. The URLs will likely change again in the near future with the next round of navigation improvements too. For now, we don't recommend using `href` attributes in the application. Using the `navPush` and `navPop` directives is a better option for now while URL support is being built-out.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **navigation:** add isTab check to getSegmentsFromNav ([f39c381](https://github.com/ionic-team/ionic/commit/f39c381))
|
||||
* **navigation:** fallback to name if component does not exist on segment ([30f69c8](https://github.com/ionic-team/ionic/commit/30f69c8))
|
||||
* **select:** _inputUpdated should not be called manually ([8dc08f9](https://github.com/ionic-team/ionic/commit/8dc08f9))
|
||||
* **select:** floating label ([e3a8d27](https://github.com/ionic-team/ionic/commit/e3a8d27)), closes [#12068](https://github.com/ionic-team/ionic/issues/12068)
|
||||
* **tabs:** use segment if it exists even if component exists ([016b90d](https://github.com/ionic-team/ionic/commit/016b90d))
|
||||
|
||||
|
||||
|
||||
<a name="3.4.2"></a>
|
||||
## [3.4.2](https://github.com/ionic-team/ionic/compare/v3.4.1...v3.4.2) (2017-06-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **rtl:** use multi direction in order to override the default ltr ([70b5b6](https://github.com/ionic-team/ionic/commit/70b5b6))
|
||||
|
||||
|
||||
|
||||
<a name="3.4.1"></a>
|
||||
## [3.4.1](https://github.com/ionic-team/ionic/compare/v3.4.0...v3.4.1) (2017-06-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **themes:** change default app-direction ([1ca7df](https://github.com/ionic-team/ionic/commit/1ca7df))
|
||||
|
||||
|
||||
|
||||
<a name="3.4.0"></a>
|
||||
# [3.4.0](https://github.com/ionic-team/ionic/compare/v3.3.0...v3.4.0) (2017-06-15)
|
||||
|
||||
### Steps to Upgrade
|
||||
|
||||
`ionic-angular` should be set to version `3.4.0` in the package.json dependency list. The latest `@angular` release `4.1.3` is also supported. Feel free to update apps by updating the `package.json` dependencies to match below.
|
||||
|
||||
```
|
||||
"dependencies": {
|
||||
"@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",
|
||||
"@ionic-native/core": "3.12.1",
|
||||
"@ionic-native/splash-screen": "3.12.1",
|
||||
"@ionic-native/status-bar": "3.12.1",
|
||||
"@ionic/storage": "2.0.1",
|
||||
"ionic-angular": "3.4.2",
|
||||
"ionicons": "3.0.0",
|
||||
"rxjs": "5.4.0",
|
||||
"sw-toolbox": "3.6.0",
|
||||
"zone.js": "0.8.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ionic/app-scripts": "1.3.7",
|
||||
"typescript": "2.3.4"
|
||||
}
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** rtl fix for md ripple effect ([#11842](https://github.com/ionic-team/ionic/issues/11842)) ([bb966e5](https://github.com/ionic-team/ionic/commit/bb966e5))
|
||||
* **content:** scroll content should inherit background ([#11467](https://github.com/ionic-team/ionic/issues/11467)) ([6256b0f](https://github.com/ionic-team/ionic/commit/6256b0f))
|
||||
* **datetime:** set datetime direction the same on ltr and rtl ([#11992](https://github.com/ionic-team/ionic/issues/11992)) ([20c9dd7](https://github.com/ionic-team/ionic/commit/20c9dd7))
|
||||
* **gesture:** RTL fix for slide-gesture ([#11822](https://github.com/ionic-team/ionic/issues/11822)) ([59a1e3d](https://github.com/ionic-team/ionic/commit/59a1e3d))
|
||||
* **input:** add correct translate3d for rtl ([ef85ba6](https://github.com/ionic-team/ionic/commit/ef85ba6)), closes [#11745](https://github.com/ionic-team/ionic/issues/11745) [#11211](https://github.com/ionic-team/ionic/issues/11211)
|
||||
* **input:** better handling of attributes ([9f86e10](https://github.com/ionic-team/ionic/commit/9f86e10))
|
||||
* **input:** slightly longer delay for autofocus ([#12037](https://github.com/ionic-team/ionic/issues/12037)) ([54ac2e3](https://github.com/ionic-team/ionic/commit/54ac2e3))
|
||||
* **input:** use all supported attributes on both textareas and inputs ([#12028](https://github.com/ionic-team/ionic/issues/12028)) ([8041eed](https://github.com/ionic-team/ionic/commit/8041eed))
|
||||
* **item-sliding:** RTL fix for item sliding ([#11825](https://github.com/ionic-team/ionic/issues/11825)) ([10f4df4](https://github.com/ionic-team/ionic/commit/10f4df4))
|
||||
* **keyboard:** big keyboard/input refactor ([c10f72b](https://github.com/ionic-team/ionic/commit/c10f72b)), closes [#9699](https://github.com/ionic-team/ionic/issues/9699) [#11484](https://github.com/ionic-team/ionic/issues/11484) [#11389](https://github.com/ionic-team/ionic/issues/11389) [#11325](https://github.com/ionic-team/ionic/issues/11325) [#11291](https://github.com/ionic-team/ionic/issues/11291) [#10828](https://github.com/ionic-team/ionic/issues/10828) [#11291](https://github.com/ionic-team/ionic/issues/11291) [#10393](https://github.com/ionic-team/ionic/issues/10393) [#10257](https://github.com/ionic-team/ionic/issues/10257) [#9434](https://github.com/ionic-team/ionic/issues/9434) [#8933](https://github.com/ionic-team/ionic/issues/8933) [#7178](https://github.com/ionic-team/ionic/issues/7178) [#7047](https://github.com/ionic-team/ionic/issues/7047) [#10552](https://github.com/ionic-team/ionic/issues/10552) [#10393](https://github.com/ionic-team/ionic/issues/10393) [#10183](https://github.com/ionic-team/ionic/issues/10183) [#10187](https://github.com/ionic-team/ionic/issues/10187) [#10852](https://github.com/ionic-team/ionic/issues/10852) [#11578](https://github.com/ionic-team/ionic/issues/11578)
|
||||
* **menu:** rtl gesture for menu ([#11830](https://github.com/ionic-team/ionic/issues/11830)) ([30047f0](https://github.com/ionic-team/ionic/commit/30047f0))
|
||||
* **refresher:** border should only show when pulled ([#12015](https://github.com/ionic-team/ionic/issues/12015)) ([47e3c70](https://github.com/ionic-team/ionic/commit/47e3c70)), closes [#10994](https://github.com/ionic-team/ionic/issues/10994)
|
||||
* **rtl:** add icon-start and icon-end attributes ([#11737](https://github.com/ionic-team/ionic/issues/11737)) ([a40b872](https://github.com/ionic-team/ionic/commit/a40b872))
|
||||
* **sass:** add default flag to variables ([#11779](https://github.com/ionic-team/ionic/issues/11779)) ([f14d7d6](https://github.com/ionic-team/ionic/commit/f14d7d6))
|
||||
* **searchbar:** caret moving to the end when typing ([261bc4d](https://github.com/ionic-team/ionic/commit/261bc4d))
|
||||
* **segment:** fix border-radius logic for RTL ([#11981](https://github.com/ionic-team/ionic/issues/11981)) ([6db8c14](https://github.com/ionic-team/ionic/commit/6db8c14))
|
||||
* **select:** add cssClass for popover interface ([#11769](https://github.com/ionic-team/ionic/issues/11769)) ([1c25acb](https://github.com/ionic-team/ionic/commit/1c25acb))
|
||||
* **select:** return undefined when there are no options ([#11968](https://github.com/ionic-team/ionic/issues/11968)) ([dc6c586](https://github.com/ionic-team/ionic/commit/dc6c586)), closes [#10435](https://github.com/ionic-team/ionic/issues/10435)
|
||||
* **split-pane:** correct split-pane menu side order ([30dc247](https://github.com/ionic-team/ionic/commit/30dc247))
|
||||
* **textarea:** apply classes properly ([dc958c3](https://github.com/ionic-team/ionic/commit/dc958c3))
|
||||
* **toggle:** RTL fix for toggle ([2afb936](https://github.com/ionic-team/ionic/commit/2afb936))
|
||||
* **toolbar:** get the correct contrast color for md mode ([0f4ed1c](https://github.com/ionic-team/ionic/commit/0f4ed1c)), closes [#11848](https://github.com/ionic-team/ionic/issues/11848)
|
||||
* **toolbar:** use the correct contrast color for MD toolbar ([041689b](https://github.com/ionic-team/ionic/commit/041689b)), closes [#11848](https://github.com/ionic-team/ionic/issues/11848)
|
||||
* **transition:** RTL fix for transition on ios ([#11820](https://github.com/ionic-team/ionic/issues/11820)) ([6322134](https://github.com/ionic-team/ionic/commit/6322134))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **background-position:** add background position support for rtl ([#11946](https://github.com/ionic-team/ionic/issues/11946)) ([305c306](https://github.com/ionic-team/ionic/commit/305c306))
|
||||
* **loading:** add enableBackdropDismiss to Loading ([#11937](https://github.com/ionic-team/ionic/issues/11937)) ([d0ae810](https://github.com/ionic-team/ionic/commit/d0ae810)), closes [#7975](https://github.com/ionic-team/ionic/issues/7975)
|
||||
* **loading:** add margin start variable ([#11980](https://github.com/ionic-team/ionic/issues/11980)) ([3e0d43e](https://github.com/ionic-team/ionic/commit/3e0d43e))
|
||||
* **rtl:** add transform and transform-origin support for rtl ([#11649](https://github.com/ionic-team/ionic/issues/11649)) ([2273fb5](https://github.com/ionic-team/ionic/commit/2273fb5))
|
||||
* **rtl:** optimize the new mixins for smaller bundle, ltr separation ([#11635](https://github.com/ionic-team/ionic/issues/11635)) ([f0c6948](https://github.com/ionic-team/ionic/commit/f0c6948))
|
||||
* **rtl:** support flipped svg background images on rtl ([#11945](https://github.com/ionic-team/ionic/issues/11945)) ([f4452b5](https://github.com/ionic-team/ionic/commit/f4452b5))
|
||||
* **slides:** support centering slides and using decimal numbers ([e3c60c5](https://github.com/ionic-team/ionic/commit/e3c60c5)), closes [#10361](https://github.com/ionic-team/ionic/issues/10361)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **item-sliding:** remove duplicate class ([#11829](https://github.com/ionic-team/ionic/issues/11829)) ([c9cb9ae](https://github.com/ionic-team/ionic/commit/c9cb9ae))
|
||||
|
||||
|
||||
|
||||
<a name="3.3.0"></a>
|
||||
# [3.3.0](https://github.com/ionic-team/ionic/compare/v3.2.1...v3.3.0) (2017-05-24)
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ jobs:
|
||||
working_directory: ~/ionic/
|
||||
docker:
|
||||
- image: node:7
|
||||
branches:
|
||||
ignore:
|
||||
- mono-refactor
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
|
||||
@@ -58,13 +58,13 @@ export class PageOne {
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
handler: (data) => {
|
||||
handler: () => {
|
||||
console.log('Cancel clicked');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Save',
|
||||
handler: (data) => {
|
||||
handler: () => {
|
||||
console.log('Saved clicked');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export class AppComponent {
|
||||
this.listenToLoginEvents();
|
||||
}
|
||||
|
||||
openPage(menu: any, page: any) {
|
||||
openPage(_: any, page: any) {
|
||||
// find the nav component and set what the root page should be
|
||||
// reset the nav to remove previous pages and only have this page
|
||||
// we wouldn't want the back button to show in this scenario
|
||||
|
||||
@@ -71,7 +71,7 @@ export class PageOne {
|
||||
this.expandAction(item, 'downloading', 'Login was downloaded.');
|
||||
}
|
||||
|
||||
expandAction(item: ItemSliding, action: string, text: string) {
|
||||
expandAction(item: ItemSliding, _: any, text: string) {
|
||||
// TODO item.setElementClass(action, true);
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
14861
package-lock.json
generated
Normal file
14861
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "ionic2",
|
||||
"version": "3.3.0",
|
||||
"version": "3.6.0",
|
||||
"description": "A powerful framework for building mobile and progressive web apps with JavaScript and Angular",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -22,7 +22,8 @@
|
||||
"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.3",
|
||||
@@ -38,7 +39,7 @@
|
||||
"zone.js": "0.8.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ionic/app-scripts": "1.3.7",
|
||||
"@ionic/app-scripts": "^1.3.11",
|
||||
"@ionic/commit-hooks": "1.0.3",
|
||||
"@types/connect": "3.4.30",
|
||||
"@types/del": "2.2.31",
|
||||
@@ -65,6 +66,7 @@
|
||||
"conventional-changelog": "1.1.0",
|
||||
"core-js": "2.4.1",
|
||||
"cpr": "2.0.0",
|
||||
"cross-spawn": "^5.1.0",
|
||||
"del": "2.2.2",
|
||||
"dgeni": "^0.4.7",
|
||||
"dgeni-packages": "^0.16.10",
|
||||
@@ -91,7 +93,7 @@
|
||||
"gulp-scss-lint": "0.4.0",
|
||||
"gulp-shell": "0.5.2",
|
||||
"gulp-strip-debug": "1.1.0",
|
||||
"gulp-tslint": "6.1.1",
|
||||
"gulp-tslint": "^8.1.1",
|
||||
"gulp-typescript": "2.13.6",
|
||||
"gulp-uglify": "2.0.0",
|
||||
"gulp-util": "3.0.7",
|
||||
@@ -130,8 +132,8 @@
|
||||
"systemjs": "0.19.38",
|
||||
"through2": "2.0.1",
|
||||
"ts-node": "1.3.0",
|
||||
"tslint": "3.15.1",
|
||||
"tslint-ionic-rules": "0.0.8",
|
||||
"tslint": "^5.4.3",
|
||||
"tslint-ionic-rules": "0.0.11",
|
||||
"typescript": "~2.3.3",
|
||||
"vinyl": "1.2.0",
|
||||
"webpack": "^2.1.0-beta.27",
|
||||
|
||||
@@ -29,6 +29,14 @@ module.exports = function jekyll(renderDocsProcessor) {
|
||||
if (docs[i].href) {
|
||||
docs[i].href = doc.href.replace('content/', '');
|
||||
}
|
||||
if (docs[i].description) {
|
||||
docs[i].description = docs[i].description.replace(/(\#\#\#).+/g, (section) => {
|
||||
const title = section.replace(/^(\#+\s?)/, '');
|
||||
const segment = title.replace(/[^a-zA-Z0-9]+/g, '-').toLowerCase();
|
||||
|
||||
return `\n<h3><a class="anchor" name="${segment}" href="#${segment}">${title}</a></h3>\n`;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
docs.push({
|
||||
|
||||
@@ -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.
|
||||
|
||||
23
scripts/docs/templates/common.template.html
vendored
23
scripts/docs/templates/common.template.html
vendored
@@ -242,7 +242,7 @@ Improve this doc
|
||||
|
||||
<!-- @usage tag -->
|
||||
<@ if doc.usage @>
|
||||
<h2><a class="anchor" name="usage" href="#usage"></a>Usage</h2>
|
||||
<h2><a class="anchor" name="usage" href="#usage">Usage</a></h2>
|
||||
<@ block usage @>
|
||||
<$ doc.usage | marked $>
|
||||
<@ endblock @>
|
||||
@@ -250,7 +250,7 @@ Improve this doc
|
||||
|
||||
<!-- @property tags -->
|
||||
<@ if doc.properties @>
|
||||
<h2><a class="anchor" name="attributes" href="#attributes"></a>Attributes:</h2>
|
||||
<h2><a class="anchor" name="attributes" href="#attributes">Attributes</a></h2>
|
||||
<table class="table" style="margin:0;">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -293,10 +293,10 @@ Improve this doc
|
||||
|
||||
|
||||
<@- if doc.statics.length -@>
|
||||
<h2><a class="anchor" name="static-members" href="#static-members"></a>Static Members</h2>
|
||||
<h2><a class="anchor" name="static-members" href="#static-members">Static Members</a></h2>
|
||||
<@- for method in doc.statics @><@ if not method.internal @>
|
||||
<div id="<$ method.name $>"></div>
|
||||
<h3><a class="anchor" name="<$ method.name $>" href="#<$ method.name $>"></a><$ functionSyntax(method) $></h3>
|
||||
<h3><a class="anchor" name="<$ method.name $>" href="#<$ method.name $>"><$ functionSyntax(method) $></a></h3>
|
||||
|
||||
<$ method.description $>
|
||||
|
||||
@@ -327,14 +327,15 @@ Improve this doc
|
||||
<!-- instance methods on the class -->
|
||||
<@- if doc.members and doc.members.length @>
|
||||
|
||||
<h2><a class="anchor" name="instance-members" href="#instance-members"></a>Instance Members</h2>
|
||||
<h2><a class="anchor" name="instance-members" href="#instance-members">Instance Members</a></h2>
|
||||
<@- for method in doc.members @>
|
||||
|
||||
<div id="<$ method.name $>"></div>
|
||||
|
||||
<h3>
|
||||
<a class="anchor" name="<$ method.name $>" href="#<$ method.name $>"></a>
|
||||
<a class="anchor" name="<$ method.name $>" href="#<$ method.name $>">
|
||||
<$ functionSyntax(method) $>
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<$ method.description $>
|
||||
@@ -366,26 +367,26 @@ Improve this doc
|
||||
|
||||
<@- if doc.inputs and doc.inputs.length @>
|
||||
<!-- input methods on the class -->
|
||||
<h2><a class="anchor" name="input-properties" href="#input-properties"></a>Input Properties</h2>
|
||||
<h2><a class="anchor" name="input-properties" href="#input-properties">Input Properties</a></h2>
|
||||
<$ inputTable(doc.inputs) $>
|
||||
<@- endif -@>
|
||||
|
||||
<@- if doc.outputs and doc.outputs.length @>
|
||||
<!-- output events on the class -->
|
||||
<h2><a class="anchor" name="output-events" href="#output-events"></a>Output Events</h2>
|
||||
<h2><a class="anchor" name="output-events" href="#output-events">Output Events</a></h2>
|
||||
<$ outputTable(doc.outputs) $>
|
||||
<@- endif -@>
|
||||
|
||||
|
||||
<@ block advanced @>
|
||||
<@- if doc.advanced -@>
|
||||
<h2><a class="anchor" name="advanced" href="#advanced"></a>Advanced</h2>
|
||||
<h2><a class="anchor" name="advanced" href="#advanced">Advanced</a></h2>
|
||||
<$ doc.advanced | marked $>
|
||||
<@- endif -@>
|
||||
<@ endblock @>
|
||||
|
||||
<@ if doc.sassVariables @>
|
||||
<h2 id="sass-variable-header"><a class="anchor" name="sass-variables" href="#sass-variables"></a>Sass Variables</h2>
|
||||
<h2 id="sass-variable-header"><a class="anchor" name="sass-variables" href="#sass-variables">Sass Variables</a></h2>
|
||||
<$ sassTable(doc.sassVariables) $>
|
||||
<@ endif @>
|
||||
|
||||
@@ -393,7 +394,7 @@ Improve this doc
|
||||
<!-- related link -->
|
||||
<@- if doc.see @>
|
||||
|
||||
<h2><a class="anchor" name="related" href="#related"></a>Related</h2>
|
||||
<h2><a class="anchor" name="related" href="#related">Related</a></h2>
|
||||
<@ for s in doc.see @>
|
||||
<$ s | safe $> <@- if not loop.last @>,<@- endif -@>
|
||||
<@- endfor -@>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(join(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);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { exec, spawnSync, spawn } from 'child_process';
|
||||
import { exec, spawnSync } from 'child_process';
|
||||
import { spawn } from 'cross-spawn';
|
||||
import { writeFileSync } from 'fs';
|
||||
import * as changelog from 'conventional-changelog';
|
||||
import * as GithubApi from 'github';
|
||||
|
||||
@@ -50,6 +50,15 @@ export function createTempTsConfig(includeGlob: string[], target: string, module
|
||||
if (config.compilerOptions && config.compilerOptions.outDir) {
|
||||
delete config.compilerOptions.outDir;
|
||||
}
|
||||
|
||||
// remove linting checks that we do not want in dist
|
||||
if (config.compilerOptions.noUnusedLocals) {
|
||||
delete config.compilerOptions.noUnusedLocals;
|
||||
}
|
||||
if (config.compilerOptions.noUnusedParameters) {
|
||||
delete config.compilerOptions.noUnusedParameters;
|
||||
}
|
||||
|
||||
if (config.compilerOptions) {
|
||||
config.compilerOptions.module = moduleType;
|
||||
config.compilerOptions.target = target;
|
||||
@@ -190,7 +199,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 = [
|
||||
@@ -207,6 +216,9 @@ export function runAppScriptsServe(testOrDemoName: string, appEntryPoint: string
|
||||
'--copy', copyConfigPath,
|
||||
'--enableLint', 'false'
|
||||
];
|
||||
if (devApp) {
|
||||
scriptArgs.push('--bonjour');
|
||||
}
|
||||
|
||||
if (watchConfigPath) {
|
||||
scriptArgs.push('--watch');
|
||||
@@ -349,9 +361,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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export function config(config) {
|
||||
'dist/ionic-angular/umd/**/!(*spec).js': ['coverage'],
|
||||
'dist/ionic-angular/**/*.js': ['sourcemap']
|
||||
},
|
||||
reporters: ['dots', 'coverage', 'spec'],
|
||||
reporters: ['coverage', 'spec'],
|
||||
specReporter: {
|
||||
maxLogLines: 5, // limit number of lines logged per test
|
||||
suppressErrorSummary: true, // do not print error summary
|
||||
|
||||
@@ -3,8 +3,8 @@ import { Component } from '@angular/core';
|
||||
/**
|
||||
* Generated class for the $CLASSNAME component.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html
|
||||
* for more info on Angular Components.
|
||||
* See https://angular.io/api/core/Component for more info on Angular
|
||||
* Components.
|
||||
*/
|
||||
@Component({
|
||||
selector: '$FILENAME',
|
||||
|
||||
@@ -3,8 +3,8 @@ import { Directive } from '@angular/core';
|
||||
/**
|
||||
* Generated class for the $CLASSNAME directive.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/api/core/index/DirectiveMetadata-class.html
|
||||
* for more info on Angular Directives.
|
||||
* See https://angular.io/api/core/Directive for more info on Angular
|
||||
* Directives.
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[$FILENAME]' // Attribute selector
|
||||
|
||||
@@ -9,8 +9,5 @@ import { $CLASSNAME } from './$FILENAME';
|
||||
imports: [
|
||||
IonicPageModule.forChild($CLASSNAME),
|
||||
],
|
||||
exports: [
|
||||
$CLASSNAME
|
||||
]
|
||||
})
|
||||
export class $CLASSNAMEModule {}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
$IMPORTSTATEMENT
|
||||
|
||||
/**
|
||||
* Generated class for the $CLASSNAME page.
|
||||
*
|
||||
* See http://ionicframework.com/docs/components/#navigation for more info
|
||||
* on Ionic pages and navigation.
|
||||
* See https://ionicframework.com/docs/components/#navigation for more info on
|
||||
* Ionic pages and navigation.
|
||||
*/
|
||||
@IonicPage()
|
||||
$IONICPAGE
|
||||
@Component({
|
||||
selector: 'page-$FILENAME',
|
||||
templateUrl: '$FILENAME.html',
|
||||
|
||||
@@ -3,11 +3,10 @@ import { Pipe, PipeTransform } from '@angular/core';
|
||||
/**
|
||||
* Generated class for the $CLASSNAME pipe.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/guide/pipes.html for more info on
|
||||
* Angular Pipes.
|
||||
* See https://angular.io/api/core/Pipe for more info on Angular Pipes.
|
||||
*/
|
||||
@Pipe({
|
||||
name: '$FILENAME',
|
||||
name: '$PIPENAME',
|
||||
})
|
||||
export class $CLASSNAME implements PipeTransform {
|
||||
/**
|
||||
|
||||
@@ -5,8 +5,8 @@ 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 DI.
|
||||
See https://angular.io/guide/dependency-injection for more info on providers
|
||||
and Angular DI.
|
||||
*/
|
||||
@Injectable()
|
||||
export class $CLASSNAME {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController } from 'ionic-angular';
|
||||
$TABS_IMPORTSTATEMENT
|
||||
|
||||
/**
|
||||
* Generated class for the $CLASSNAME tabs.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/guide/dependency-injection.html for
|
||||
* more info on providers and Angular DI.
|
||||
* See https://ionicframework.com/docs/components/#navigation for more info on
|
||||
* Ionic pages and navigation.
|
||||
*/
|
||||
$IONICPAGE
|
||||
@Component({
|
||||
selector: 'page-$FILENAME',
|
||||
templateUrl: '$FILENAME.html'
|
||||
})
|
||||
@IonicPage()
|
||||
export class $CLASSNAME {
|
||||
|
||||
$TAB_VARIABLES
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { isDefined, assert } from '../util/util';
|
||||
import { assert, isDefined } from '../util/util';
|
||||
import { Platform } from '../platform/platform';
|
||||
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
@@ -48,12 +47,12 @@ export class Animation {
|
||||
if (ele) {
|
||||
if (typeof ele === 'string') {
|
||||
ele = this.plt.doc().querySelectorAll(ele);
|
||||
for (var i = 0; i < ele.length; i++) {
|
||||
for (let i = 0; i < ele.length; i++) {
|
||||
this._addEle(ele[i]);
|
||||
}
|
||||
|
||||
} else if (ele.length) {
|
||||
for (var i = 0; i < ele.length; i++) {
|
||||
for (let i = 0; i < ele.length; i++) {
|
||||
this._addEle(ele[i]);
|
||||
}
|
||||
|
||||
@@ -194,7 +193,7 @@ export class Animation {
|
||||
|
||||
if (!fxProp) {
|
||||
// first time we've see this EffectProperty
|
||||
var shouldTrans = (ANIMATION_TRANSFORMS[prop] === 1);
|
||||
const shouldTrans = (ANIMATION_TRANSFORMS[prop] === 1);
|
||||
fxProp = {
|
||||
name: prop,
|
||||
trans: shouldTrans,
|
||||
@@ -262,7 +261,7 @@ export class Animation {
|
||||
*/
|
||||
beforeClearStyles(propertyNames: string[]): Animation {
|
||||
this._bfSty = this._bfSty || {};
|
||||
for (var i = 0; i < propertyNames.length; i++) {
|
||||
for (let i = 0; i < propertyNames.length; i++) {
|
||||
this._bfSty[propertyNames[i]] = '';
|
||||
}
|
||||
return this;
|
||||
@@ -319,7 +318,7 @@ export class Animation {
|
||||
*/
|
||||
afterClearStyles(propertyNames: string[]): Animation {
|
||||
this._afSty = this._afSty || {};
|
||||
for (var i = 0; i < propertyNames.length; i++) {
|
||||
for (let i = 0; i < propertyNames.length; i++) {
|
||||
this._afSty[propertyNames[i]] = '';
|
||||
}
|
||||
return this;
|
||||
@@ -386,7 +385,7 @@ export class Animation {
|
||||
this._hasDur = (this.getDuration(opts) > ANIMATION_DURATION_MIN);
|
||||
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
children[i]._playInit(opts);
|
||||
}
|
||||
@@ -441,7 +440,7 @@ export class Animation {
|
||||
*/
|
||||
_playProgress(opts: PlayOptions) {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
children[i]._playProgress(opts);
|
||||
}
|
||||
@@ -474,7 +473,7 @@ export class Animation {
|
||||
*/
|
||||
_playToStep(stepValue: number) {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
children[i]._playToStep(stepValue);
|
||||
}
|
||||
@@ -546,7 +545,7 @@ export class Animation {
|
||||
*/
|
||||
_playEnd(stepValue?: number) {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
children[i]._playEnd(stepValue);
|
||||
}
|
||||
@@ -583,7 +582,7 @@ export class Animation {
|
||||
}
|
||||
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
if (children[i]._hasDuration(opts)) {
|
||||
return true;
|
||||
}
|
||||
@@ -602,7 +601,7 @@ export class Animation {
|
||||
}
|
||||
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
if (children[i]._hasDomReads()) {
|
||||
return true;
|
||||
}
|
||||
@@ -650,16 +649,16 @@ export class Animation {
|
||||
if (this._rv) {
|
||||
stepValue = ((stepValue * -1) + 1);
|
||||
}
|
||||
var i: number, j: number;
|
||||
var finalTransform: string = '';
|
||||
var elements = this._e;
|
||||
let i: number, j: number;
|
||||
let finalTransform: string = '';
|
||||
const elements = this._e;
|
||||
for (i = 0; i < effects.length; i++) {
|
||||
var fx = effects[i];
|
||||
const fx = effects[i];
|
||||
|
||||
if (fx.from && fx.to) {
|
||||
var fromNum = fx.from.num;
|
||||
var toNum = fx.to.num;
|
||||
var tweenEffect = (fromNum !== toNum);
|
||||
const fromNum = fx.from.num;
|
||||
const toNum = fx.to.num;
|
||||
const tweenEffect = (fromNum !== toNum);
|
||||
|
||||
assert(tweenEffect || !this._isAsync, 'in async animations to != from value');
|
||||
if (tweenEffect) {
|
||||
@@ -676,8 +675,8 @@ export class Animation {
|
||||
|
||||
} else if (tweenEffect) {
|
||||
// EVERYTHING IN BETWEEN
|
||||
var valNum = (((toNum - fromNum) * stepValue) + fromNum);
|
||||
var unit = fx.to.unit;
|
||||
let valNum = (((toNum - fromNum) * stepValue) + fromNum);
|
||||
const unit = fx.to.unit;
|
||||
if (unit === 'px') {
|
||||
valNum = Math.round(valNum);
|
||||
}
|
||||
@@ -685,7 +684,7 @@ export class Animation {
|
||||
}
|
||||
|
||||
if (val !== null) {
|
||||
var prop = fx.name;
|
||||
const prop = fx.name;
|
||||
if (fx.trans) {
|
||||
finalTransform += prop + '(' + val + ') ';
|
||||
|
||||
@@ -705,7 +704,7 @@ export class Animation {
|
||||
finalTransform += 'translateZ(0px)';
|
||||
}
|
||||
|
||||
var cssTransform = this.plt.Css.transform;
|
||||
const cssTransform = this.plt.Css.transform;
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
(<any>elements[i].style)[cssTransform] = finalTransform;
|
||||
@@ -734,7 +733,7 @@ export class Animation {
|
||||
const cssTransitionTimingFn = Css.transitionTimingFn;
|
||||
|
||||
let eleStyle: any;
|
||||
for (var i = 0; i < this._eL; i++) {
|
||||
for (let i = 0; i < this._eL; i++) {
|
||||
eleStyle = elements[i].style;
|
||||
if (dur > 0) {
|
||||
// ******** DOM WRITE ****************
|
||||
@@ -836,14 +835,14 @@ export class Animation {
|
||||
*/
|
||||
_fireBeforeReadFunc() {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM READ ****************
|
||||
children[i]._fireBeforeReadFunc();
|
||||
}
|
||||
|
||||
const readFunctions = this._rdFn;
|
||||
if (readFunctions) {
|
||||
for (var i = 0; i < readFunctions.length; i++) {
|
||||
for (let i = 0; i < readFunctions.length; i++) {
|
||||
// ******** DOM READ ****************
|
||||
readFunctions[i]();
|
||||
}
|
||||
@@ -857,14 +856,14 @@ export class Animation {
|
||||
*/
|
||||
_fireBeforeWriteFunc() {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
children[i]._fireBeforeWriteFunc();
|
||||
}
|
||||
|
||||
const writeFunctions = this._wrFn;
|
||||
if (this._wrFn) {
|
||||
for (var i = 0; i < writeFunctions.length; i++) {
|
||||
for (let i = 0; i < writeFunctions.length; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
writeFunctions[i]();
|
||||
}
|
||||
@@ -909,7 +908,7 @@ export class Animation {
|
||||
|
||||
// inline styles that were added before the animation should be removed
|
||||
if (this._bfSty) {
|
||||
for (var prop in this._bfSty) {
|
||||
for (const prop in this._bfSty) {
|
||||
// ******** DOM WRITE ****************
|
||||
(<any>ele).style[prop] = '';
|
||||
}
|
||||
@@ -936,7 +935,7 @@ export class Animation {
|
||||
|
||||
// inline styles to add after the animation
|
||||
if (this._afSty) {
|
||||
for (var prop in this._afSty) {
|
||||
for (const prop in this._afSty) {
|
||||
// ******** DOM WRITE ****************
|
||||
(<any>ele).style[prop] = this._afSty[prop];
|
||||
}
|
||||
@@ -956,8 +955,8 @@ export class Animation {
|
||||
let willChange: string;
|
||||
if (addWillChange && effects) {
|
||||
wc = [];
|
||||
for (var i = 0; i < effects.length; i++) {
|
||||
var propWC = effects[i].wc;
|
||||
for (let i = 0; i < effects.length; i++) {
|
||||
const propWC = effects[i].wc;
|
||||
if (propWC === 'webkitTransform') {
|
||||
wc.push('transform', '-webkit-transform');
|
||||
|
||||
@@ -969,7 +968,7 @@ export class Animation {
|
||||
} else {
|
||||
willChange = '';
|
||||
}
|
||||
for (var i = 0; i < this._eL; i++) {
|
||||
for (let i = 0; i < this._eL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
(<any>this._e[i]).style.willChange = willChange;
|
||||
}
|
||||
@@ -996,7 +995,7 @@ export class Animation {
|
||||
*/
|
||||
_progressStart() {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
children[i]._progressStart();
|
||||
}
|
||||
@@ -1017,7 +1016,7 @@ export class Animation {
|
||||
stepValue = Math.min(1, Math.max(0, stepValue));
|
||||
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
children[i].progressStep(stepValue);
|
||||
}
|
||||
@@ -1076,7 +1075,7 @@ export class Animation {
|
||||
*/
|
||||
_progressEnd(shouldComplete: boolean, stepValue: number, dur: number, isAsync: boolean) {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
// ******** DOM WRITE ****************
|
||||
children[i]._progressEnd(shouldComplete, stepValue, dur, isAsync);
|
||||
}
|
||||
@@ -1127,7 +1126,7 @@ export class Animation {
|
||||
*/
|
||||
_didFinishAll(hasCompleted: boolean, finishAsyncAnimations: boolean, finishNoDurationAnimations: boolean) {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
children[i]._didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations);
|
||||
}
|
||||
|
||||
@@ -1146,14 +1145,14 @@ export class Animation {
|
||||
|
||||
if (this._fFn) {
|
||||
// run all finish callbacks
|
||||
for (var i = 0; i < this._fFn.length; i++) {
|
||||
for (let i = 0; i < this._fFn.length; i++) {
|
||||
this._fFn[i](this);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._fOneFn) {
|
||||
// run all "onetime" finish callbacks
|
||||
for (var i = 0; i < this._fOneFn.length; i++) {
|
||||
for (let i = 0; i < this._fOneFn.length; i++) {
|
||||
this._fOneFn[i](this);
|
||||
}
|
||||
this._fOneFn.length = 0;
|
||||
@@ -1165,7 +1164,7 @@ export class Animation {
|
||||
*/
|
||||
reverse(shouldReverse: boolean = true): Animation {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
children[i].reverse(shouldReverse);
|
||||
}
|
||||
this._rv = shouldReverse;
|
||||
@@ -1177,7 +1176,7 @@ export class Animation {
|
||||
*/
|
||||
destroy() {
|
||||
const children = this._c;
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
children[i].destroy();
|
||||
}
|
||||
|
||||
@@ -1202,9 +1201,9 @@ export class Animation {
|
||||
*/
|
||||
_transEl(): HTMLElement {
|
||||
// get the lowest level element that has an Animation
|
||||
var targetEl: HTMLElement;
|
||||
let targetEl: HTMLElement;
|
||||
|
||||
for (var i = 0; i < this._cL; i++) {
|
||||
for (let i = 0; i < this._cL; i++) {
|
||||
targetEl = this._c[i]._transEl();
|
||||
if (targetEl) {
|
||||
return targetEl;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Component, ElementRef, HostListener, Renderer, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { ActionSheetOptions, ActionSheetButton } from './action-sheet-options';
|
||||
import { ActionSheetButton, ActionSheetOptions } from './action-sheet-options';
|
||||
import { assert } from '../../util/util';
|
||||
import { BlockerDelegate, GestureController, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
import { BLOCK_ALL, BlockerDelegate, GestureController } from '../../gestures/gesture-controller';
|
||||
import { Config } from '../../config/config';
|
||||
import { KEY_ESCAPE } from '../../platform/key';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { NavOptions } from '../../navigation/nav-util';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
@@ -57,7 +56,6 @@ export class ActionSheetCmp {
|
||||
constructor(
|
||||
private _viewCtrl: ViewController,
|
||||
config: Config,
|
||||
private _plt: Platform,
|
||||
private _elementRef: ElementRef,
|
||||
gestureCtrl: GestureController,
|
||||
params: NavParams,
|
||||
@@ -117,8 +115,6 @@ export class ActionSheetCmp {
|
||||
}
|
||||
|
||||
ionViewDidEnter() {
|
||||
this._plt.focusOutActiveElement();
|
||||
|
||||
const focusableEle = this._elementRef.nativeElement.querySelector('button');
|
||||
if (focusableEle) {
|
||||
focusableEle.focus();
|
||||
|
||||
@@ -13,4 +13,4 @@ export interface ActionSheetButton {
|
||||
icon?: string;
|
||||
cssClass?: string;
|
||||
handler?: () => boolean|void;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ActionSheetCmp } from './action-sheet-component';
|
||||
import { ActionSheetOptions, ActionSheetButton } from './action-sheet-options';
|
||||
import { ActionSheetSlideIn, ActionSheetMdSlideIn, ActionSheetSlideOut, ActionSheetMdSlideOut, ActionSheetWpSlideIn, ActionSheetWpSlideOut } from './action-sheet-transitions';
|
||||
import { ActionSheetButton, ActionSheetOptions } from './action-sheet-options';
|
||||
import { ActionSheetMdSlideIn, ActionSheetMdSlideOut, ActionSheetSlideIn, ActionSheetSlideOut, ActionSheetWpSlideIn, ActionSheetWpSlideOut } from './action-sheet-transitions';
|
||||
import { App } from '../app/app';
|
||||
import { Config } from '../../config/config';
|
||||
import { isPresent } from '../../util/util';
|
||||
|
||||
@@ -2,14 +2,14 @@ import { Component, ElementRef, HostListener, Renderer, ViewEncapsulation } from
|
||||
|
||||
import { Config } from '../../config/config';
|
||||
import { NON_TEXT_INPUT_REGEX } from '../../util/dom';
|
||||
import { GestureController, BlockerDelegate, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
import { isPresent, assert } from '../../util/util';
|
||||
import { BLOCK_ALL, BlockerDelegate, GestureController } from '../../gestures/gesture-controller';
|
||||
import { assert, isPresent } from '../../util/util';
|
||||
import { KEY_ENTER, KEY_ESCAPE } from '../../platform/key';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { NavOptions } from '../../navigation/nav-util';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
import { AlertInputOptions, AlertOptions, AlertButton } from './alert-options';
|
||||
import { AlertButton, AlertInputOptions, AlertOptions } from './alert-options';
|
||||
|
||||
|
||||
/**
|
||||
@@ -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
|
||||
|
||||
@@ -29,4 +29,4 @@ export interface AlertButton {
|
||||
role?: string;
|
||||
cssClass?: string;
|
||||
handler?: (value: any) => boolean|void;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { App } from '../app/app';
|
||||
import { AlertCmp } from './alert-component';
|
||||
import { AlertOptions, AlertInputOptions, AlertButton } from './alert-options';
|
||||
import { AlertPopIn, AlertPopOut, AlertMdPopIn, AlertMdPopOut, AlertWpPopIn, AlertWpPopOut } from './alert-transitions';
|
||||
import { AlertButton, AlertInputOptions, AlertOptions } from './alert-options';
|
||||
import { AlertMdPopIn, AlertMdPopOut, AlertPopIn, AlertPopOut, AlertWpPopIn, AlertWpPopOut } from './alert-transitions';
|
||||
import { Config } from '../../config/config';
|
||||
import { isPresent } from '../../util/util';
|
||||
import { NavOptions } from '../../navigation/nav-util';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule, AlertController, LoadingController, NavController } from '../../../..';
|
||||
import { AlertController, IonicApp, IonicModule, LoadingController, NavController } from '../../../..';
|
||||
import { FormBuilder, Validators } from '@angular/forms';
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { EventEmitter, Injectable, Optional } from '@angular/core';
|
||||
import { Title, DOCUMENT } from '@angular/platform-browser';
|
||||
import { DOCUMENT, Title } from '@angular/platform-browser';
|
||||
|
||||
import { IonicApp } from './app-root';
|
||||
import * as Constants from './app-constants';
|
||||
import { ClickBlock } from './click-block';
|
||||
import { runInDev, assert } from '../../util/util';
|
||||
import { assert, runInDev } from '../../util/util';
|
||||
import { Config } from '../../config/config';
|
||||
import { isNav, NavOptions, DIRECTION_FORWARD, DIRECTION_BACK } from '../../navigation/nav-util';
|
||||
import { DIRECTION_BACK, DIRECTION_FORWARD, NavOptions, 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,28 +206,82 @@ 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()`
|
||||
* @return {NavController} Returns the first Active Nav Controller from the list. This method is deprecated
|
||||
*/
|
||||
getActiveNav(): NavController {
|
||||
getActiveNav(): NavControllerBase {
|
||||
console.warn('(getActiveNav) is deprecated and will be removed in the next major release. Use getActiveNavs instead.');
|
||||
const navs = this.getActiveNavs();
|
||||
if (navs && navs.length) {
|
||||
return navs[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {NavController[]} Returns the active NavControllers. Using this method is preferred when we need access to the top-level navigation controller while on the outside views and handlers like `registerBackButtonAction()`
|
||||
*/
|
||||
getActiveNavs(rootNavId?: string): NavControllerBase[] {
|
||||
const portal = this._appRoot._getPortal(Constants.PORTAL_MODAL);
|
||||
if (portal.length() > 0) {
|
||||
return findTopNav(portal);
|
||||
return <NavControllerBase[]> findTopNavs(portal);
|
||||
}
|
||||
return findTopNav(this._rootNav || null);
|
||||
if (!this._rootNavs || !this._rootNavs.size) {
|
||||
return [];
|
||||
}
|
||||
if (this._rootNavs.size === 1) {
|
||||
return <NavControllerBase[]> findTopNavs(this._rootNavs.values().next().value);
|
||||
}
|
||||
if (rootNavId) {
|
||||
return <NavControllerBase[]> findTopNavs(this._rootNavs.get(rootNavId));
|
||||
}
|
||||
// fallback to just using all root names
|
||||
let activeNavs: NavigationContainer[] = [];
|
||||
this._rootNavs.forEach(nav => {
|
||||
const topNavs = findTopNavs(nav);
|
||||
activeNavs = activeNavs.concat(topNavs);
|
||||
});
|
||||
return <NavControllerBase[]> activeNavs;
|
||||
}
|
||||
|
||||
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
|
||||
let list: NavigationContainer[] = [];
|
||||
this._rootNavs.forEach((container: NavigationContainer) => {
|
||||
list = list.concat(findTopNavs(container));
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,7 +296,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 +303,7 @@ export class App {
|
||||
}
|
||||
|
||||
enteringView.setLeavingOpts({
|
||||
keyboardClose: false,
|
||||
keyboardClose: opts.keyboardClose,
|
||||
direction: DIRECTION_BACK,
|
||||
animation: enteringView.getTransitionName(DIRECTION_BACK),
|
||||
ev: opts.ev
|
||||
@@ -260,7 +321,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 +336,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 +345,140 @@ 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 activeNavs = this.getActiveNavs(navContainer.id);
|
||||
const poppableNavs = activeNavs.map(activeNav => getPoppableNav(activeNav)).filter(nav => !!nav);
|
||||
poppableNavs.forEach(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() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
getNavByIdOrName(id: string) {
|
||||
const navs = Array.from(this._rootNavs.values());
|
||||
for (const navContainer of navs) {
|
||||
const match = getNavByIdOrName(navContainer, id);
|
||||
if (match) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function recursivePop(nav: any): Promise<any> {
|
||||
export function getNavByIdOrName(nav: NavigationContainer, id: string): NavigationContainer {
|
||||
if (nav.id === id || nav.name === id) {
|
||||
return nav;
|
||||
}
|
||||
for (const child of nav.getAllChildNavs()) {
|
||||
const tmp = getNavByIdOrName(child, id);
|
||||
if (tmp) {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
while (nav) {
|
||||
activeChildNav = nav.getActiveChildNav();
|
||||
if (!activeChildNav) {
|
||||
break;
|
||||
}
|
||||
nav = activeChildNav;
|
||||
export function findTopNavs(nav: NavigationContainer): NavigationContainer[] {
|
||||
let containers: NavigationContainer[] = [];
|
||||
const childNavs = nav.getActiveChildNavs();
|
||||
if (!childNavs || !childNavs.length) {
|
||||
containers.push(nav);
|
||||
} else {
|
||||
childNavs.forEach(childNav => {
|
||||
const topNavs = findTopNavs(childNav);
|
||||
containers = containers.concat(topNavs);
|
||||
});
|
||||
}
|
||||
|
||||
return nav;
|
||||
return containers;
|
||||
}
|
||||
|
||||
|
||||
const SKIP_BLURRING = ['INPUT', 'TEXTAREA', 'ION-INPUT', 'ION-TEXTAREA'];
|
||||
const ACTIVE_SCROLLING_TIME = 100;
|
||||
const CLICK_BLOCK_BUFFER_IN_MILLIS = 64;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, ElementRef, forwardRef, Inject, Renderer } from '@angular/core';
|
||||
import { Directive, ElementRef, Inject, Renderer, forwardRef } from '@angular/core';
|
||||
|
||||
import { App } from '../app/app';
|
||||
import { Config } from '../../config/config';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Menu, MenuType } from './menu-interface';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { removeArrayItem, assert } from '../../util/util';
|
||||
import { assert, removeArrayItem } from '../../util/util';
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ export interface Menu {
|
||||
getBackdropElement(): HTMLElement;
|
||||
_canOpen(): boolean;
|
||||
persistent: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MenuType {
|
||||
ani: Animation;
|
||||
@@ -37,4 +37,4 @@ export interface MenuType {
|
||||
setProgessStep(stepValue: number): void;
|
||||
setProgressEnd(shouldComplete: boolean, currentStepValue: number, velocity: number, done: Function): void;
|
||||
destroy(): void;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { ComponentFactoryResolver, Directive, ElementRef, ErrorHandler, forwardRef, Inject, Input, NgZone, Optional, Renderer, ViewContainerRef } from '@angular/core';
|
||||
import { ComponentFactoryResolver, Directive, ElementRef, ErrorHandler, Inject, Input, NgZone, Optional, Renderer, ViewContainerRef, forwardRef } from '@angular/core';
|
||||
|
||||
import { App } from './app';
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { App } from '../app';
|
||||
import { ClickBlock } from '../click-block';
|
||||
import { Config } from '../../../config/config';
|
||||
import { mockApp, mockConfig, mockElementRef, mockNavController, mockPlatform, MockPlatform, mockRenderer, mockTab, mockTabs, mockView, mockViews } from '../../../util/mock-providers';
|
||||
import { MockPlatform, mockApp, mockConfig, mockElementRef, mockNavController, mockPlatform, mockRenderer, mockTab, mockTabs, mockView, mockViews } from '../../../util/mock-providers';
|
||||
import { OverlayPortal } from '../overlay-portal';
|
||||
import { PORTAL_MODAL } from '../app-constants';
|
||||
|
||||
@@ -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.getActiveNavs(nav.id)[0]).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.getActiveNavs(nav.id)[0]).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,38 +271,273 @@ 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', () => {
|
||||
describe('getActiveNavs', () => {
|
||||
|
||||
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();
|
||||
nav2.name = 'nav2';
|
||||
const nav3 = mockNavController();
|
||||
nav3.name = 'nav3';
|
||||
const nav4 = mockNavController();
|
||||
nav4.name = 'nav4';
|
||||
|
||||
tab1.registerChildNav(nav4);
|
||||
// tab 2 registers two child navs!!
|
||||
tab2.registerChildNav(nav2);
|
||||
tab2.registerChildNav(nav3);
|
||||
|
||||
expect(app.getActiveNav()).toBe(nav3);
|
||||
const activeNavs = app.getActiveNavs(nav.id);
|
||||
expect(activeNavs.length).toEqual(2);
|
||||
expect(activeNavs[0]).toEqual(nav2);
|
||||
expect(activeNavs[1]).toEqual(nav3);
|
||||
|
||||
const activeNavsTwo = app.getActiveNavs();
|
||||
expect(activeNavsTwo.length).toEqual(2);
|
||||
expect(activeNavsTwo[0]).toEqual(nav2);
|
||||
expect(activeNavsTwo[1]).toEqual(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.getActiveNavs(nav.id)[0]).toBe(tab2);
|
||||
expect(app.getActiveNavs()[0]).toBe(tab2);
|
||||
|
||||
tab2.setSelected(false);
|
||||
tab3.setSelected(true);
|
||||
expect(app.getActiveNavs(nav.id)[0]).toBe(tab3);
|
||||
expect(app.getActiveNavs()[0]).toBe(tab3);
|
||||
});
|
||||
|
||||
it('should get active tab NavController when using tabs, and tabs is the root', () => {
|
||||
const tabs = mockTabs();
|
||||
mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
const tab3 = mockTab(tabs);
|
||||
app.registerRootNav(tabs);
|
||||
|
||||
tab2.setSelected(true);
|
||||
|
||||
expect(app.getActiveNavs(tabs.id)[0]).toBe(tab2);
|
||||
expect(app.getActiveNavs()[0]).toBe(tab2);
|
||||
|
||||
tab2.setSelected(false);
|
||||
tab3.setSelected(true);
|
||||
expect(app.getActiveNavs(tabs.id)[0]).toBe(tab3);
|
||||
expect(app.getActiveNavs()[0]).toBe(tab3);
|
||||
});
|
||||
|
||||
it('should get active NavController when nested 3 deep', () => {
|
||||
const nav1 = mockNavController();
|
||||
const nav2 = mockNavController();
|
||||
const nav3 = mockNavController();
|
||||
app.registerRootNav(nav1);
|
||||
|
||||
nav1.registerChildNav(nav2);
|
||||
nav2.registerChildNav(nav3);
|
||||
|
||||
expect(app.getActiveNavs(nav1.id)[0]).toBe(nav3);
|
||||
expect(app.getActiveNavs()[0]).toBe(nav3);
|
||||
expect(app.getActiveNavs().length).toBe(1);
|
||||
});
|
||||
|
||||
it('should get active NavController when nested 2 deep', () => {
|
||||
const nav1 = mockNavController();
|
||||
const nav2 = mockNavController();
|
||||
app.registerRootNav(nav1);
|
||||
|
||||
nav1.registerChildNav(nav2);
|
||||
|
||||
const activeNav = app.getActiveNavs(nav1.id)[0];
|
||||
|
||||
expect(activeNav).toBe(nav2);
|
||||
|
||||
expect(app.getActiveNavs()[0]).toBe(nav2);
|
||||
});
|
||||
|
||||
it('should get active NavController when only one nav controller', () => {
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
expect(app.getActiveNavs(nav.id)[0]).toBe(nav);
|
||||
expect(app.getActiveNavs()[0]).toBe(nav);
|
||||
});
|
||||
|
||||
it('should set/get the root nav controller', () => {
|
||||
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', () => {
|
||||
const activeNavs = app.getActiveNavs();
|
||||
const rootNav = app.getRootNavById('');
|
||||
expect(activeNavs.length).toEqual(0);
|
||||
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.getActiveNavs(rootNavOne.id)[0];
|
||||
const activeNavTwo = app.getActiveNavs(rootNavTwo.id)[0];
|
||||
|
||||
expect(activeNavOne).toBe(childNavOne);
|
||||
expect(activeNavTwo).toBe(childNavTwo);
|
||||
|
||||
expect(app.getActiveNavs()[0]).toBe(childNavOne);
|
||||
expect(app.getActiveNavs()[1]).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.getActiveNavs()[0];
|
||||
|
||||
expect(result).toEqual(childNavOne);
|
||||
});
|
||||
|
||||
it('should return the all the active navs when there is not an id passed', () => {
|
||||
const rootNavOne = mockNavController();
|
||||
app.registerRootNav(rootNavOne);
|
||||
|
||||
const rootNavTwo = mockNavController();
|
||||
app.registerRootNav(rootNavTwo);
|
||||
|
||||
const childNavOne = mockNavController();
|
||||
rootNavOne.registerChildNav(childNavOne);
|
||||
|
||||
const childChildNavOne = mockNavController();
|
||||
childNavOne.registerChildNav(childChildNavOne);
|
||||
|
||||
const childNavTwo = mockNavController();
|
||||
rootNavTwo.registerChildNav(childNavTwo);
|
||||
|
||||
const childChildNavTwo = mockNavController();
|
||||
childNavTwo.registerChildNav(childChildNavTwo);
|
||||
|
||||
const results = app.getActiveNavs();
|
||||
expect(results.length).toEqual(2);
|
||||
expect(results[0]).toEqual(childChildNavOne);
|
||||
expect(results[1]).toEqual(childChildNavTwo);
|
||||
|
||||
const withIdResultsOne = app.getActiveNavs(rootNavOne.id);
|
||||
expect(withIdResultsOne.length).toEqual(1);
|
||||
expect(withIdResultsOne[0]).toEqual(childChildNavOne);
|
||||
|
||||
const withIdResultsTwo = app.getActiveNavs(rootNavTwo.id);
|
||||
expect(withIdResultsTwo.length).toEqual(1);
|
||||
expect(withIdResultsTwo[0]).toEqual(childChildNavTwo);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getActiveNav', () => {
|
||||
it('should get active NavController when using tabs with nested nav', () => {
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
const tabs = mockTabs();
|
||||
const tab1 = mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
nav.registerChildNav(tabs);
|
||||
|
||||
tab2.setSelected(true);
|
||||
const nav2 = mockNavController();
|
||||
nav2.name = 'nav2';
|
||||
const nav3 = mockNavController();
|
||||
nav3.name = 'nav3';
|
||||
const nav4 = mockNavController();
|
||||
nav4.name = 'nav4';
|
||||
|
||||
tab1.registerChildNav(nav4);
|
||||
// tab 2 registers two child navs!!
|
||||
tab2.registerChildNav(nav2);
|
||||
tab2.registerChildNav(nav3);
|
||||
|
||||
const activeNav = app.getActiveNav();
|
||||
expect(activeNav).toEqual(nav2);
|
||||
});
|
||||
|
||||
it('should get active NavController when using tabs, nested in a root nav', () => {
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
|
||||
const tabs = mockTabs();
|
||||
mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
const tab3 = mockTab(tabs);
|
||||
nav.registerChildNav(tabs);
|
||||
|
||||
tab2.setSelected(true);
|
||||
@@ -307,11 +550,11 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
@@ -323,10 +566,10 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
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);
|
||||
@@ -335,29 +578,87 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
expect(activeNav).toBe(nav2);
|
||||
});
|
||||
|
||||
it('should get active NavController when only one nav controller', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
expect(app.getActiveNav()).toBe(nav);
|
||||
});
|
||||
|
||||
it('should set/get the root nav controller', () => {
|
||||
let nav = mockNavController();
|
||||
app._setRootNav(nav);
|
||||
expect(app.getRootNav()).toBe(nav);
|
||||
it('should not get an active NavController if there is not root set', () => {
|
||||
const activeNav = app.getActiveNav();
|
||||
expect(activeNav).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not get an active NavController if there is not root set', () => {
|
||||
expect(app.getActiveNav()).toBeNull();
|
||||
expect(app.getRootNav()).toBeNull();
|
||||
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();
|
||||
|
||||
expect(activeNavOne).toBe(childNavOne);
|
||||
});
|
||||
|
||||
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 +682,7 @@ describe('App', () => {
|
||||
|
||||
it('should enable click block when false is passed with duration', () => {
|
||||
// arrange
|
||||
let mockClickBlock: any = {
|
||||
const mockClickBlock: any = {
|
||||
activate: () => {}
|
||||
};
|
||||
|
||||
@@ -398,7 +699,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 +717,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 +734,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 +751,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 +767,153 @@ describe('App', () => {
|
||||
});
|
||||
});
|
||||
|
||||
var app: App;
|
||||
var config: Config;
|
||||
var plt: MockPlatform;
|
||||
var portal: OverlayPortal;
|
||||
describe('getNavByIdOrName', () => {
|
||||
it('should return a basic root nav', () => {
|
||||
const nav = mockNavController();
|
||||
app.registerRootNav(nav);
|
||||
const result = app.getNavByIdOrName(nav.id);
|
||||
expect(result).toEqual(nav);
|
||||
});
|
||||
|
||||
it('should return a child nav', () => {
|
||||
const rootNav = mockNavController();
|
||||
app.registerRootNav(rootNav);
|
||||
|
||||
const childNav = mockNavController();
|
||||
childNav.parent = rootNav;
|
||||
rootNav.registerChildNav(childNav);
|
||||
|
||||
const childChildNav = mockNavController();
|
||||
childChildNav.parent = childNav;
|
||||
childNav.registerChildNav(childChildNav);
|
||||
|
||||
|
||||
const expectedChildNav = app.getNavByIdOrName(childNav.id);
|
||||
expect(expectedChildNav).toEqual(childNav);
|
||||
|
||||
const expectedChildChildNav = app.getNavByIdOrName(childChildNav.id);
|
||||
expect(expectedChildChildNav).toEqual(childChildNav);
|
||||
});
|
||||
|
||||
it('should return a child nav when there is a tabs in there', () => {
|
||||
const rootNav = mockNavController();
|
||||
app.registerRootNav(rootNav);
|
||||
|
||||
const tabs = mockTabs();
|
||||
tabs.parent = rootNav;
|
||||
rootNav.registerChildNav(tabs);
|
||||
|
||||
const tab1 = mockTab(tabs);
|
||||
const tab2 = mockTab(tabs);
|
||||
const tab3 = mockTab(tabs);
|
||||
|
||||
const tabChildNav = mockNavController();
|
||||
tabChildNav.parent = tab2;
|
||||
tab2.registerChildNav(tabChildNav);
|
||||
|
||||
const tabChildChildNav = mockNavController();
|
||||
tabChildChildNav.parent = tabChildNav;
|
||||
tabChildNav.registerChildNav(tabChildChildNav);
|
||||
|
||||
const expectedTab1 = app.getNavByIdOrName(tab1.id);
|
||||
expect(expectedTab1).toEqual(tab1);
|
||||
|
||||
const expectedTab2 = app.getNavByIdOrName(tab2.id);
|
||||
expect(expectedTab2).toEqual(tab2);
|
||||
|
||||
const expectedTab3 = app.getNavByIdOrName(tab3.id);
|
||||
expect(expectedTab3).toEqual(tab3);
|
||||
|
||||
const expectedTabChildNav = app.getNavByIdOrName(tabChildNav.id);
|
||||
expect(expectedTabChildNav).toEqual(tabChildNav);
|
||||
|
||||
const expectedTabChildChildNav = app.getNavByIdOrName(tabChildChildNav.id);
|
||||
expect(expectedTabChildChildNav).toEqual(tabChildChildNav);
|
||||
});
|
||||
|
||||
it('should return a basic root nav when the are multiple root navs', () => {
|
||||
const rootNavOne = mockNavController();
|
||||
const rootNavTwo = mockNavController();
|
||||
const rootNavThree = mockNavController();
|
||||
app.registerRootNav(rootNavOne);
|
||||
app.registerRootNav(rootNavTwo);
|
||||
app.registerRootNav(rootNavThree);
|
||||
|
||||
const expectedRootNavOne = app.getNavByIdOrName(rootNavOne.id);
|
||||
expect(expectedRootNavOne).toEqual(rootNavOne);
|
||||
|
||||
const expectedRootNavTwo = app.getNavByIdOrName(rootNavTwo.id);
|
||||
expect(expectedRootNavTwo).toEqual(rootNavTwo);
|
||||
|
||||
const expectedRootNavThree = app.getNavByIdOrName(rootNavThree.id);
|
||||
expect(expectedRootNavThree).toEqual(rootNavThree);
|
||||
});
|
||||
|
||||
it('should return a proper navs when there are multiple root navs with nested navs', () => {
|
||||
const rootNavOne = mockNavController();
|
||||
const rootNavTwo = mockNavController();
|
||||
const rootNavThree = mockNavController();
|
||||
app.registerRootNav(rootNavOne);
|
||||
app.registerRootNav(rootNavTwo);
|
||||
app.registerRootNav(rootNavThree);
|
||||
|
||||
const childNavOne = mockNavController();
|
||||
childNavOne.parent = rootNavOne;
|
||||
rootNavOne.registerChildNav(childNavOne);
|
||||
|
||||
const childChildNavOne = mockNavController();
|
||||
childChildNavOne.parent = childNavOne;
|
||||
childNavOne.registerChildNav(childChildNavOne);
|
||||
|
||||
const childNavTwo = mockNavController();
|
||||
childNavOne.parent = rootNavTwo;
|
||||
rootNavTwo.registerChildNav(childNavTwo);
|
||||
|
||||
const childChildNavTwo = mockNavController();
|
||||
childChildNavTwo.parent = childNavTwo;
|
||||
childNavTwo.registerChildNav(childChildNavTwo);
|
||||
|
||||
const childNavThree = mockNavController();
|
||||
childNavThree.parent = rootNavThree;
|
||||
rootNavThree.registerChildNav(childNavThree);
|
||||
|
||||
const childChildNavThree = mockNavController();
|
||||
childChildNavThree.parent = childNavThree;
|
||||
childNavThree.registerChildNav(childChildNavThree);
|
||||
|
||||
const expectedRootNavOne = app.getNavByIdOrName(rootNavOne.id);
|
||||
expect(expectedRootNavOne).toEqual(rootNavOne);
|
||||
|
||||
const expectedChildNavOne = app.getNavByIdOrName(childNavOne.id);
|
||||
expect(expectedChildNavOne).toEqual(childNavOne);
|
||||
|
||||
const expectedChildChildNavOne = app.getNavByIdOrName(childChildNavOne.id);
|
||||
expect(expectedChildChildNavOne).toEqual(childChildNavOne);
|
||||
|
||||
const expectedRootNavTwo = app.getNavByIdOrName(rootNavTwo.id);
|
||||
expect(expectedRootNavTwo).toEqual(rootNavTwo);
|
||||
|
||||
const expectedChildNavTwo = app.getNavByIdOrName(childNavTwo.id);
|
||||
expect(expectedChildNavTwo).toEqual(childNavTwo);
|
||||
|
||||
const expectedChildChildNavTwo = app.getNavByIdOrName(childChildNavTwo.id);
|
||||
expect(expectedChildChildNavTwo).toEqual(childChildNavTwo);
|
||||
|
||||
const expectedRootNavThree = app.getNavByIdOrName(rootNavThree.id);
|
||||
expect(expectedRootNavThree).toEqual(rootNavThree);
|
||||
|
||||
const expectedChildNavThree = app.getNavByIdOrName(childNavThree.id);
|
||||
expect(expectedChildNavThree).toEqual(childNavThree);
|
||||
|
||||
const expectedChildChildNavThree = app.getNavByIdOrName(childChildNavThree.id);
|
||||
expect(expectedChildChildNavThree).toEqual(childChildNavThree);
|
||||
});
|
||||
});
|
||||
|
||||
let app: App;
|
||||
let config: Config;
|
||||
let plt: MockPlatform;
|
||||
let portal: OverlayPortal;
|
||||
|
||||
beforeEach(() => {
|
||||
config = mockConfig();
|
||||
|
||||
@@ -492,7 +492,7 @@ $button-md-strong-font-weight: bold !default;
|
||||
}
|
||||
}
|
||||
|
||||
.md .button-effect {
|
||||
.md button .button-effect {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import { Checkbox } from '../checkbox';
|
||||
import { mockConfig, mockElementRef, mockRenderer, mockItem } from '../../../util/mock-providers';
|
||||
import { commonInputTest, BOOLEAN_CORPUS } from '../../../util/input-tester';
|
||||
import { mockConfig, mockElementRef, mockItem, mockRenderer } from '../../../util/mock-providers';
|
||||
import { BOOLEAN_CORPUS, commonInputTest } from '../../../util/input-tester';
|
||||
|
||||
describe('Checkbox', () => {
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ import { DomController } from '../../platform/dom-controller';
|
||||
import { Img } from '../img/img-interface';
|
||||
import { Ion } from '../ion';
|
||||
import { isTabs } from '../../navigation/nav-util';
|
||||
import { isTrueProperty, assert, removeArrayItem } from '../../util/util';
|
||||
import { assert, isTrueProperty, removeArrayItem } from '../../util/util';
|
||||
import { Keyboard } from '../../platform/keyboard';
|
||||
import { NavController } from '../../navigation/nav-controller';
|
||||
import { Content as IContent, Tabs } from '../../navigation/nav-interfaces';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { ScrollView, ScrollEvent } from '../../util/scroll-view';
|
||||
import { ScrollEvent, ScrollView } from '../../util/scroll-view';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
|
||||
export { ScrollEvent } from '../../util/scroll-view';
|
||||
@@ -31,7 +31,7 @@ export class EventEmitterProxy<T> extends EventEmitter<T> {
|
||||
* The Content component provides an easy to use content area with
|
||||
* some useful methods to control the scrollable area. There should
|
||||
* only be one content in a single view component. If additional scrollable
|
||||
* elements are need, use [ionScroll](../../scroll/Scroll).
|
||||
* elements are needed, use [ionScroll](../../scroll/Scroll).
|
||||
*
|
||||
*
|
||||
* The content area can also implement pull-to-refresh with the
|
||||
@@ -63,7 +63,7 @@ export class EventEmitterProxy<T> extends EventEmitter<T> {
|
||||
*
|
||||
* @advanced
|
||||
*
|
||||
* ### Sroll Events
|
||||
* ### Scroll 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
|
||||
@@ -167,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
|
||||
@@ -212,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;
|
||||
@@ -782,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;
|
||||
|
||||
@@ -8,8 +8,23 @@ import { PickerColumn } from '../picker/picker-options';
|
||||
import { Form } from '../../util/form';
|
||||
import { BaseInput } from '../../util/base-input';
|
||||
import { Item } from '../item/item';
|
||||
import { deepCopy, isBlank, isPresent, isArray, isObject, isString, assert, clamp } from '../../util/util';
|
||||
import { dateValueRange, renderDateTime, renderTextFormat, convertDataToISO, convertFormatToKey, getValueFromFormat, parseTemplate, parseDate, updateDate, DateTimeData, daysInMonth, dateSortValue, dateDataSortValue, LocaleData } from '../../util/datetime-util';
|
||||
import { assert, clamp, deepCopy, isArray, isBlank, isObject, isPresent, isString } from '../../util/util';
|
||||
import {
|
||||
DateTimeData,
|
||||
LocaleData,
|
||||
convertDataToISO,
|
||||
convertFormatToKey,
|
||||
dateDataSortValue,
|
||||
dateSortValue,
|
||||
dateValueRange,
|
||||
daysInMonth,
|
||||
getValueFromFormat,
|
||||
parseDate,
|
||||
parseTemplate,
|
||||
renderDateTime,
|
||||
renderTextFormat,
|
||||
updateDate,
|
||||
} from '../../util/datetime-util';
|
||||
|
||||
/**
|
||||
* @name DateTime
|
||||
@@ -120,6 +135,8 @@ import { dateValueRange, renderDateTime, renderTextFormat, convertDataToISO, con
|
||||
* to serialize and pass within JSON objects, and sending databases a standardized
|
||||
* format which it can be easily parsed if need be.
|
||||
*
|
||||
* To create an ISO datetime string for the current date and time, e.g. use `const currentDate = (new Date()).toISOString();`.
|
||||
*
|
||||
* An ISO format can be used as a simple year, or just the hour and minute, or get more
|
||||
* detailed down to the millisecond and timezone. Any of the ISO formats below can be used,
|
||||
* and after a user selects a new value, Ionic will continue to use the same ISO format
|
||||
@@ -152,7 +169,7 @@ import { dateValueRange, renderDateTime, renderTextFormat, convertDataToISO, con
|
||||
* ## Min and Max Datetimes
|
||||
*
|
||||
* Dates are infinite in either direction, so for a user's selection there should be at
|
||||
* least some form of restricting the dates that can be selected. Be default, the maximum
|
||||
* least some form of restricting the dates that can be selected. By default, the maximum
|
||||
* date is to the end of the current year, and the minimum date is from the beginning
|
||||
* of the year that was 100 years ago.
|
||||
*
|
||||
@@ -448,6 +465,7 @@ export class DateTime extends BaseInput<DateTimeData> implements AfterContentIni
|
||||
* @hidden
|
||||
*/
|
||||
_inputUpdated() {
|
||||
super._inputUpdated();
|
||||
this.updateText();
|
||||
}
|
||||
|
||||
@@ -475,10 +493,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();
|
||||
|
||||
@@ -90,7 +90,7 @@ describe('DateTime', () => {
|
||||
columns[0].selectedIndex = 1; // February
|
||||
datetime.validate();
|
||||
|
||||
for (var i = 0; i < 28; i++) {
|
||||
for (let i = 0; i < 28; i++) {
|
||||
expect(columns[1].options[i].disabled).toEqual(false);
|
||||
}
|
||||
expect(columns[1].options[28].disabled).toEqual(true);
|
||||
@@ -100,7 +100,7 @@ describe('DateTime', () => {
|
||||
columns[0].selectedIndex = 3; // April
|
||||
datetime.validate();
|
||||
|
||||
for (var i = 0; i < 30; i++) {
|
||||
for (let i = 0; i < 30; i++) {
|
||||
expect(columns[1].options[i].disabled).toEqual(false);
|
||||
}
|
||||
expect(columns[1].options[30].disabled).toEqual(true);
|
||||
@@ -130,7 +130,7 @@ describe('DateTime', () => {
|
||||
}
|
||||
|
||||
// // Days
|
||||
for (var i = 0; i < columns[1].options.length; i++) {
|
||||
for (let i = 0; i < columns[1].options.length; i++) {
|
||||
expect(columns[1].options[i].disabled).toEqual(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ContentChildren, QueryList, Directive, ElementRef, Renderer } from '@angular/core';
|
||||
import { ContentChildren, Directive, ElementRef, QueryList, Renderer } from '@angular/core';
|
||||
|
||||
import { Config } from '../../config/config';
|
||||
import { isTrueProperty } from '../../util/util';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, ChangeDetectionStrategy, ElementRef, Renderer, ViewEncapsulation } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, Renderer, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { Config } from '../../config/config';
|
||||
import { Ion } from '../ion';
|
||||
|
||||
@@ -6,4 +6,4 @@ export interface Img {
|
||||
canRequest: boolean;
|
||||
reset(): void;
|
||||
update(): void;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, ViewChild, NgModule } from '@angular/core';
|
||||
import { Component, NgModule, ViewChild } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule, InfiniteScroll, NavController } from '../../../..';
|
||||
import { InfiniteScroll, IonicApp, IonicModule, NavController } from '../../../..';
|
||||
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule, InfiniteScroll } from '../../../..';
|
||||
import { InfiniteScroll, IonicApp, IonicModule } from '../../../..';
|
||||
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -93,6 +93,8 @@ input.text-input:-webkit-autofill {
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.input[disabled] .input-cover {
|
||||
@@ -127,27 +129,6 @@ input.text-input:-webkit-autofill {
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
// --------------------------------------------------
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -0,0 +1,39 @@
|
||||
<ion-header>
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-title>Input attributes</ion-title>
|
||||
</ion-toolbar>
|
||||
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-label stacked>Stacked</ion-label>
|
||||
<ion-input #input1
|
||||
type="number"
|
||||
placeholder="Placeholder"
|
||||
value="1234"
|
||||
id="mystackinput"
|
||||
name="holaa"
|
||||
min="0"
|
||||
max="10000"
|
||||
step="2"
|
||||
autocomplete="on"
|
||||
autocorrect="on"
|
||||
autocapitalize="on"
|
||||
spellcheck="true"
|
||||
maxlength="4"
|
||||
disabled
|
||||
readonly
|
||||
></ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-list>
|
||||
<ion-item *ngIf="input1Valid" color="secondary">Test passed</ion-item>
|
||||
<ion-item *ngIf="!input1Valid" color="danger">Test FAILED</ion-item>
|
||||
</ion-list>
|
||||
|
||||
</ion-list>
|
||||
|
||||
</ion-content>
|
||||
@@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from '../../../../../..';
|
||||
|
||||
import { RootPage } from './root-page';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
RootPage,
|
||||
],
|
||||
imports: [
|
||||
IonicPageModule.forChild(RootPage)
|
||||
]
|
||||
})
|
||||
export class RootPageModule {}
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { TextInput } from '../../../../../../';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'root-page.html'
|
||||
})
|
||||
export class RootPage {
|
||||
|
||||
input1Valid: boolean;
|
||||
input2Valid: boolean;
|
||||
|
||||
@ViewChild('input1') input1: TextInput;
|
||||
|
||||
ionViewDidEnter() {
|
||||
this.input1Valid = this.checkInput1();
|
||||
}
|
||||
|
||||
checkInput1(): boolean {
|
||||
const nativeEle = <HTMLElement>this.input1._native.nativeElement;
|
||||
|
||||
return testAttributes(nativeEle, {
|
||||
id: null,
|
||||
type: 'number',
|
||||
placeholder: 'Placeholder',
|
||||
name: 'holaa',
|
||||
min: '0',
|
||||
max: '10000',
|
||||
step: '2',
|
||||
autocomplete: 'on',
|
||||
autocorrect: 'on',
|
||||
autocapitalize: 'on',
|
||||
spellcheck: 'true',
|
||||
maxLength: '4',
|
||||
'aria-labelledby': 'lbl-0',
|
||||
readOnly: true,
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function testAttributes(ele: HTMLElement, attributes: any): boolean {
|
||||
for (let attr in attributes) {
|
||||
const expected = attributes[attr];
|
||||
const value = (<any>ele)[attr];
|
||||
|
||||
if (expected === null) {
|
||||
if (ele.hasAttribute(attr) || value !== '') {
|
||||
console.error(`Element should NOT have "${attr}"`);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (expected !== value && expected !== ele.getAttribute(attr)) {
|
||||
console.error(`Value "${attr}" does not match: ${expected} != ${value}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ export class RootPage {
|
||||
}
|
||||
}
|
||||
|
||||
submit(ev: UIEvent, value?: any) {
|
||||
submit(_: UIEvent, value?: any) {
|
||||
console.log('Submitted', value);
|
||||
this.submitted = true;
|
||||
}
|
||||
|
||||
@@ -102,4 +102,16 @@
|
||||
</ion-list>
|
||||
</ion-card>
|
||||
</form>
|
||||
</ion-content>
|
||||
</ion-content>
|
||||
|
||||
<ion-footer>
|
||||
<ion-toolbar>
|
||||
<ion-input style="background: white;
|
||||
margin: 3px;
|
||||
padding: 0px 8px;
|
||||
border: 1px solid gray;
|
||||
border-radius: 5px;
|
||||
width: auto;
|
||||
transform: translateZ(0);" placeholder="chat here"></ion-input>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
@@ -38,7 +38,7 @@ export class RootPage {
|
||||
}
|
||||
}
|
||||
|
||||
submit(ev: UIEvent, value: any) {
|
||||
submit(_: UIEvent, value: any) {
|
||||
console.log('Submitted', value);
|
||||
this.submitted = true;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,38 @@
|
||||
import { getScrollData } from '../input';
|
||||
import { TextInput, getScrollData } from '../input';
|
||||
import { ContentDimensions } from '../../content/content';
|
||||
import { mockApp, mockConfig, mockDomController, mockElementRef, mockElementRefEle, mockForm, mockItem, mockPlatform, mockRenderer } from '../../../util/mock-providers';
|
||||
import { TEXT_CORPUS, commonInputTest } from '../../../util/input-tester';
|
||||
|
||||
|
||||
function newInput(): TextInput {
|
||||
const platform = mockPlatform();
|
||||
const config = mockConfig();
|
||||
const app = mockApp(config, platform);
|
||||
const elementRef = mockElementRef();
|
||||
const renderer = mockRenderer();
|
||||
const item: any = mockItem();
|
||||
const form = mockForm();
|
||||
const dom = mockDomController(platform);
|
||||
const input = new TextInput(config, platform, form, app, elementRef, renderer, null, item, null, dom);
|
||||
input._native = mockElementRefEle(document.createElement('input'));
|
||||
return input;
|
||||
}
|
||||
|
||||
describe('text input', () => {
|
||||
|
||||
it('should pass common test', () => {
|
||||
const textInput = newInput();
|
||||
const ele = textInput._native.nativeElement;
|
||||
textInput._item._elementRef = mockElementRefEle(document.createElement('div'));
|
||||
commonInputTest(textInput, {
|
||||
defaultValue: '',
|
||||
corpus: TEXT_CORPUS,
|
||||
onValueChange: (value) => ele.value === value,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('getScrollData', () => {
|
||||
|
||||
it('should scroll, top and bottom below safe area, no room to scroll', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ElementRef, Renderer, Input } from '@angular/core';
|
||||
import { ElementRef, Input, Renderer } from '@angular/core';
|
||||
|
||||
import { Config } from '../config/config';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { indexForItem, findReorderItem } from './item-reorder-util';
|
||||
import { findReorderItem, indexForItem } from './item-reorder-util';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { PointerCoordinates, pointerCoord } from '../../util/dom';
|
||||
import { UIEventManager } from '../../gestures/ui-event-manager';
|
||||
@@ -46,7 +46,7 @@ export class ItemReorderGesture {
|
||||
}
|
||||
this.reorderList._reorderPrepare();
|
||||
|
||||
let item = reorderMark.getReorderNode();
|
||||
const item = reorderMark.getReorderNode();
|
||||
if (!item) {
|
||||
console.error('reorder node not found');
|
||||
return false;
|
||||
@@ -71,26 +71,26 @@ export class ItemReorderGesture {
|
||||
}
|
||||
|
||||
private onDragMove(ev: any) {
|
||||
let selectedItem = this.selectedItemEle;
|
||||
const selectedItem = this.selectedItemEle;
|
||||
if (!selectedItem) {
|
||||
return;
|
||||
}
|
||||
ev.preventDefault();
|
||||
|
||||
// Get coordinate
|
||||
let coord = pointerCoord(ev);
|
||||
let posY = coord.y;
|
||||
const coord = pointerCoord(ev);
|
||||
const posY = coord.y;
|
||||
|
||||
// Scroll if we reach the scroll margins
|
||||
let scrollPosition = this.scroll(posY);
|
||||
const scrollPosition = this.scroll(posY);
|
||||
|
||||
// Only perform hit test if we moved at least 30px from previous position
|
||||
if (Math.abs(posY - this.lastYcoord) > 30) {
|
||||
let overItem = this.itemForCoord(coord);
|
||||
var overItem = this.itemForCoord(coord);
|
||||
if (overItem) {
|
||||
let toIndex = indexForItem(overItem);
|
||||
var toIndex = indexForItem(overItem);
|
||||
if (toIndex !== undefined && (toIndex !== this.lastToIndex || this.emptyZone)) {
|
||||
let fromIndex = indexForItem(selectedItem);
|
||||
var fromIndex = indexForItem(selectedItem);
|
||||
this.lastToIndex = toIndex;
|
||||
this.lastYcoord = posY;
|
||||
this.emptyZone = false;
|
||||
@@ -102,12 +102,12 @@ export class ItemReorderGesture {
|
||||
}
|
||||
|
||||
// Update selected item position
|
||||
let ydiff = Math.round(posY - this.offset.y + scrollPosition);
|
||||
const ydiff = Math.round(posY - this.offset.y + scrollPosition);
|
||||
(<any>selectedItem.style)[this.plt.Css.transform] = `translateY(${ydiff}px)`;
|
||||
}
|
||||
|
||||
private onDragEnd(ev: any) {
|
||||
let selectedItem = this.selectedItemEle;
|
||||
const selectedItem = this.selectedItemEle;
|
||||
if (!selectedItem) {
|
||||
return;
|
||||
}
|
||||
@@ -116,9 +116,9 @@ export class ItemReorderGesture {
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
let toIndex = this.lastToIndex;
|
||||
let fromIndex = indexForItem(selectedItem);
|
||||
let reorderInactive = () => {
|
||||
const toIndex = this.lastToIndex;
|
||||
const fromIndex = indexForItem(selectedItem);
|
||||
const reorderInactive = () => {
|
||||
this.selectedItemEle.style.transition = '';
|
||||
this.selectedItemEle.classList.remove(ITEM_REORDER_ACTIVE);
|
||||
this.selectedItemEle = null;
|
||||
@@ -134,7 +134,7 @@ export class ItemReorderGesture {
|
||||
}
|
||||
|
||||
private itemForCoord(coord: PointerCoordinates): HTMLElement {
|
||||
const sideOffset = this.plt.isRTL ? 100 : -100;
|
||||
const sideOffset = this.reorderList._isStart === this.plt.isRTL ? -100 : 100;
|
||||
const x = this.offset.x + sideOffset;
|
||||
const y = coord.y;
|
||||
const element = this.plt.getElementFromPoint(x, y);
|
||||
@@ -167,6 +167,7 @@ const SCROLL_JUMP = 10;
|
||||
const ITEM_REORDER_ACTIVE = 'reorder-active';
|
||||
|
||||
export interface ItemReorderGestureDelegate {
|
||||
_isStart: boolean;
|
||||
getNativeElement: () => any;
|
||||
_reorderPrepare: () => void;
|
||||
_scrollContent: (scrollPosition: number) => number;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
@import "../../themes/ionic.globals";
|
||||
|
||||
$reorder-initial-transform: 160% !default;
|
||||
|
||||
// Item reorder
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-reorder {
|
||||
@include transform(translate3d(160%, 0, 0));
|
||||
@include transform(translate3d($reorder-initial-transform, 0, 0));
|
||||
|
||||
display: none;
|
||||
|
||||
@@ -18,13 +20,18 @@ ion-reorder {
|
||||
font-size: 1.7em;
|
||||
opacity: .25;
|
||||
|
||||
|
||||
transition: transform 140ms ease-in;
|
||||
|
||||
pointer-events: all;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.reorder-side-start ion-reorder {
|
||||
@include transform(translate3d(-$reorder-initial-transform, 0, 0));
|
||||
|
||||
order: -1;
|
||||
}
|
||||
|
||||
ion-reorder ion-icon {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Directive, ElementRef, EventEmitter, Input, NgZone, Renderer, Optional, Output } from '@angular/core';
|
||||
import { Directive, ElementRef, EventEmitter, Input, NgZone, Optional, Output, Renderer } from '@angular/core';
|
||||
|
||||
import { Content } from '../content/content';
|
||||
import { DomController } from '../../platform/dom-controller';
|
||||
import { isTrueProperty, reorderArray } from '../../util/util';
|
||||
import { ItemReorderGestureDelegate, ItemReorderGesture } from './item-reorder-gesture';
|
||||
import { ItemReorderGesture, ItemReorderGestureDelegate } from './item-reorder-gesture';
|
||||
import { Platform } from '../../platform/platform';
|
||||
|
||||
|
||||
@@ -142,12 +142,14 @@ export class ReorderIndexes {
|
||||
host: {
|
||||
'[class.reorder-enabled]': '_enableReorder',
|
||||
'[class.reorder-visible]': '_visibleReorder',
|
||||
'[class.reorder-side-start]': '_isStart'
|
||||
}
|
||||
})
|
||||
export class ItemReorder implements ItemReorderGestureDelegate {
|
||||
|
||||
_enableReorder: boolean = false;
|
||||
_visibleReorder: boolean = false;
|
||||
_isStart: boolean = false;
|
||||
_reorderGesture: ItemReorderGesture;
|
||||
_lastToIndex: number = -1;
|
||||
_element: HTMLElement;
|
||||
@@ -158,6 +160,14 @@ export class ItemReorder implements ItemReorderGestureDelegate {
|
||||
*/
|
||||
@Output() ionItemReorder: EventEmitter<ReorderIndexes> = new EventEmitter<ReorderIndexes>();
|
||||
|
||||
/**
|
||||
* @input {string} Which side of the view the ion-reorder should be placed. Default `"end"`.
|
||||
*/
|
||||
@Input('side')
|
||||
set side(side: 'start' | 'end') {
|
||||
this._isStart = side === 'start';
|
||||
}
|
||||
|
||||
constructor(
|
||||
private _plt: Platform,
|
||||
private _dom: DomController,
|
||||
@@ -268,7 +278,7 @@ export class ItemReorder implements ItemReorderGestureDelegate {
|
||||
/********* DOM WRITE ********* */
|
||||
let transform = this._plt.Css.transform;
|
||||
if (toIndex >= lastToIndex) {
|
||||
for (var i = lastToIndex; i <= toIndex; i++) {
|
||||
for (let i = lastToIndex; i <= toIndex; i++) {
|
||||
if (i !== fromIndex) {
|
||||
(<any>children[i]).style[transform] = (i > fromIndex)
|
||||
? `translateY(${-itemHeight}px)` : '';
|
||||
@@ -277,7 +287,7 @@ export class ItemReorder implements ItemReorderGestureDelegate {
|
||||
}
|
||||
|
||||
if (toIndex <= lastToIndex) {
|
||||
for (var i = toIndex; i <= lastToIndex; i++) {
|
||||
for (let i = toIndex; i <= lastToIndex; i++) {
|
||||
if (i !== fromIndex) {
|
||||
(<any>children[i]).style[transform] = (i < fromIndex)
|
||||
? `translateY(${itemHeight}px)` : '';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ItemSliding } from './item-sliding';
|
||||
import { List } from '../list/list';
|
||||
import { DomController } from '../../platform/dom-controller';
|
||||
import { GestureController, GESTURE_PRIORITY_SLIDING_ITEM, GESTURE_ITEM_SWIPE } from '../../gestures/gesture-controller';
|
||||
import { GESTURE_ITEM_SWIPE, GESTURE_PRIORITY_SLIDING_ITEM, GestureController } from '../../gestures/gesture-controller';
|
||||
import { PanGesture } from '../../gestures/pan-gesture';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { pointerCoord } from '../../util/dom';
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
import { ChangeDetectionStrategy, Component, ContentChildren, ContentChild, ElementRef, EventEmitter, forwardRef, Optional, Output, QueryList, Renderer, ViewEncapsulation, NgZone } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ContentChild,
|
||||
ContentChildren,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
NgZone,
|
||||
Optional,
|
||||
Output,
|
||||
QueryList,
|
||||
Renderer,
|
||||
ViewEncapsulation,
|
||||
forwardRef } from '@angular/core';
|
||||
|
||||
import { swipeShouldReset, assert } from '../../util/util';
|
||||
import { assert, swipeShouldReset } from '../../util/util';
|
||||
import { Item } from './item';
|
||||
import { List } from '../list/list';
|
||||
import { Platform } from '../../platform/platform';
|
||||
@@ -266,11 +279,11 @@ export class ItemSliding {
|
||||
}
|
||||
|
||||
if (openAmount > this._optsWidthRightSide) {
|
||||
var optsWidth = this._optsWidthRightSide;
|
||||
const optsWidth = this._optsWidthRightSide;
|
||||
openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
|
||||
|
||||
} else if (openAmount < -this._optsWidthLeftSide) {
|
||||
var optsWidth = -this._optsWidthLeftSide;
|
||||
const optsWidth = -this._optsWidthLeftSide;
|
||||
openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
|
||||
}
|
||||
|
||||
@@ -296,8 +309,8 @@ export class ItemSliding {
|
||||
restingPoint = 0;
|
||||
}
|
||||
|
||||
this._setOpenAmount(restingPoint, true);
|
||||
this.fireSwipeEvent();
|
||||
this._setOpenAmount(restingPoint, true);
|
||||
return restingPoint;
|
||||
}
|
||||
|
||||
@@ -344,24 +357,24 @@ export class ItemSliding {
|
||||
|
||||
if (isFinal) {
|
||||
this.item.setElementStyle(platform.Css.transition, '');
|
||||
}
|
||||
|
||||
if (openAmount > 0) {
|
||||
var state = (openAmount >= (this._optsWidthRightSide + SWIPE_MARGIN))
|
||||
? SlidingState.Right | SlidingState.SwipeRight
|
||||
: SlidingState.Right;
|
||||
|
||||
this._setState(state);
|
||||
|
||||
} else if (openAmount < 0) {
|
||||
const state = (openAmount <= (-this._optsWidthLeftSide - SWIPE_MARGIN))
|
||||
? SlidingState.Left | SlidingState.SwipeLeft
|
||||
: SlidingState.Left;
|
||||
|
||||
this._setState(state);
|
||||
|
||||
} else {
|
||||
if (openAmount > 0) {
|
||||
var state = (openAmount >= (this._optsWidthRightSide + SWIPE_MARGIN))
|
||||
? SlidingState.Right | SlidingState.SwipeRight
|
||||
: SlidingState.Right;
|
||||
|
||||
this._setState(state);
|
||||
|
||||
} else if (openAmount < 0) {
|
||||
var state = (openAmount <= (-this._optsWidthLeftSide - SWIPE_MARGIN))
|
||||
? SlidingState.Left | SlidingState.SwipeLeft
|
||||
: SlidingState.Left;
|
||||
|
||||
this._setState(state);
|
||||
}
|
||||
}
|
||||
if (openAmount === 0) {
|
||||
assert(openAmount === 0, 'bad internal state');
|
||||
this._tmr = platform.timeout(() => {
|
||||
this._setState(SlidingState.Disabled);
|
||||
this._tmr = null;
|
||||
@@ -371,7 +384,7 @@ export class ItemSliding {
|
||||
}
|
||||
|
||||
this.item.setElementStyle(platform.Css.transform, `translate3d(${-openAmount}px,0,0)`);
|
||||
let ionDrag = this.ionDrag;
|
||||
const ionDrag = this.ionDrag;
|
||||
if (ionDrag.observers.length > 0) {
|
||||
ionDrag.emit(this);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, ContentChild, ContentChildren, ElementRef, QueryList, Renderer, Optional, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ContentChild, ContentChildren, ElementRef, Optional, QueryList, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { Button } from '../button/button';
|
||||
import { Config } from '../../config/config';
|
||||
@@ -323,6 +323,7 @@ export class Item extends Ion {
|
||||
this._setName(elementRef);
|
||||
this._hasReorder = !!reorder;
|
||||
this.id = form.nextId().toString();
|
||||
this.labelId = 'lbl-' + this.id;
|
||||
|
||||
// auto add "tappable" attribute to ion-item components that have a click listener
|
||||
if (!(<any>renderer).orgListen) {
|
||||
@@ -391,7 +392,7 @@ export class Item extends Ion {
|
||||
set contentLabel(label: Label) {
|
||||
if (label) {
|
||||
this._label = label;
|
||||
this.labelId = label.id = ('lbl-' + this.id);
|
||||
label.id = this.labelId;
|
||||
if (label.type) {
|
||||
this.setElementClass('item-label-' + label.type, true);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export class SessionList {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const data = [
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
</button>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>DateTime</ion-label>
|
||||
<ion-label floating>DateTime</ion-label>
|
||||
<ion-datetime [(ngModel)]="datetime" min="1994-03-14" max="2017-12-09" displayFormat="MM/DD/YYYY" required [disabled]='disabled'></ion-datetime>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Select</ion-label>
|
||||
<ion-label floating>Select</ion-label>
|
||||
<ion-select [(ngModel)]="select" [disabled]='strDisabled()'>
|
||||
<ion-option value="">No Game Console</ion-option>
|
||||
<ion-option value="nes">NES</ion-option>
|
||||
<ion-option value="n64">Nintendo64</ion-option>
|
||||
<ion-option value="ps">PlayStation</ion-option>
|
||||
@@ -42,7 +43,7 @@
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Input (text)</ion-label>
|
||||
<ion-label floating>Input (text)</ion-label>
|
||||
<ion-input [(ngModel)]="text" [disabled]='disabled'></ion-input>
|
||||
</ion-item>
|
||||
|
||||
|
||||
@@ -13,24 +13,30 @@
|
||||
|
||||
<ion-list [reorder]="isReordering" (ionItemReorder)="reorder($event)">
|
||||
<button ion-item *ngFor="let item of items" (click)="clickedButton(item)"
|
||||
[style.background]="'rgb('+(255-item*4)+','+(255-item*4)+','+(255-item*4)+')'"
|
||||
[style.min-height]="item*2+35+'px'">
|
||||
[style.background]="'rgb('+(255-item*4)+','+(255-item*4)+','+(255-item*4)+')'"
|
||||
[style.min-height]="item*2+35+'px'">
|
||||
{{item}}
|
||||
</button>
|
||||
</ion-list>
|
||||
|
||||
<ion-list [reorder]="isReordering" (ionItemReorder)="$event.applyTo(items)">
|
||||
<ion-item-sliding *ngFor="let item of items">
|
||||
<button ion-item (click)="clickedButton(item)">
|
||||
<h2>Sliding item {{item}}</h2>
|
||||
</button>
|
||||
<ion-item-options side="right" icon-start>
|
||||
<button ion-button color='danger'>
|
||||
<ion-icon name="trash"></ion-icon>
|
||||
Remove
|
||||
</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
</ion-list>
|
||||
<div *ngFor="let side of ['start', 'end']">
|
||||
<ion-list>
|
||||
<ion-list-header>{{side}}</ion-list-header>
|
||||
<ion-item-group [reorder]="isReordering" (ionItemReorder)="$event.applyTo(items)" [side]="side">
|
||||
<ion-item-sliding *ngFor="let item of items">
|
||||
<button ion-item (click)="clickedButton(item)">
|
||||
<h2>Sliding item {{item}}</h2>
|
||||
<div item-end>right</div>
|
||||
</button>
|
||||
<ion-item-options side="right" icon-start>
|
||||
<button ion-button color='danger'>
|
||||
<ion-icon name="trash"></ion-icon>
|
||||
Remove
|
||||
</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
</ion-item-group>
|
||||
</ion-list>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
|
||||
@@ -9,7 +9,7 @@ export class RootPage {
|
||||
isReordering: boolean = false;
|
||||
|
||||
constructor() {
|
||||
let nu = 9;
|
||||
let nu = 5;
|
||||
for (let i = 0; i < nu; i++) {
|
||||
this.items.push(i);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { AlertController, List, ItemSliding, ToastController } from '../../../../../../';
|
||||
import { AlertController, ItemSliding, List, ToastController } from '../../../../../../';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'root-page.html'
|
||||
@@ -52,7 +52,7 @@ export class RootPage {
|
||||
console.log('UNREAD', item);
|
||||
}
|
||||
|
||||
didClick(item: ItemSliding) {
|
||||
didClick(_: ItemSliding) {
|
||||
console.log('Clicked, ion-item');
|
||||
|
||||
let alert = this.alertCtrl.create({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Attribute, Directive, ElementRef, Renderer, Input } from '@angular/core';
|
||||
import { Attribute, Directive, ElementRef, Input, Renderer } from '@angular/core';
|
||||
|
||||
import { Config } from '../../config/config';
|
||||
import { Ion } from '../ion';
|
||||
|
||||
@@ -87,14 +87,14 @@ $list-md-header-color: #757575 !default;
|
||||
}
|
||||
|
||||
.list-md ion-item-options .button {
|
||||
@include margin(1px, 0);
|
||||
@include margin(0);
|
||||
@include border-radius(0);
|
||||
|
||||
display: inline-flex;
|
||||
|
||||
align-items: center;
|
||||
|
||||
height: calc(100% - 2px);
|
||||
height: 100%;
|
||||
|
||||
border: 0;
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { Component, ElementRef, HostListener, Renderer, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { Config } from '../../config/config';
|
||||
import { GestureController, BlockerDelegate, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
import { isDefined, isUndefined, assert } from '../../util/util';
|
||||
import { BLOCK_ALL, BlockerDelegate, GestureController } from '../../gestures/gesture-controller';
|
||||
import { assert, isDefined, isUndefined } from '../../util/util';
|
||||
import { KEY_ESCAPE } from '../../platform/key';
|
||||
import { LoadingOptions } from './loading-options';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
|
||||
/**
|
||||
@@ -37,8 +36,7 @@ export class LoadingCmp {
|
||||
constructor(
|
||||
private _viewCtrl: ViewController,
|
||||
private _config: Config,
|
||||
private _plt: Platform,
|
||||
private _elementRef: ElementRef,
|
||||
_elementRef: ElementRef,
|
||||
gestureCtrl: GestureController,
|
||||
params: NavParams,
|
||||
renderer: Renderer
|
||||
@@ -79,8 +77,6 @@ export class LoadingCmp {
|
||||
}
|
||||
|
||||
ionViewDidEnter() {
|
||||
this._plt.focusOutActiveElement();
|
||||
|
||||
// If there is a duration, dismiss after that amount of time
|
||||
if ( this.d && this.d.duration ) {
|
||||
this.durationTimeout = setTimeout(() => this.dismiss('backdrop'), this.d.duration);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { isPresent } from '../../util/util';
|
||||
import { PORTAL_LOADING } from '../app/app-constants';
|
||||
import { LoadingCmp } from './loading-component';
|
||||
import { LoadingOptions } from './loading-options';
|
||||
import { LoadingPopIn, LoadingPopOut, LoadingMdPopIn, LoadingMdPopOut, LoadingWpPopIn, LoadingWpPopOut } from './loading-transitions';
|
||||
import { LoadingMdPopIn, LoadingMdPopOut, LoadingPopIn, LoadingPopOut, LoadingWpPopIn, LoadingWpPopOut } from './loading-transitions';
|
||||
import { NavOptions } from '../../navigation/nav-util';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@ export class AppComponent {
|
||||
root = PageOne;
|
||||
|
||||
constructor(app: App) {
|
||||
app.viewDidLeave.subscribe((ev: any) => {
|
||||
app.viewDidLeave.subscribe((_: any) => {
|
||||
console.log('App didLeave');
|
||||
});
|
||||
|
||||
app.viewWillLeave.subscribe((ev: any) => {
|
||||
app.viewWillLeave.subscribe((_: any) => {
|
||||
console.log('App willLeave');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Menu } from './menu';
|
||||
import { DomController } from '../../platform/dom-controller';
|
||||
import { GestureController, GESTURE_PRIORITY_MENU_SWIPE, GESTURE_MENU_SWIPE } from '../../gestures/gesture-controller';
|
||||
import { GESTURE_MENU_SWIPE, GESTURE_PRIORITY_MENU_SWIPE, GestureController } from '../../gestures/gesture-controller';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { SlideEdgeGesture } from '../../gestures/slide-edge-gesture';
|
||||
import { SlideData } from '../../gestures/slide-gesture';
|
||||
@@ -46,7 +46,7 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
}
|
||||
|
||||
// Set CSS, then wait one frame for it to apply before sliding starts
|
||||
onSlideBeforeStart(ev: any) {
|
||||
onSlideBeforeStart() {
|
||||
console.debug('menu gesture, onSlideBeforeStart', this.menu.side);
|
||||
this.menu._swipeBeforeStart();
|
||||
}
|
||||
@@ -56,14 +56,14 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
this.menu._swipeStart();
|
||||
}
|
||||
|
||||
onSlide(slide: SlideData, ev: any) {
|
||||
onSlide(slide: SlideData) {
|
||||
const z = (this.menu.isRightSide !== this.plt.isRTL ? slide.min : slide.max);
|
||||
const stepValue = (slide.distance / z);
|
||||
|
||||
this.menu._swipeProgress(stepValue);
|
||||
}
|
||||
|
||||
onSlideEnd(slide: SlideData, ev: any) {
|
||||
onSlideEnd(slide: SlideData) {
|
||||
let z = (this.menu.isRightSide !== this.plt.isRTL ? slide.min : slide.max);
|
||||
const currentStepValue = (slide.distance / z);
|
||||
const velocity = slide.velocity;
|
||||
@@ -87,7 +87,7 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
this.menu._swipeEnd(shouldCompleteLeft, shouldCompleteRight, currentStepValue, velocity);
|
||||
}
|
||||
|
||||
getElementStartPos(slide: SlideData, ev: any) {
|
||||
getElementStartPos(slide: SlideData) {
|
||||
const menu = this.menu;
|
||||
if (menu.isRightSide !== this.plt.isRTL) {
|
||||
return menu.isOpen ? slide.min : slide.max;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, Input, HostListener, Optional } from '@angular/core';
|
||||
import { Directive, HostListener, Input, Optional } from '@angular/core';
|
||||
|
||||
import { Button } from '../button/button';
|
||||
import { MenuController } from '../app/menu-controller';
|
||||
@@ -111,7 +111,7 @@ export class MenuToggle {
|
||||
private _menu: MenuController,
|
||||
@Optional() private _viewCtrl: ViewController,
|
||||
@Optional() private _button: Button,
|
||||
@Optional() private _navbar: Navbar
|
||||
@Optional() _navbar: Navbar
|
||||
) {
|
||||
this._isButton = !!_button;
|
||||
this._inNavbar = !!_navbar;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { OnInit, OnDestroy, ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, forwardRef, Input, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, Renderer, ViewChild, ViewEncapsulation, forwardRef } from '@angular/core';
|
||||
|
||||
import { App } from '../app/app';
|
||||
import { Backdrop } from '../backdrop/backdrop';
|
||||
import { Config } from '../../config/config';
|
||||
import { Content } from '../content/content';
|
||||
import { DomController } from '../../platform/dom-controller';
|
||||
import { GestureController, GESTURE_GO_BACK_SWIPE, BlockerDelegate } from '../../gestures/gesture-controller';
|
||||
import { isTrueProperty, Side, isRightSide, assert } from '../../util/util';
|
||||
import { BlockerDelegate, GESTURE_GO_BACK_SWIPE, GestureController, } from '../../gestures/gesture-controller';
|
||||
import { Side, assert, isRightSide, isTrueProperty } from '../../util/util';
|
||||
import { Keyboard } from '../../platform/keyboard';
|
||||
import { MenuContentGesture } from './menu-gestures';
|
||||
import { Menu as MenuInterface } from '../app/menu-interface';
|
||||
@@ -25,7 +25,7 @@ import { RootNode } from '../split-pane/split-pane';
|
||||
* will be displayed differently based on the mode, however the display type can be changed
|
||||
* to any of the available [menu types](#menu-types). The menu element should be a sibling
|
||||
* to the app's content element. There can be any number of menus attached to the content.
|
||||
* These can be controlled from the templates, or programmatically using the [MenuController](../app/MenuController).
|
||||
* These can be controlled from the templates, or programmatically using the [MenuController](../../app/MenuController).
|
||||
*
|
||||
* @usage
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, ViewChild, NgModule } from '@angular/core';
|
||||
import { Component, NgModule, ViewChild } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule, App, MenuController, Nav } from '../../../..';
|
||||
import { App, IonicApp, IonicModule, MenuController, Nav } from '../../../..';
|
||||
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, ViewChild, NgModule } from '@angular/core';
|
||||
import { Component, NgModule, ViewChild } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule, Nav, AlertController } from '../../../..';
|
||||
import { AlertController, IonicApp, IonicModule, Nav } from '../../../..';
|
||||
|
||||
|
||||
@Component({templateUrl: 'page1.html'})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, ViewChild, NgModule } from '@angular/core';
|
||||
import { Component, NgModule, ViewChild } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule, Nav, AlertController } from '../../../..';
|
||||
import { AlertController, IonicApp, IonicModule, Nav } from '../../../..';
|
||||
|
||||
|
||||
@Component({templateUrl: 'page1.html'})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, ViewChild, NgModule } from '@angular/core';
|
||||
import { Component, NgModule, ViewChild } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule, Nav } from '../../../..';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { KEY_ESCAPE } from '../../platform/key';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { NavOptions } from '../../navigation/nav-util';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
import { GestureController, BlockerDelegate, GESTURE_MENU_SWIPE, GESTURE_GO_BACK_SWIPE } from '../../gestures/gesture-controller';
|
||||
import { BlockerDelegate, GESTURE_GO_BACK_SWIPE, GESTURE_MENU_SWIPE, GestureController } from '../../gestures/gesture-controller';
|
||||
import { ModuleLoader } from '../../util/module-loader';
|
||||
import { assert } from '../../util/util';
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { DeepLinker } from '../../navigation/deep-linker';
|
||||
*
|
||||
* When a modal (or any other overlay such as an alert or actionsheet) is
|
||||
* "presented" to a nav controller, the overlay is added to the app's root nav.
|
||||
* After the modal has been presented, from within the component instance The
|
||||
* After the modal has been presented, from within the component instance, the
|
||||
* modal can later be closed or "dismissed" by using the ViewController's
|
||||
* `dismiss` method. Additionally, you can dismiss any overlay by using `pop`
|
||||
* on the root nav controller. Modals are not reusable. When a modal is dismissed
|
||||
@@ -112,6 +112,25 @@ import { DeepLinker } from '../../navigation/deep-linker';
|
||||
*
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* A common issue is that a developer may try to implement navigation in a modal, but when you try NavController.push(),
|
||||
* you will notice that the status bar on iOS gets cut off. The proper way to implement navigation in a modal is to
|
||||
* make the modal component a navigation container, and set the root page to the page you want to show in your modal.
|
||||
*
|
||||
* ```ts
|
||||
* @Component({
|
||||
* template: '<ion-nav [root]="rootPage" [rootParams]="rootParams"></ion-nav>'
|
||||
* })
|
||||
* export class MyModalWrapper {
|
||||
* rootPage = 'MyModalContentPage'; // This is the page you want your modal to display
|
||||
* rootParams;
|
||||
*
|
||||
* constructor(navParams: NavParams, private viewCtrl: ViewController) {
|
||||
* this.rootParams = Object.assign({}, navParams.data, {viewCtrl: viewCtrl});
|
||||
* // This line will send the view controller into your child views, so you can dismiss the modals from there.
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @demo /docs/demos/src/modal/
|
||||
* @see {@link /docs/components#modals Modal Component Docs}
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@ import { isPresent } from '../../util/util';
|
||||
import { PORTAL_MODAL } from '../app/app-constants';
|
||||
import { ModalCmp } from './modal-component';
|
||||
import { ModalOptions } from './modal-options';
|
||||
import { ModalSlideIn, ModalSlideOut, ModalMDSlideIn, ModalMDSlideOut } from './modal-transitions';
|
||||
import { ModalMDSlideIn, ModalMDSlideOut, ModalSlideIn, ModalSlideOut } from './modal-transitions';
|
||||
import { NavOptions } from '../../navigation/nav-util';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicModule, IonicApp } from '../../../../..';
|
||||
import { IonicApp, IonicModule } from '../../../../..';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { PageOneModule } from '../pages/page-one/page-one.module';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Config, IonicPage, NavController, ModalController, ToastController, Platform } from '../../../../../..';
|
||||
import { Config, IonicPage, ModalController, NavController, Platform, ToastController } from '../../../../../..';
|
||||
|
||||
@IonicPage()
|
||||
@Component({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { App, ActionSheetController, AlertController, IonicPage, ModalController, NavController, ToastController } from '../../../../../..';
|
||||
import { ActionSheetController, AlertController, App, IonicPage, ModalController, NavController, ToastController } from '../../../../../..';
|
||||
|
||||
@IonicPage()
|
||||
@Component({
|
||||
|
||||
@@ -32,8 +32,8 @@ import { Page } from '../../navigation/nav-util';
|
||||
* template: `<button ion-button [navPush]="pushPage" [navParams]="params">Go</button>`
|
||||
* })
|
||||
* class MyPage {
|
||||
* params: Object;
|
||||
* pushPage: any;
|
||||
* params: Object;
|
||||
* constructor(){
|
||||
* this.pushPage = LoginPage;
|
||||
* this.params = { id: 42 };
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { AfterViewInit, Component, ComponentFactoryResolver, ElementRef, ErrorHandler, forwardRef, Input, Optional, NgZone, Renderer, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
|
||||
import { AfterViewInit, Component, ComponentFactoryResolver, ElementRef, ErrorHandler, Input, NgZone, Optional, Renderer, ViewChild, ViewContainerRef, ViewEncapsulation, forwardRef } from '@angular/core';
|
||||
|
||||
import { App } from '../app/app';
|
||||
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 { Nav as INav } from '../../navigation/nav-interfaces';
|
||||
import { NavController } from '../../navigation/nav-controller';
|
||||
import { NavControllerBase } from '../../navigation/nav-controller-base';
|
||||
@@ -66,7 +65,6 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode, I
|
||||
app: App,
|
||||
config: Config,
|
||||
plt: Platform,
|
||||
keyboard: Keyboard,
|
||||
elementRef: ElementRef,
|
||||
zone: NgZone,
|
||||
renderer: Renderer,
|
||||
@@ -77,7 +75,7 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode, I
|
||||
domCtrl: DomController,
|
||||
errHandler: ErrorHandler
|
||||
) {
|
||||
super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl, errHandler);
|
||||
super(parent, app, config, plt, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl, errHandler);
|
||||
|
||||
if (viewCtrl) {
|
||||
// an ion-nav can also act as an ion-page within a parent ion-nav
|
||||
@@ -94,10 +92,10 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode, I
|
||||
this.parent = viewCtrl.getNav();
|
||||
this.parent.registerChildNav(this);
|
||||
|
||||
} else if (app && !app.getRootNav()) {
|
||||
} else if (app && !app.getRootNavById(this.id)) {
|
||||
// a root nav has not been registered yet with the app
|
||||
// this is the root navcontroller for the entire app
|
||||
app._setRootNav(this);
|
||||
app.registerRootNav(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,25 +110,22 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode, I
|
||||
ngAfterViewInit() {
|
||||
this._hasInit = true;
|
||||
|
||||
let navSegment = this._linker.initNav(this);
|
||||
if (navSegment && (navSegment.component || navSegment.loadChildren)) {
|
||||
// there is a segment match in the linker
|
||||
return this._linker.initViews(navSegment).then(views => {
|
||||
this.setPages(views, null, null);
|
||||
});
|
||||
const segment = this._linker.getSegmentByNavIdOrName(this.id, this.name);
|
||||
|
||||
if (segment && (segment.component || segment.loadChildren)) {
|
||||
return this._linker.initViews(segment).then(views => {
|
||||
return this.setPages(views, null, null);
|
||||
});
|
||||
} else if (this._root) {
|
||||
// no segment match, so use the root property
|
||||
// no segment match, so use the root property but don't set the url I guess
|
||||
const setUrl = segment ? false : true;
|
||||
return this.push(this._root, this.rootParams, {
|
||||
isNavRoot: (<any>this._app.getRootNav() === this)
|
||||
isNavRoot: (<any>this._app.getRootNavById(this.id) === this),
|
||||
updateUrl: setUrl
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
goToRoot(opts: NavOptions) {
|
||||
return this.setRoot(this._root, this.rootParams, opts, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @input {Page} The Page component to load as the root page within this nav.
|
||||
*/
|
||||
@@ -138,6 +133,7 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode, I
|
||||
get root(): any {
|
||||
return this._root;
|
||||
}
|
||||
|
||||
set root(page: any) {
|
||||
this._root = page;
|
||||
|
||||
@@ -151,6 +147,11 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode, I
|
||||
*/
|
||||
@Input() rootParams: any;
|
||||
|
||||
/**
|
||||
* @input {string} a unique name for the nav element
|
||||
*/
|
||||
@Input() name: string;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
@@ -169,4 +170,21 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode, I
|
||||
}
|
||||
}
|
||||
|
||||
goToRoot(opts: NavOptions) {
|
||||
return this.setRoot(this._root, this.rootParams, opts, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* @private
|
||||
*/
|
||||
getType() {
|
||||
return 'nav';
|
||||
}
|
||||
|
||||
/*
|
||||
* @private
|
||||
*/
|
||||
getSecondaryIdentifier(): string {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<ion-split-pane>
|
||||
<ion-nav [root]="rootOne" name="left"></ion-nav>
|
||||
<ion-nav [root]="rootTwo" main #content name="right"></ion-nav>
|
||||
|
||||
</ion-split-pane>
|
||||
`
|
||||
})
|
||||
export class AppComponent {
|
||||
rootOne = 'NestedNavOnePageTwo';
|
||||
rootTwo = 'NestedNavTwoPageTwo';
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule } from '../../../../..';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
IonicModule.forRoot(AppComponent, { swipeBackEnabled: true, preloadModules: true }),
|
||||
],
|
||||
bootstrap: [IonicApp]
|
||||
})
|
||||
export class AppModule {}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user