mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Merge branch '2.0' into pr/5379
# Conflicts: # ionic/components/slides/slides.ts
This commit is contained in:
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,3 +1,36 @@
|
||||
<a name="2.0.0-beta.0"></a>
|
||||
# 2.0.0-beta.0
|
||||
|
||||
Enjoy!
|
||||
|
||||
<3 The Ionic Team
|
||||
|
||||
|
||||
|
||||
<a name="2.0.0-alpha.57"></a>
|
||||
# [2.0.0-alpha.57](https://github.com/driftyco/ionic/compare/v2.0.0-alpha.56...v2.0.0-alpha.57) (2016-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** bar-button uses inner span as flexbox ([38a3be4](https://github.com/driftyco/ionic/commit/38a3be4))
|
||||
|
||||
### Features
|
||||
|
||||
* Improved transitions and animations
|
||||
* hairlines width can be configured with a sass variable ([06b3a5b](https://github.com/driftyco/ionic/commit/06b3a5b))
|
||||
* **ion-item-sliding:** style icons on top of text in an option button ([4e57fcf](https://github.com/driftyco/ionic/commit/4e57fcf)), closes [#5352](https://github.com/driftyco/ionic/issues/5352)
|
||||
|
||||
### Refactor
|
||||
|
||||
* **animations:** no longer using Web Animations polyfill ([da18868](https://github.com/driftyco/ionic/commit/da18868))
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
The Web Animations polyfill is no longer shipped with the framework and may cause build errors.
|
||||
|
||||
Projects will need to be [updated accordingly](https://github.com/driftyco/ionic-conference-app/commit/2ed59e6fd275c4616792c7b2e5aa9da4a20fb188).
|
||||
|
||||
<a name="2.0.0-alpha.56"></a>
|
||||
# [2.0.0-alpha.56](https://github.com/driftyco/ionic/compare/v2.0.0-alpha.55...v2.0.0-alpha.56) (2016-02-05)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[](http://commitizen.github.io/cz-cli/)
|
||||
|
||||
# Ionic 2: Alpha
|
||||
# Ionic 2: Beta
|
||||
|
||||
Ionic 2 is the next generation of [Ionic](http://ionicframework.com/), the open-source mobile app development SDK that makes it easy to build top quality mobile apps with web technologies.
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
general:
|
||||
branches:
|
||||
ignore:
|
||||
- ins_n_outs
|
||||
machine:
|
||||
node:
|
||||
version: 4.1.0
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
.chat-sliding-demo ion-item-options button {
|
||||
.chat-sliding-demo ion-item-options .button-inner {
|
||||
font-size: 14px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@@ -238,6 +238,7 @@ gulp.task('transpile', function(){
|
||||
|
||||
function tsCompile(options, cacheName){
|
||||
return gulp.src([
|
||||
'typings/main.d.ts',
|
||||
'ionic/**/*.ts',
|
||||
'!ionic/**/*.d.ts',
|
||||
'!ionic/components/*/test/**/*',
|
||||
@@ -709,7 +710,7 @@ gulp.task('prepare', function(){
|
||||
|
||||
//Update package.json version
|
||||
var packageJSON = require('./package.json');
|
||||
packageJSON.version = semver.inc(packageJSON.version, 'prerelease', 'alpha');
|
||||
packageJSON.version = semver.inc(packageJSON.version, 'prerelease', 'beta');
|
||||
fs.writeFileSync('package.json', JSON.stringify(packageJSON, null, 2));
|
||||
|
||||
//Update changelog
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {ViewController} from '../components/nav/view-controller';
|
||||
import {CSS, rafFrames, raf, transitionEnd} from '../util/dom';
|
||||
import {assign} from '../util/util';
|
||||
import {assign, isDefined} from '../util/util';
|
||||
|
||||
|
||||
/**
|
||||
@@ -25,12 +24,14 @@ export class Animation {
|
||||
private _fOnceFns: Array<Function>;
|
||||
private _wChg: boolean = false;
|
||||
private _rv: boolean;
|
||||
private _unregTrans: Function;
|
||||
private _tmr;
|
||||
|
||||
public isPlaying: boolean;
|
||||
public hasTween: boolean;
|
||||
public meta;
|
||||
|
||||
constructor(ele?, opts={}) {
|
||||
constructor(ele?, opts: AnimationOptions = {}) {
|
||||
this._reset();
|
||||
this.element(ele);
|
||||
|
||||
@@ -54,6 +55,8 @@ export class Animation {
|
||||
this._fFns = [];
|
||||
this._fOnceFns = [];
|
||||
|
||||
this._clearAsync();
|
||||
|
||||
this.isPlaying = this.hasTween = this._rv = false;
|
||||
this._el = this._easing = this._dur = null;
|
||||
}
|
||||
@@ -106,11 +109,11 @@ export class Animation {
|
||||
return this;
|
||||
}
|
||||
|
||||
from(prop: string, val: string): Animation {
|
||||
from(prop: string, val): Animation {
|
||||
return this._addProp('from', prop, val);
|
||||
}
|
||||
|
||||
to(prop: string, val: string): Animation {
|
||||
to(prop: string, val): Animation {
|
||||
return this._addProp('to', prop, val);
|
||||
}
|
||||
|
||||
@@ -196,12 +199,12 @@ export class Animation {
|
||||
}
|
||||
}
|
||||
|
||||
play() {
|
||||
play(opts: PlayOptions = {}) {
|
||||
var self = this;
|
||||
var i;
|
||||
var duration = isDefined(opts.duration) ? opts.duration : self._dur;
|
||||
|
||||
var i, fallbackTimerId, deregTransEnd;
|
||||
|
||||
console.debug('Animation, play, duration', self._dur, 'easing', self._easing);
|
||||
console.debug('Animation, play, duration', duration, 'easing', self._easing);
|
||||
|
||||
// always default that an animation does not tween
|
||||
// a tween requires that an Animation class has an element
|
||||
@@ -226,7 +229,10 @@ export class Animation {
|
||||
// will recursively stage all child elements
|
||||
self._before();
|
||||
|
||||
if (self._dur > 30) {
|
||||
// ensure all past transition end events have been cleared
|
||||
this._clearAsync();
|
||||
|
||||
if (duration > 30) {
|
||||
// this animation has a duration, so it should animate
|
||||
// place all the elements with their FROM properties
|
||||
|
||||
@@ -235,9 +241,9 @@ export class Animation {
|
||||
|
||||
self._willChange(true);
|
||||
|
||||
// set the TRANSITION END event
|
||||
// set the async TRANSITION END event
|
||||
// and run onFinishes when the transition ends
|
||||
self._asyncEnd(self._dur);
|
||||
self._asyncEnd(duration, true);
|
||||
|
||||
// begin each animation when everything is rendered in their place
|
||||
// and the transition duration/easing is ready to go
|
||||
@@ -245,7 +251,7 @@ export class Animation {
|
||||
// there's been a moment and the elements are in place
|
||||
|
||||
// now set the TRANSITION duration/easing
|
||||
self._setTrans(self._dur, false);
|
||||
self._setTrans(duration, false);
|
||||
|
||||
// wait a few moments again to wait for the transition
|
||||
// info to take hold in the DOM
|
||||
@@ -264,47 +270,73 @@ export class Animation {
|
||||
// just go straight to the TO properties and call it done
|
||||
self._progress(1);
|
||||
|
||||
// so there was no animation, immediately run the after
|
||||
// since there was no animation, immediately run the after
|
||||
self._after();
|
||||
|
||||
// so there was no animation, it's done
|
||||
// since there was no animation, it's done
|
||||
// fire off all the onFinishes
|
||||
self._onFinish();
|
||||
self._onFinish(true);
|
||||
}
|
||||
}
|
||||
|
||||
_asyncEnd(duration: number) {
|
||||
stop(opts: PlayOptions = {}) {
|
||||
var self = this;
|
||||
var deregTransEnd, fallbackTimerId;
|
||||
var duration = isDefined(opts.duration) ? opts.duration : 0;
|
||||
var stepValue = isDefined(opts.stepValue) ? opts.stepValue : 1;
|
||||
|
||||
// set the TRANSITION END event
|
||||
deregTransEnd = transitionEnd(self._transEl(), function() {
|
||||
// transition has completed
|
||||
console.debug('Animation, transition end');
|
||||
// ensure all past transition end events have been cleared
|
||||
this._clearAsync();
|
||||
|
||||
// cancel the fallback timer so it doesn't fire also
|
||||
clearTimeout(fallbackTimerId);
|
||||
// set the TO properties
|
||||
self._progress(stepValue);
|
||||
|
||||
if (duration > 30) {
|
||||
// this animation has a duration, so it should animate
|
||||
// place all the elements with their TO properties
|
||||
|
||||
// now set the TRANSITION duration
|
||||
self._setTrans(duration, true);
|
||||
|
||||
// set the async TRANSITION END event
|
||||
// and run onFinishes when the transition ends
|
||||
self._asyncEnd(duration, false);
|
||||
|
||||
} else {
|
||||
// this animation does not have a duration, so it should not animate
|
||||
// just go straight to the TO properties and call it done
|
||||
self._after();
|
||||
|
||||
// since there was no animation, it's done
|
||||
// fire off all the onFinishes
|
||||
self._onFinish(false);
|
||||
}
|
||||
}
|
||||
|
||||
_asyncEnd(duration: number, shouldComplete: boolean) {
|
||||
var self = this;
|
||||
|
||||
function onTransitionEnd(ev) {
|
||||
console.debug('Animation async end,', (ev ? 'transitionEnd, ' + ev.target.nodeName + ', property: ' + ev.propertyName : 'fallback timeout'));
|
||||
|
||||
// ensure transition end events and timeouts have been cleared
|
||||
self._clearAsync();
|
||||
|
||||
// set the after styles
|
||||
self._after();
|
||||
self._willChange(false);
|
||||
self._onFinish();
|
||||
});
|
||||
self._onFinish(shouldComplete);
|
||||
}
|
||||
|
||||
// set the TRANSITION END event on one of the transition elements
|
||||
self._unregTrans = transitionEnd(self._transEl(), onTransitionEnd);
|
||||
|
||||
// set a fallback timeout if the transition end event never fires
|
||||
fallbackTimerId = setTimeout(function() {
|
||||
// fallback timeout fired instead of the transition end
|
||||
console.debug('Animation, fallback end');
|
||||
self._tmr = setTimeout(onTransitionEnd, duration + 300);
|
||||
}
|
||||
|
||||
// deregister the transition end event listener
|
||||
deregTransEnd();
|
||||
|
||||
// set the after styles
|
||||
self._after();
|
||||
self._willChange(false);
|
||||
self._onFinish();
|
||||
|
||||
}, duration + 300);
|
||||
_clearAsync() {
|
||||
this._unregTrans && this._unregTrans();
|
||||
clearTimeout(this._tmr);
|
||||
}
|
||||
|
||||
_progress(stepValue: number) {
|
||||
@@ -548,12 +580,12 @@ export class Animation {
|
||||
// for example, the left menu was dragged all the way open already
|
||||
this._after();
|
||||
this._willChange(false);
|
||||
this._onFinish();
|
||||
this._onFinish(shouldComplete);
|
||||
|
||||
} else {
|
||||
// the stepValue was left off at a point when it needs to finish transition still
|
||||
// for example, the left menu was opened 75% and needs to finish opening
|
||||
this._asyncEnd(64);
|
||||
this._asyncEnd(64, shouldComplete);
|
||||
|
||||
// force quick duration, linear easing
|
||||
this._setTrans(64, true);
|
||||
@@ -565,7 +597,11 @@ export class Animation {
|
||||
return this;
|
||||
}
|
||||
|
||||
onFinish(callback: Function, onceTimeCallback: boolean = false) {
|
||||
onFinish(callback: Function, onceTimeCallback: boolean = false, clearOnFinishCallacks: boolean = false) {
|
||||
if (clearOnFinishCallacks) {
|
||||
this._fFns = [];
|
||||
this._fOnceFns = [];
|
||||
}
|
||||
if (onceTimeCallback) {
|
||||
this._fOnceFns.push(callback);
|
||||
|
||||
@@ -575,15 +611,15 @@ export class Animation {
|
||||
return this;
|
||||
}
|
||||
|
||||
_onFinish() {
|
||||
_onFinish(hasCompleted: boolean) {
|
||||
this.isPlaying = false;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < this._fFns.length; i++) {
|
||||
this._fFns[i]();
|
||||
this._fFns[i](hasCompleted);
|
||||
}
|
||||
for (i = 0; i < this._fOnceFns.length; i++) {
|
||||
this._fOnceFns[i]();
|
||||
this._fOnceFns[i](hasCompleted);
|
||||
}
|
||||
this._fOnceFns = [];
|
||||
}
|
||||
@@ -625,7 +661,7 @@ export class Animation {
|
||||
/*
|
||||
STATIC CLASSES
|
||||
*/
|
||||
static create(name: string): Animation {
|
||||
static create(name: string, opts: AnimationOptions = {}): Animation {
|
||||
let AnimationClass = AnimationRegistry[name];
|
||||
|
||||
if (!AnimationClass) {
|
||||
@@ -633,17 +669,7 @@ export class Animation {
|
||||
// fallback to just the base Animation class
|
||||
AnimationClass = Animation;
|
||||
}
|
||||
return new AnimationClass();
|
||||
}
|
||||
|
||||
static createTransition(enteringView: ViewController, leavingView: ViewController, opts: any = {}): Animation {
|
||||
let TransitionClass = AnimationRegistry[opts.animation];
|
||||
if (!TransitionClass) {
|
||||
// didn't find a transition animation, default to ios-transition
|
||||
TransitionClass = AnimationRegistry['ios-transition'];
|
||||
}
|
||||
|
||||
return new TransitionClass(enteringView, leavingView, opts);
|
||||
return new AnimationClass(null, opts);
|
||||
}
|
||||
|
||||
static register(name: string, AnimationClass) {
|
||||
@@ -652,6 +678,16 @@ export class Animation {
|
||||
|
||||
}
|
||||
|
||||
export interface AnimationOptions {
|
||||
animation?: string;
|
||||
renderDelay?: number;
|
||||
}
|
||||
|
||||
export interface PlayOptions {
|
||||
duration?: number;
|
||||
stepValue?: number;
|
||||
}
|
||||
|
||||
const doc: any = document;
|
||||
const TRANSFORMS = [
|
||||
'translateX', 'translateY', 'translateZ', 'scale', 'scaleX', 'scaleY', 'scaleZ',
|
||||
|
||||
@@ -2,6 +2,7 @@ import {Component, Renderer, ElementRef} from 'angular2/core';
|
||||
import {NgFor, NgIf} from 'angular2/common';
|
||||
|
||||
import {Animation} from '../../animations/animation';
|
||||
import {Transition, TransitionOptions} from '../../transitions/transition';
|
||||
import {Config} from '../../config/config';
|
||||
import {Icon} from '../icon/icon';
|
||||
import {isDefined} from '../../util/util';
|
||||
@@ -129,7 +130,8 @@ import {ViewController} from '../nav/view-controller';
|
||||
title?: string,
|
||||
subTitle?: string,
|
||||
cssClass?: string,
|
||||
buttons?: Array<any>
|
||||
buttons?: Array<any>,
|
||||
enableBackdropDismiss?: boolean
|
||||
} = {}) {
|
||||
return new ActionSheet(opts);
|
||||
}
|
||||
@@ -272,9 +274,9 @@ class ActionSheetCmp {
|
||||
|
||||
|
||||
|
||||
class ActionSheetSlideIn extends Animation {
|
||||
constructor(enteringView, leavingView, opts) {
|
||||
super(null, opts);
|
||||
class ActionSheetSlideIn extends Transition {
|
||||
constructor(enteringView, leavingView, opts: TransitionOptions) {
|
||||
super(opts);
|
||||
|
||||
let ele = enteringView.pageRef().nativeElement;
|
||||
let backdrop = new Animation(ele.querySelector('.backdrop'));
|
||||
@@ -286,12 +288,12 @@ class ActionSheetSlideIn extends Animation {
|
||||
this.easing('cubic-bezier(.36,.66,.04,1)').duration(400).add(backdrop).add(wrapper);
|
||||
}
|
||||
}
|
||||
Animation.register('action-sheet-slide-in', ActionSheetSlideIn);
|
||||
Transition.register('action-sheet-slide-in', ActionSheetSlideIn);
|
||||
|
||||
|
||||
class ActionSheetSlideOut extends Animation {
|
||||
constructor(enteringView, leavingView, opts) {
|
||||
super(null, opts);
|
||||
class ActionSheetSlideOut extends Transition {
|
||||
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
|
||||
super(opts);
|
||||
|
||||
let ele = leavingView.pageRef().nativeElement;
|
||||
let backdrop = new Animation(ele.querySelector('.backdrop'));
|
||||
@@ -303,12 +305,12 @@ class ActionSheetSlideOut extends Animation {
|
||||
this.easing('cubic-bezier(.36,.66,.04,1)').duration(300).add(backdrop).add(wrapper);
|
||||
}
|
||||
}
|
||||
Animation.register('action-sheet-slide-out', ActionSheetSlideOut);
|
||||
Transition.register('action-sheet-slide-out', ActionSheetSlideOut);
|
||||
|
||||
|
||||
class ActionSheetMdSlideIn extends Animation {
|
||||
constructor(enteringView, leavingView, opts) {
|
||||
super(null, opts);
|
||||
class ActionSheetMdSlideIn extends Transition {
|
||||
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
|
||||
super(opts);
|
||||
|
||||
let ele = enteringView.pageRef().nativeElement;
|
||||
let backdrop = new Animation(ele.querySelector('.backdrop'));
|
||||
@@ -320,12 +322,12 @@ class ActionSheetMdSlideIn extends Animation {
|
||||
this.easing('cubic-bezier(.36,.66,.04,1)').duration(450).add(backdrop).add(wrapper);
|
||||
}
|
||||
}
|
||||
Animation.register('action-sheet-md-slide-in', ActionSheetMdSlideIn);
|
||||
Transition.register('action-sheet-md-slide-in', ActionSheetMdSlideIn);
|
||||
|
||||
|
||||
class ActionSheetMdSlideOut extends Animation {
|
||||
constructor(enteringView, leavingView, opts) {
|
||||
super(null, opts);
|
||||
class ActionSheetMdSlideOut extends Transition {
|
||||
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
|
||||
super(opts);
|
||||
|
||||
let ele = leavingView.pageRef().nativeElement;
|
||||
let backdrop = new Animation(ele.querySelector('.backdrop'));
|
||||
@@ -337,4 +339,4 @@ class ActionSheetMdSlideOut extends Animation {
|
||||
this.easing('cubic-bezier(.36,.66,.04,1)').duration(450).add(backdrop).add(wrapper);
|
||||
}
|
||||
}
|
||||
Animation.register('action-sheet-md-slide-out', ActionSheetMdSlideOut);
|
||||
Transition.register('action-sheet-md-slide-out', ActionSheetMdSlideOut);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, Page, ActionSheet, NavController} from 'ionic/ionic';
|
||||
import {App, Page, ActionSheet, NavController} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@Page({
|
||||
|
||||
@@ -94,6 +94,12 @@ ion-alert {
|
||||
text-align: $alert-ios-message-text-align;
|
||||
}
|
||||
|
||||
.alert-message {
|
||||
&:empty {
|
||||
padding: 0 0 12px 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// iOS Alert Input
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@import "../../globals.md";
|
||||
@import "./alert";
|
||||
@import "../button/button.md";
|
||||
|
||||
// Material Design Alerts
|
||||
// --------------------------------------------------
|
||||
@@ -68,6 +69,10 @@ $alert-md-buttons-justify-content: flex-end !default;
|
||||
|
||||
.alert-message {
|
||||
font-size: $alert-md-message-font-size;
|
||||
|
||||
&:empty {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +231,7 @@ $alert-md-buttons-justify-content: flex-end !default;
|
||||
text-align: right;
|
||||
|
||||
&.activated {
|
||||
background-color: $button-md-clear-active-background-color;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,10 +52,6 @@ ion-alert {
|
||||
|
||||
.alert-message {
|
||||
overflow: auto;
|
||||
|
||||
&:empty {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.alert-input {
|
||||
|
||||
@@ -2,6 +2,7 @@ import {Component, ElementRef, Renderer} from 'angular2/core';
|
||||
import {NgClass, NgSwitch, NgIf, NgFor} from 'angular2/common';
|
||||
|
||||
import {Animation} from '../../animations/animation';
|
||||
import {Transition, TransitionOptions} from '../../transitions/transition';
|
||||
import {Config} from '../../config/config';
|
||||
import {isDefined} from '../../util/util';
|
||||
import {NavParams} from '../nav/nav-params';
|
||||
@@ -197,7 +198,7 @@ export class Alert extends ViewController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} button Alert button
|
||||
* @param {any} button Alert button
|
||||
*/
|
||||
addButton(button: any) {
|
||||
this.data.buttons.push(button);
|
||||
@@ -211,7 +212,7 @@ export class Alert extends ViewController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} opts Alert options
|
||||
* @param {object} opts Alert options
|
||||
*/
|
||||
static create(opts: {
|
||||
title?: string,
|
||||
@@ -247,7 +248,7 @@ export class Alert extends ViewController {
|
||||
'<h2 id="{{hdrId}}" class="alert-title" *ngIf="d.title" [innerHTML]="d.title"></h2>' +
|
||||
'<h3 id="{{subHdrId}}" class="alert-sub-title" *ngIf="d.subTitle" [innerHTML]="d.subTitle"></h3>' +
|
||||
'</div>' +
|
||||
'<div id="{{msgId}}" class="alert-message" *ngIf="d.message" [innerHTML]="d.message"></div>' +
|
||||
'<div id="{{msgId}}" class="alert-message" [innerHTML]="d.message"></div>' +
|
||||
'<div *ngIf="d.inputs.length" [ngSwitch]="inputType">' +
|
||||
|
||||
'<template ngSwitchWhen="radio">' +
|
||||
@@ -334,6 +335,10 @@ class AlertCmp {
|
||||
} else if (this.d.subTitle) {
|
||||
this.descId = this.subHdrId;
|
||||
}
|
||||
|
||||
if (!this.d.message) {
|
||||
this.d.message = '';
|
||||
}
|
||||
}
|
||||
|
||||
onPageLoaded() {
|
||||
@@ -484,9 +489,9 @@ class AlertCmp {
|
||||
/**
|
||||
* Animations for alerts
|
||||
*/
|
||||
class AlertPopIn extends Animation {
|
||||
constructor(enteringView, leavingView, opts) {
|
||||
super(null, opts);
|
||||
class AlertPopIn extends Transition {
|
||||
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
|
||||
super(opts);
|
||||
|
||||
let ele = enteringView.pageRef().nativeElement;
|
||||
let backdrop = new Animation(ele.querySelector('.backdrop'));
|
||||
@@ -502,12 +507,12 @@ class AlertPopIn extends Animation {
|
||||
.add(wrapper);
|
||||
}
|
||||
}
|
||||
Animation.register('alert-pop-in', AlertPopIn);
|
||||
Transition.register('alert-pop-in', AlertPopIn);
|
||||
|
||||
|
||||
class AlertPopOut extends Animation {
|
||||
constructor(enteringView, leavingView, opts) {
|
||||
super(null, opts);
|
||||
class AlertPopOut extends Transition {
|
||||
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
|
||||
super(opts);
|
||||
|
||||
let ele = leavingView.pageRef().nativeElement;
|
||||
let backdrop = new Animation(ele.querySelector('.backdrop'));
|
||||
@@ -523,12 +528,12 @@ class AlertPopOut extends Animation {
|
||||
.add(wrapper);
|
||||
}
|
||||
}
|
||||
Animation.register('alert-pop-out', AlertPopOut);
|
||||
Transition.register('alert-pop-out', AlertPopOut);
|
||||
|
||||
|
||||
class AlertMdPopIn extends Animation {
|
||||
constructor(enteringView, leavingView, opts) {
|
||||
super(null, opts);
|
||||
class AlertMdPopIn extends Transition {
|
||||
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
|
||||
super(opts);
|
||||
|
||||
let ele = enteringView.pageRef().nativeElement;
|
||||
let backdrop = new Animation(ele.querySelector('.backdrop'));
|
||||
@@ -544,12 +549,12 @@ class AlertMdPopIn extends Animation {
|
||||
.add(wrapper);
|
||||
}
|
||||
}
|
||||
Animation.register('alert-md-pop-in', AlertMdPopIn);
|
||||
Transition.register('alert-md-pop-in', AlertMdPopIn);
|
||||
|
||||
|
||||
class AlertMdPopOut extends Animation {
|
||||
constructor(enteringView, leavingView, opts) {
|
||||
super(null, opts);
|
||||
class AlertMdPopOut extends Transition {
|
||||
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
|
||||
super(opts);
|
||||
|
||||
let ele = leavingView.pageRef().nativeElement;
|
||||
let backdrop = new Animation(ele.querySelector('.backdrop'));
|
||||
@@ -565,6 +570,6 @@ class AlertMdPopOut extends Animation {
|
||||
.add(wrapper);
|
||||
}
|
||||
}
|
||||
Animation.register('alert-md-pop-out', AlertMdPopOut);
|
||||
Transition.register('alert-md-pop-out', AlertMdPopOut);
|
||||
|
||||
let alertIds = -1;
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import {App, Page, Alert, NavController} from 'ionic/ionic';
|
||||
import {App, Page, Alert, NavController} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@Page({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EPage {
|
||||
testConfirmOpen: boolean = false;
|
||||
testPromptOpen: boolean = false;
|
||||
testConfirmResult: string = '';
|
||||
testPromptResult: string = '';
|
||||
|
||||
constructor(private nav: NavController) {
|
||||
this.testConfirmOpen = false;
|
||||
this.testPromptOpen = false;
|
||||
this.testConfirmResult = '';
|
||||
this.testPromptResult = '';
|
||||
}
|
||||
constructor(private nav: NavController) { }
|
||||
|
||||
doAlert() {
|
||||
let alert = Alert.create({
|
||||
@@ -60,6 +59,14 @@ class E2EPage {
|
||||
this.nav.present(alert);
|
||||
}
|
||||
|
||||
doAlertNoMessage() {
|
||||
let alert = Alert.create({
|
||||
title: 'Alert',
|
||||
buttons: ['OK']
|
||||
});
|
||||
this.nav.present(alert);
|
||||
}
|
||||
|
||||
doMultipleButtons() {
|
||||
let alert = Alert.create({
|
||||
title: 'Alert',
|
||||
@@ -234,7 +241,7 @@ class E2EPage {
|
||||
|
||||
setTimeout(() => {
|
||||
alert.dismiss();
|
||||
}, 100);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
doDisabledBackdropAlert() {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<button block class="e2eOpenAlert" (click)="doAlert()">Alert</button>
|
||||
<button block class="e2eOpenAlertLongMessage" (click)="doAlertLongMessage()">Alert Long Message</button>
|
||||
<button block class="e2eOpenMultipleButtons" (click)="doMultipleButtons()">Multiple Buttons (>2)</button>
|
||||
<button block class="e2eOpenAlertNoMessage" (click)="doAlertNoMessage()">Alert No Message</button>
|
||||
<button block class="e2eOpenConfirm" (click)="doConfirm()">Confirm</button>
|
||||
<button block class="e2eOpenPrompt" (click)="doPrompt()">Prompt</button>
|
||||
<button block class="e2eOpenRadio" (click)="doRadio()">Radio</button>
|
||||
|
||||
@@ -50,8 +50,8 @@ export class IonicApp {
|
||||
* available to accept new user commands. For example, this is set to `false`
|
||||
* while views transition, a modal slides up, an action-sheet
|
||||
* slides up, etc. After the transition completes it is set back to `true`.
|
||||
* @param {bool} isEnabled
|
||||
* @param {bool} fallback When `isEnabled` is set to `false`, this argument
|
||||
* @param {boolean} isEnabled
|
||||
* @param {boolean} fallback When `isEnabled` is set to `false`, this argument
|
||||
* is used to set the maximum number of milliseconds that app will wait until
|
||||
* it will automatically enable the app again. It's basically a fallback incase
|
||||
* something goes wrong during a transition and the app wasn't re-enabled correctly.
|
||||
@@ -68,7 +68,7 @@ export class IonicApp {
|
||||
/**
|
||||
* @private
|
||||
* Boolean if the app is actively enabled or not.
|
||||
* @return {bool}
|
||||
* @return {boolean}
|
||||
*/
|
||||
isEnabled(): boolean {
|
||||
return (this._disTime < Date.now());
|
||||
@@ -84,7 +84,7 @@ export class IonicApp {
|
||||
/**
|
||||
* @private
|
||||
* Boolean if the app is actively scrolling or not.
|
||||
* @return {bool}
|
||||
* @return {boolean}
|
||||
*/
|
||||
isScrolling(): boolean {
|
||||
return (this._scrollTime + 64 > Date.now());
|
||||
@@ -94,7 +94,7 @@ export class IonicApp {
|
||||
* @private
|
||||
* Register a known component with a key, for easy lookups later.
|
||||
* @param {string} id The id to use to register the component
|
||||
* @param {Object} component The component to register
|
||||
* @param {object} component The component to register
|
||||
*/
|
||||
register(id: string, component: any) {
|
||||
this.components[id] = component;
|
||||
@@ -112,8 +112,8 @@ export class IonicApp {
|
||||
/**
|
||||
* @private
|
||||
* Get a registered component with the given type (returns the first)
|
||||
* @param {Object} cls the type to search for
|
||||
* @return {Object} the matching component, or undefined if none was found
|
||||
* @param {object} cls the type to search for
|
||||
* @return {object} the matching component, or undefined if none was found
|
||||
*/
|
||||
getRegisteredComponent(cls: any): any {
|
||||
for (let key in this.components) {
|
||||
@@ -128,7 +128,7 @@ export class IonicApp {
|
||||
* @private
|
||||
* Get the component for the given key.
|
||||
* @param {string} id TODO
|
||||
* @return {Object} TODO
|
||||
* @return {object} TODO
|
||||
*/
|
||||
getComponent(id: string): any {
|
||||
// deprecated warning
|
||||
|
||||
@@ -18,7 +18,7 @@ import {IonicApp} from './app';
|
||||
* <ion-checkbox id="myCheckbox"></ion-checkbox>
|
||||
* ```
|
||||
*
|
||||
* To get a reference to the registered component, inject the [IonicApp](../app/IonicApp/)
|
||||
* To get a reference to the registered component, inject the [IonicApp](../IonicApp/)
|
||||
* service:
|
||||
* ```ts
|
||||
* constructor(app: IonicApp) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, Page, Animation} from 'ionic/ionic';
|
||||
import {App, Page, Animation} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@Page({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Component} from 'angular2/core';
|
||||
import {Control, ControlGroup} from 'angular2/common';
|
||||
|
||||
import {App, Storage, LocalStorage, SqlStorage} from 'ionic/ionic';
|
||||
import {App, Storage, LocalStorage, SqlStorage} from '../../../../../ionic/ionic';
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicApp} from 'ionic/ionic';
|
||||
import {App, IonicApp} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicApp} from 'ionic/ionic';
|
||||
import {App, IonicApp} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -97,7 +97,6 @@ $button-ios-small-icon-font-size: 1.3em !default;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
|
||||
// iOS Full Button
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -105,11 +104,10 @@ $button-ios-small-icon-font-size: 1.3em !default;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
border-radius: 0;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-right-width: 0;
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
|
||||
// iOS Outline Button
|
||||
// --------------------------------------------------
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ $button-md-small-icon-font-size: 1.4em !default;
|
||||
color $button-md-transition-duration $button-md-animation-curve;
|
||||
|
||||
&:hover:not(.disable-hover) {
|
||||
background-color: $button-md-clear-hover-background-color;
|
||||
background-color: $button-md-color;
|
||||
}
|
||||
|
||||
&.activated {
|
||||
@@ -85,6 +85,10 @@ $button-md-small-icon-font-size: 1.4em !default;
|
||||
color: $fg-color;
|
||||
background-color: $bg-color;
|
||||
|
||||
&:hover:not(.disable-hover) {
|
||||
background-color: $bg-color;
|
||||
}
|
||||
|
||||
&.activated {
|
||||
opacity: 1;
|
||||
background-color: $bg-color-activated;
|
||||
@@ -117,28 +121,25 @@ $button-md-small-icon-font-size: 1.4em !default;
|
||||
font-size: $button-md-small-icon-font-size;
|
||||
}
|
||||
|
||||
// Material Design Block Button
|
||||
// --------------------------------------------------
|
||||
|
||||
.button-block {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
// Material Design Full Button
|
||||
// --------------------------------------------------
|
||||
|
||||
.button-full {
|
||||
border-radius: 0;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
border-radius: 0;
|
||||
border-right-width: 0;
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Block Button
|
||||
// --------------------------------------------------
|
||||
|
||||
.button-block {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Outline Button
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -150,6 +151,10 @@ $button-md-small-icon-font-size: 1.4em !default;
|
||||
color: $button-md-color;
|
||||
box-shadow: none;
|
||||
|
||||
&:hover:not(.disable-hover) {
|
||||
background-color: $button-md-clear-hover-background-color;
|
||||
}
|
||||
|
||||
&.activated {
|
||||
opacity: 1;
|
||||
box-shadow: none;
|
||||
@@ -173,6 +178,10 @@ $button-md-small-icon-font-size: 1.4em !default;
|
||||
background-color: transparent;
|
||||
color: $fg-color;
|
||||
|
||||
&:hover:not(.disable-hover) {
|
||||
background-color: $button-md-clear-hover-background-color;
|
||||
}
|
||||
|
||||
&.activated {
|
||||
background-color: transparent;
|
||||
}
|
||||
@@ -201,7 +210,7 @@ $button-md-small-icon-font-size: 1.4em !default;
|
||||
}
|
||||
|
||||
&:hover:not(.disable-hover) {
|
||||
color: $button-md-color;
|
||||
background-color: $button-md-clear-hover-background-color;
|
||||
}
|
||||
|
||||
ion-button-effect {
|
||||
|
||||
@@ -29,17 +29,17 @@ $button-round-border-radius: 64px !default;
|
||||
@include appearance(none);
|
||||
}
|
||||
|
||||
span.button-inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.button-inner {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a.button {
|
||||
a.button, a[button] {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ a.button {
|
||||
// --------------------------------------------------
|
||||
|
||||
.button-block {
|
||||
display: flex;
|
||||
display: block;
|
||||
clear: both;
|
||||
width: 100%;
|
||||
|
||||
@@ -68,6 +68,7 @@ a.button {
|
||||
// --------------------------------------------------
|
||||
|
||||
.button-full {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicApp} from 'ionic/ionic';
|
||||
import {App, IonicApp} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Button, Config} from 'ionic/ionic';
|
||||
import {Button, Config} from '../../../../ionic/ionic';
|
||||
|
||||
export function run() {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -25,6 +25,7 @@ $card-ios-font-size: 1.4rem !default;
|
||||
$card-ios-text-color: #666 !default;
|
||||
$card-ios-title-font-size: 1.8rem !default;
|
||||
$card-ios-title-padding: 8px 0 8px 0 !default;
|
||||
$card-ios-title-margin: 2px 0 2px !default;
|
||||
$card-ios-title-text-color: #222 !default;
|
||||
|
||||
$card-ios-header-font-size: 1.6rem !default;
|
||||
@@ -85,8 +86,11 @@ ion-card {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
ion-card-title {
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
padding: $card-ios-title-padding;
|
||||
margin: $card-ios-title-margin;
|
||||
font-size: $card-ios-title-font-size;
|
||||
color: $card-ios-title-text-color;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ $card-md-line-height: 1.5 !default;
|
||||
$card-md-text-color: #222 !default;
|
||||
$card-md-title-font-size: 2.4rem !default;
|
||||
$card-md-title-padding: 8px 0 8px 0 !default;
|
||||
$card-md-title-margin: 2px 0 2px !default;
|
||||
$card-md-title-text-color: #222 !default;
|
||||
|
||||
$card-md-header-font-size: 1.6rem !default;
|
||||
@@ -87,8 +88,11 @@ ion-card {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
ion-card-title {
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
padding: $card-md-title-padding;
|
||||
margin: $card-md-title-margin;
|
||||
font-size: $card-md-title-font-size;
|
||||
color: $card-md-title-text-color;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
</div>
|
||||
|
||||
<ion-card-content>
|
||||
<h2 class="card-title">
|
||||
<ion-card-title>
|
||||
Card Title Goes Here
|
||||
</h2>
|
||||
</ion-card-title>
|
||||
<p>
|
||||
Keep close to Nature's heart... and break clear away,
|
||||
once in awhile, and climb a mountain. I am within a paragraph element.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -9,17 +9,17 @@
|
||||
|
||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
|
||||
<button fab fab-right fab-top>
|
||||
<icon pin></icon>
|
||||
<ion-icon name="pin"></ion-icon>
|
||||
</button>
|
||||
|
||||
<ion-item>
|
||||
<icon item-left large football></icon>
|
||||
<ion-icon item-left large name="football"></ion-icon>
|
||||
<h2>Museum of Football</h2>
|
||||
<p>11 N. Way St, Madison, WI 53703</p>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<icon item-left large wine></icon>
|
||||
<ion-icon item-left large name="wine"></ion-icon>
|
||||
<h2>Institute of Fine Cocktails</h2>
|
||||
<p>14 S. Hop Avenue, Madison, WI 53703</p>
|
||||
</ion-item>
|
||||
@@ -28,7 +28,7 @@
|
||||
<span item-left>18 min</span>
|
||||
<span item-left>(2.6 mi)</span>
|
||||
<button primary clear item-right>
|
||||
<icon navigate></icon>
|
||||
<ion-icon name="navigate"></ion-icon>
|
||||
Start
|
||||
</button>
|
||||
</ion-item>
|
||||
@@ -39,17 +39,17 @@
|
||||
|
||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
|
||||
<button danger fab fab-right fab-top>
|
||||
<icon pin></icon>
|
||||
<ion-icon name="pin"></ion-icon>
|
||||
</button>
|
||||
|
||||
<ion-item>
|
||||
<icon item-left large cloud></icon>
|
||||
<ion-icon item-left large name="cloud"></ion-icon>
|
||||
<h2>Yoshi's Island</h2>
|
||||
<p>Iggy Koopa</p>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<icon item-left large leaf></icon>
|
||||
<ion-icon item-left large name="leaf"></ion-icon>
|
||||
<h2>Forest of Illusion</h2>
|
||||
<p>Roy Koopa</p>
|
||||
</ion-item>
|
||||
@@ -58,7 +58,7 @@
|
||||
<span item-left>3 hr</span>
|
||||
<span item-left>(4.8 mi)</span>
|
||||
<button danger clear item-right>
|
||||
<icon navigate></icon>
|
||||
<ion-icon name="navigate"></ion-icon>
|
||||
Start
|
||||
</button>
|
||||
</ion-item>
|
||||
@@ -69,17 +69,17 @@
|
||||
|
||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
|
||||
<button secondary fab fab-right fab-top>
|
||||
<icon pin></icon>
|
||||
<ion-icon name="pin"></ion-icon>
|
||||
</button>
|
||||
|
||||
<ion-item>
|
||||
<icon item-left large information-circle></icon>
|
||||
<ion-icon item-left large name="information-circle"></ion-icon>
|
||||
<h2>Museum of Information</h2>
|
||||
<p>44 Rue de Info, 75010 Paris, France</p>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<icon item-left large leaf></icon>
|
||||
<ion-icon item-left large name="leaf"></ion-icon>
|
||||
<h2>General Pharmacy</h2>
|
||||
<p>1 Avenue Faux, 75010 Paris, France</p>
|
||||
</ion-item>
|
||||
@@ -88,7 +88,7 @@
|
||||
<span item-left secondary>26 min</span>
|
||||
<span item-left>(8.1 mi)</span>
|
||||
<button secondary clear item-right>
|
||||
<icon navigate></icon>
|
||||
<ion-icon name="navigate"></ion-icon>
|
||||
Start
|
||||
</button>
|
||||
</ion-item>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
|
||||
<ion-item>
|
||||
<button primary clear item-left>
|
||||
<icon thumbs-up></icon>
|
||||
<ion-icon name="thumbs-up"></ion-icon>
|
||||
<div>12 Likes</div>
|
||||
</button>
|
||||
<button primary clear item-left>
|
||||
<icon text></icon>
|
||||
<ion-icon name="text"></ion-icon>
|
||||
<div>4 Comments</div>
|
||||
</button>
|
||||
<ion-note item-right>
|
||||
@@ -56,11 +56,11 @@
|
||||
|
||||
<ion-item>
|
||||
<button primary clear item-left>
|
||||
<icon thumbs-up></icon>
|
||||
<ion-icon name="thumbs-up"></ion-icon>
|
||||
<div>30 Likes</div>
|
||||
</button>
|
||||
<button primary clear item-left>
|
||||
<icon text></icon>
|
||||
<ion-icon name="text"></ion-icon>
|
||||
<div>64 Comments</div>
|
||||
</button>
|
||||
<ion-note item-right>
|
||||
@@ -88,11 +88,11 @@
|
||||
|
||||
<ion-item>
|
||||
<button primary clear item-left>
|
||||
<icon thumbs-up></icon>
|
||||
<ion-icon name="thumbs-up"></ion-icon>
|
||||
<div>46 Likes</div>
|
||||
</button>
|
||||
<button primary clear item-left>
|
||||
<icon text></icon>
|
||||
<ion-icon name="text"></ion-icon>
|
||||
<div>66 Comments</div>
|
||||
</button>
|
||||
<ion-note item-right>
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import {Component, Optional, Input, HostListener} from 'angular2/core';
|
||||
import {NgControl} from 'angular2/common';
|
||||
import {Component, Optional, Input, HostListener, Provider, forwardRef} from 'angular2/core';
|
||||
import {NG_VALUE_ACCESSOR} from 'angular2/common';
|
||||
|
||||
import {Form} from '../../util/form';
|
||||
import {Item} from '../item/item';
|
||||
import {isTrueProperty} from '../../util/util';
|
||||
|
||||
const CHECKBOX_VALUE_ACCESSOR = new Provider(
|
||||
NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => Checkbox), multi: true});
|
||||
|
||||
|
||||
/**
|
||||
* The checkbox is no different than the HTML checkbox input, except
|
||||
* it's styled accordingly to the the platform and design mode, such
|
||||
* as iOS or Material Design.
|
||||
*
|
||||
* See the [Angular 2 Docs](https://angular.io/docs/js/latest/api/core/Form-interface.html) for more info on forms and input.
|
||||
* See the [Angular 2 Docs](https://angular.io/docs/ts/latest/guide/forms.html)
|
||||
* for more info on forms and inputs.
|
||||
*
|
||||
* @property [checked] - whether or not the checkbox is checked (defaults to false)
|
||||
* @property [value] - the value of the checkbox component
|
||||
* @property [disabled] - whether or not the checkbox is disabled or not.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
@@ -23,17 +25,17 @@ import {isTrueProperty} from '../../util/util';
|
||||
*
|
||||
* <ion-item>
|
||||
* <ion-label>Pepperoni</ion-label>
|
||||
* <ion-checkbox value="pepperoni" checked="true"></ion-checkbox>
|
||||
* <ion-checkbox [(ngModel)]="pepperoni"></ion-checkbox>
|
||||
* </ion-item>
|
||||
*
|
||||
* <ion-item>
|
||||
* <ion-label>Sausage</ion-label>
|
||||
* <ion-checkbox value="sausage" disabled="true"></ion-checkbox>
|
||||
* <ion-checkbox [(ngModel)]="sausage" disabled="true"></ion-checkbox>
|
||||
* </ion-item>
|
||||
*
|
||||
* <ion-item>
|
||||
* <ion-label>Mushrooms</ion-label>
|
||||
* <ion-checkbox value="mushrooms"></ion-checkbox>
|
||||
* <ion-checkbox [(ngModel)]="mushrooms"></ion-checkbox>
|
||||
* </ion-item>
|
||||
*
|
||||
* </ion-list>
|
||||
@@ -56,34 +58,26 @@ import {isTrueProperty} from '../../util/util';
|
||||
'</button>',
|
||||
host: {
|
||||
'[class.checkbox-disabled]': '_disabled'
|
||||
}
|
||||
},
|
||||
providers: [CHECKBOX_VALUE_ACCESSOR]
|
||||
})
|
||||
export class Checkbox {
|
||||
private _checked: any = false;
|
||||
private _disabled: any = false;
|
||||
private _labelId: string;
|
||||
private _fn: Function;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Input() value: string = '';
|
||||
|
||||
constructor(
|
||||
private _form: Form,
|
||||
@Optional() private _item: Item,
|
||||
@Optional() ngControl: NgControl
|
||||
@Optional() private _item: Item
|
||||
) {
|
||||
_form.register(this);
|
||||
|
||||
if (ngControl) {
|
||||
ngControl.valueAccessor = this;
|
||||
}
|
||||
|
||||
if (_item) {
|
||||
this.id = 'chk-' + _item.registerInput('checkbox');
|
||||
this._labelId = 'lbl-' + _item.id;
|
||||
@@ -93,14 +87,17 @@ export class Checkbox {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Toggle the checked state of the checkbox. Calls onChange to pass the updated checked state to the model (Control).
|
||||
*/
|
||||
toggle() {
|
||||
this.checked = !this.checked;
|
||||
@HostListener('click', ['$event'])
|
||||
private _click(ev) {
|
||||
console.debug('checkbox, checked');
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.onChange(!this._checked);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @input {boolean} whether or not the checkbox is checked (defaults to false)
|
||||
*/
|
||||
@Input()
|
||||
get checked() {
|
||||
@@ -108,22 +105,52 @@ export class Checkbox {
|
||||
}
|
||||
|
||||
set checked(val) {
|
||||
if (!this._disabled) {
|
||||
this._checked = isTrueProperty(val);
|
||||
this.onChange(this._checked);
|
||||
this._item && this._item.setCssClass('item-checkbox-checked', this._checked);
|
||||
}
|
||||
this._setChecked(isTrueProperty(val));
|
||||
this.onChange(this._checked);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private _setChecked(isChecked: boolean) {
|
||||
this._checked = isChecked;
|
||||
this._item && this._item.setCssClass('item-checkbox-checked', isChecked);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
writeValue(val: any) {
|
||||
this._setChecked( isTrueProperty(val) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
registerOnChange(fn: Function): void {
|
||||
this._fn = fn;
|
||||
this.onChange = (isChecked: boolean) => {
|
||||
console.debug('checkbox, onChange', isChecked);
|
||||
fn(isChecked);
|
||||
this._setChecked(isChecked);
|
||||
this.onTouched();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
registerOnTouched(fn) { this.onTouched = fn; }
|
||||
|
||||
/**
|
||||
* @input {boolean} whether or not the checkbox is disabled or not.
|
||||
*/
|
||||
@Input()
|
||||
get disabled() {
|
||||
get disabled(): any {
|
||||
return this._disabled;
|
||||
}
|
||||
|
||||
set disabled(val) {
|
||||
set disabled(val: any) {
|
||||
this._disabled = isTrueProperty(val);
|
||||
this._item && this._item.setCssClass('item-checkbox-disabled', this._disabled);
|
||||
}
|
||||
@@ -131,56 +158,12 @@ export class Checkbox {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@HostListener('click', ['$event'])
|
||||
private _click(ev) {
|
||||
console.debug('checkbox, checked', this.value);
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.toggle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Angular2 Forms API method called by the model (Control) on change to update
|
||||
* the checked value.
|
||||
* https://github.com/angular/angular/blob/master/modules/angular2/src/forms/directives/shared.ts#L34
|
||||
*/
|
||||
writeValue(val) {
|
||||
if (val !== null) {
|
||||
this.checked = val;
|
||||
}
|
||||
}
|
||||
onChange(_) {}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
onChange(val) {
|
||||
// TODO: figure the whys and the becauses
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
onTouched(val) {
|
||||
// TODO: figure the whys and the becauses
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Angular2 Forms API method called by the view (NgControl) to register the
|
||||
* onChange event handler that updates the model (Control).
|
||||
* https://github.com/angular/angular/blob/master/modules/angular2/src/forms/directives/shared.ts#L27
|
||||
* @param {Function} fn the onChange event handler.
|
||||
*/
|
||||
registerOnChange(fn) { this.onChange = fn; }
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Angular2 Forms API method called by the the view (NgControl) to register
|
||||
* the onTouched event handler that marks model (Control) as touched.
|
||||
* @param {Function} fn onTouched event handler.
|
||||
*/
|
||||
registerOnTouched(fn) { this.onTouched = fn; }
|
||||
onTouched() {}
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
it('should check apple, enable/check grape, submit form', function() {
|
||||
element(by.css('[ngControl=appleCtrl] button')).click();
|
||||
element(by.css('[ngControl=appleCtrl]')).click();
|
||||
element(by.css('.e2eGrapeDisabled')).click();
|
||||
element(by.css('.e2eGrapeChecked')).click();
|
||||
element(by.css('.e2eSubmit')).click();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
import {
|
||||
Control,
|
||||
ControlGroup,
|
||||
@@ -16,9 +16,17 @@ import {
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
fruitsForm: ControlGroup;
|
||||
grapeDisabled: boolean;
|
||||
grapeChecked: boolean;
|
||||
kiwiModel: boolean;
|
||||
strawberryModel: boolean;
|
||||
standAloneChecked: boolean;
|
||||
formResults: string;
|
||||
|
||||
constructor() {
|
||||
this.fruitsForm = new ControlGroup({
|
||||
"appleCtrl": new Control(),
|
||||
"appleCtrl": new Control(true),
|
||||
"bananaCtrl": new Control(true),
|
||||
"cherryCtrl": new Control(false),
|
||||
"grapeCtrl": new Control(true)
|
||||
@@ -27,6 +35,9 @@ class E2EApp {
|
||||
this.grapeDisabled = true;
|
||||
this.grapeChecked = true;
|
||||
this.standAloneChecked = true;
|
||||
|
||||
this.kiwiModel = false;
|
||||
this.strawberryModel = true;
|
||||
}
|
||||
|
||||
toggleGrapeChecked() {
|
||||
|
||||
@@ -9,33 +9,33 @@
|
||||
<ion-list>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Apple, value=apple, init checked</ion-label>
|
||||
<ion-checkbox value="apple" checked="true" ngControl="appleCtrl"></ion-checkbox>
|
||||
<ion-label>Apple, ngControl</ion-label>
|
||||
<ion-checkbox ngControl="appleCtrl"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Banana, init no checked/value attributes</ion-label>
|
||||
<ion-label>Banana, ngControl</ion-label>
|
||||
<ion-checkbox ngControl="bananaCtrl"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Cherry, value=cherry, init disabled</ion-label>
|
||||
<ion-checkbox value="cherry" disabled="true" ngControl="cherryCtrl"></ion-checkbox>
|
||||
<ion-label>Cherry, ngControl, disabled</ion-label>
|
||||
<ion-checkbox disabled="true" ngControl="cherryCtrl"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Grape, value=grape, init checked, disabled</ion-label>
|
||||
<ion-checkbox value="grape" [checked]="grapeChecked" [disabled]="grapeDisabled" ngControl="grapeCtrl"></ion-checkbox>
|
||||
<ion-label>Grape, ngControl, checked, disabled</ion-label>
|
||||
<ion-checkbox [checked]="grapeChecked" [disabled]="grapeDisabled" ngControl="grapeCtrl"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>secondary color</ion-label>
|
||||
<ion-checkbox secondary checked="false"></ion-checkbox>
|
||||
<ion-label>Kiwi, NgModel false, Secondary color</ion-label>
|
||||
<ion-checkbox secondary [(ngModel)]="kiwiModel"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>light color</ion-label>
|
||||
<ion-checkbox light checked></ion-checkbox>
|
||||
<ion-label>Strawberry, NgModel true</ion-label>
|
||||
<ion-checkbox light [(ngModel)]="strawberryModel"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
</ion-list>
|
||||
@@ -62,6 +62,8 @@
|
||||
<code>cherry.value: {{fruitsForm.controls.cherryCtrl.value}}</code><br>
|
||||
<code>grape.dirty: {{fruitsForm.controls.grapeCtrl.dirty}}</code><br>
|
||||
<code>grape.value: {{fruitsForm.controls.grapeCtrl.value}}</code><br>
|
||||
<code>kiwiModel: {{kiwiModel}}</code><br>
|
||||
<code>strawberryModel: {{strawberryModel}}</code><br>
|
||||
</p>
|
||||
|
||||
<pre aria-hidden="true" padding>{{formResults}}</pre>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicApp} from 'ionic/ionic';
|
||||
import {App, IonicApp} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicApp} from 'ionic/ionic';
|
||||
import {App, IonicApp} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicApp} from 'ionic/ionic';
|
||||
import {App, IonicApp} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicApp} from 'ionic/ionic';
|
||||
import {App, IonicApp} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -43,8 +43,8 @@ export class Content extends Ion {
|
||||
scrollElement: HTMLElement;
|
||||
|
||||
/**
|
||||
* @param {ElementRef} elementRef A reference to the component's DOM element.
|
||||
* @param {Config} config The config object to change content's default settings.
|
||||
* @param {elementRef} elementRef A reference to the component's DOM element.
|
||||
* @param {config} config The config object to change content's default settings.
|
||||
*/
|
||||
constructor(
|
||||
private _elementRef: ElementRef,
|
||||
@@ -87,6 +87,7 @@ export class Content extends Ion {
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Adds the specified scroll handler to the content' scroll element.
|
||||
*
|
||||
* ```ts
|
||||
@@ -224,9 +225,9 @@ export class Content extends Ion {
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @param {Number} x The x-value to scroll to.
|
||||
* @param {Number} y The y-value to scroll to.
|
||||
* @param {Number} duration Duration of the scroll animation in ms.
|
||||
* @param {number} x The x-value to scroll to.
|
||||
* @param {number} y The y-value to scroll to.
|
||||
* @param {number} duration Duration of the scroll animation in ms.
|
||||
* @param {TODO} tolerance TODO
|
||||
* @returns {Promise} Returns a promise when done
|
||||
*/
|
||||
@@ -278,19 +279,19 @@ export class Content extends Ion {
|
||||
/**
|
||||
* @private
|
||||
* Returns the content and scroll elements' dimensions.
|
||||
* @returns {Object} dimensions The content and scroll elements' dimensions
|
||||
* {Number} dimensions.contentHeight content offsetHeight
|
||||
* {Number} dimensions.contentTop content offsetTop
|
||||
* {Number} dimensions.contentBottom content offsetTop+offsetHeight
|
||||
* {Number} dimensions.contentWidth content offsetWidth
|
||||
* {Number} dimensions.contentLeft content offsetLeft
|
||||
* {Number} dimensions.contentRight content offsetLeft + offsetWidth
|
||||
* {Number} dimensions.scrollHeight scroll scrollHeight
|
||||
* {Number} dimensions.scrollTop scroll scrollTop
|
||||
* {Number} dimensions.scrollBottom scroll scrollTop + scrollHeight
|
||||
* {Number} dimensions.scrollWidth scroll scrollWidth
|
||||
* {Number} dimensions.scrollLeft scroll scrollLeft
|
||||
* {Number} dimensions.scrollRight scroll scrollLeft + scrollWidth
|
||||
* @returns {object} dimensions The content and scroll elements' dimensions
|
||||
* {number} dimensions.contentHeight content offsetHeight
|
||||
* {number} dimensions.contentTop content offsetTop
|
||||
* {number} dimensions.contentBottom content offsetTop+offsetHeight
|
||||
* {number} dimensions.contentWidth content offsetWidth
|
||||
* {number} dimensions.contentLeft content offsetLeft
|
||||
* {number} dimensions.contentRight content offsetLeft + offsetWidth
|
||||
* {number} dimensions.scrollHeight scroll scrollHeight
|
||||
* {number} dimensions.scrollTop scroll scrollTop
|
||||
* {number} dimensions.scrollBottom scroll scrollTop + scrollHeight
|
||||
* {number} dimensions.scrollWidth scroll scrollWidth
|
||||
* {number} dimensions.scrollLeft scroll scrollLeft
|
||||
* {number} dimensions.scrollRight scroll scrollLeft + scrollWidth
|
||||
*/
|
||||
getContentDimensions() {
|
||||
let _scrollEle = this.scrollElement;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -30,15 +30,7 @@ import {Config} from '../../config/config';
|
||||
* <ion-icon name="logo-twitter"></ion-icon>
|
||||
* ```
|
||||
*
|
||||
* @property {string} [name] - Use the appropriate icon for the mode.
|
||||
* @property {string} [ios] - Explicitly set the icon to use on iOS.
|
||||
* @property {string} [md] - Explicitly set the icon to use on Android.
|
||||
* @property {boolean} [isActive] - Whether or not the icon has an "active"
|
||||
* appearance. On iOS an active icon is filled in or full appearance, and an
|
||||
* inactive icon on iOS will use an outlined version of the icon same icon.
|
||||
* Material Design icons do not change appearance depending if they're active
|
||||
* or not. The `isActive` property is largely used by the tabbar.
|
||||
* @demo /docs/v2/demos/icon/
|
||||
* @demo /docs/v2/demos/icon/
|
||||
* @see {@link /docs/v2/components#icons Icon Component Docs}
|
||||
*
|
||||
*/
|
||||
@@ -85,7 +77,7 @@ export class Icon {
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @input {string} Icon to use. Will load the appropriate icon for each mode
|
||||
*/
|
||||
@Input()
|
||||
get name(): string {
|
||||
@@ -103,7 +95,7 @@ export class Icon {
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @input {string} Explicitly set the icon to use on iOS
|
||||
*/
|
||||
@Input()
|
||||
get ios(): string {
|
||||
@@ -116,7 +108,7 @@ export class Icon {
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @input {string} Explicitly set the icon to use on MD
|
||||
*/
|
||||
@Input()
|
||||
get md(): string {
|
||||
@@ -128,8 +120,9 @@ export class Icon {
|
||||
this.update();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @input {bool} Whether or not the icon has an "active" appearance. On iOS an active icon is filled in or full appearance, and an inactive icon on iOS will use an outlined version of the icon same icon. Material Design icons do not change appearance depending if they're active or not. The `isActive` property is largely used by the tabbar.
|
||||
*/
|
||||
@Input()
|
||||
get isActive(): boolean {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -5,12 +5,18 @@
|
||||
|
||||
ion-input,
|
||||
ion-textarea {
|
||||
position: relative;
|
||||
display: block;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.item-input ion-input,
|
||||
.item-input ion-textarea {
|
||||
position: static;
|
||||
}
|
||||
|
||||
// Textarea Within An Item
|
||||
// --------------------------------------------------
|
||||
|
||||
|
||||
@@ -129,14 +129,14 @@ export class TextInput extends InputBase {
|
||||
* </ion-item>
|
||||
* ```
|
||||
*
|
||||
* @demo /docs/v2/demos/textarea/
|
||||
* @demo /docs/v2/demos/textarea/
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ion-textarea',
|
||||
template:
|
||||
'<textarea [(ngModel)]="_value" [placeholder]="placeholder" class="text-input"></textarea>' +
|
||||
'<input type="text" aria-hidden="true" next-input *ngIf="_useAssist">' +
|
||||
'<div (touchstart)="pointerStart($event)" (touchend)="pointerEnd($event)" (mousedown)="pointerStart($event)" (mouseup)="pointerEnd($event)" class="input-cover" *ngIf="_useAssist"></div>',
|
||||
'<div (touchstart)="pointerStart($event)" (touchend)="pointerEnd($event)" (mousedown)="pointerStart($event)" (mouseup)="pointerEnd($event)" class="input-cover" tappable *ngIf="_useAssist"></div>',
|
||||
directives: [
|
||||
NgIf,
|
||||
NextInput,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
import {FormBuilder, Validators} from 'angular2/common';
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {TextInput} from 'ionic/ionic';
|
||||
import {TextInput} from '../../../../ionic/ionic';
|
||||
|
||||
export function run() {
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ export class ItemSlidingGesture extends DragGesture {
|
||||
if (this.getOpenAmount(itemContainerEle) < (restingPoint / 2)) {
|
||||
|
||||
// If we are going left but too slow, or going right, go back to resting
|
||||
if (ev.direction & Hammer.DIRECTION_RIGHT || Math.abs(ev.velocityX) < 0.3) {
|
||||
if (ev.direction & DIRECTION_RIGHT || Math.abs(ev.velocityX) < 0.3) {
|
||||
restingPoint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,20 @@ ion-item-options .button {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
ion-item-sliding.active-slide {
|
||||
ion-item-options:not([icon-left]) .button-icon-left {
|
||||
font-size: 14px;
|
||||
|
||||
.button-inner {
|
||||
flex-direction: column;
|
||||
}
|
||||
ion-icon {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
padding-bottom: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
ion-item-sliding.active-slide {
|
||||
|
||||
.item,
|
||||
.item.activated {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
padding: 0;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
min-height: inherit;
|
||||
|
||||
flex: 1;
|
||||
flex-direction: inherit;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -88,4 +88,8 @@
|
||||
<button outline item-right (click)="testClick($event)">View</button>
|
||||
</ion-item>
|
||||
|
||||
<button ion-item *ngFor="#data of [0,1,2,3,4]; #i = index" [class.activated]="i == 1">
|
||||
<h3>ng-for {{i}}</h3>
|
||||
</button>
|
||||
|
||||
</ion-content>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, Page, NavController, NavParams} from 'ionic/ionic';
|
||||
import {App, Page, NavController, NavParams} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@Page({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, Page, IonicApp, Alert, NavController} from 'ionic/ionic';
|
||||
import {App, Page, IonicApp, Alert, NavController} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@Page({
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive(item)">Archive</button>
|
||||
<button danger (click)="del(item)"><ion-icon name="trash"></ion-icon></button>
|
||||
<button danger (click)="del(item)">
|
||||
<ion-icon name="trash"></ion-icon>
|
||||
</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
@@ -53,8 +55,10 @@
|
||||
<ion-icon name="mail" item-left></ion-icon>
|
||||
One Line w/ Icon, div only text
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive(item)">Archive</button>
|
||||
<ion-item-options icon-left>
|
||||
<button primary (click)="archive(item)">
|
||||
<ion-icon name="archive"></ion-icon>Archive
|
||||
</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
@@ -66,7 +70,16 @@
|
||||
One Line w/ Avatar, div only text
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive(item)">Archive</button>
|
||||
<button primary>
|
||||
<ion-icon name="more"></ion-icon>More
|
||||
</button>
|
||||
<button secondary (click)="archive(item)">
|
||||
<ion-icon name="archive"></ion-icon>Archive
|
||||
</button>
|
||||
<button danger (click)="del(item)">
|
||||
<ion-icon name="trash"></ion-icon>Delete
|
||||
</button>
|
||||
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
@@ -104,4 +117,4 @@
|
||||
img {
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-title>Icons</ion-title>
|
||||
</ion-toolbar>
|
||||
|
||||
<ion-content>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Username</ion-label>
|
||||
<ion-input></ion-input>
|
||||
</ion-item>
|
||||
|
||||
</ion-content>
|
||||
@@ -113,7 +113,7 @@ export class List extends Ion {
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @param {Boolean} shouldEnable whether the item-sliding should be enabled or not
|
||||
* @param {boolean} shouldEnable whether the item-sliding should be enabled or not
|
||||
*/
|
||||
enableSlidingItems(shouldEnable: boolean) {
|
||||
if (this._enableSliding !== shouldEnable) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,42 +1,9 @@
|
||||
import {ProtoViewRef, ViewContainerRef} from 'angular2/core'
|
||||
import {Directive, Host, forwardRef} from 'angular2/core';
|
||||
|
||||
import {App, List} from 'ionic/ionic';
|
||||
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html',
|
||||
directives: [forwardRef(() => ItemCellTemplate)]
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
constructor() {
|
||||
|
||||
this.items = []
|
||||
for(let i = 0; i < 1000; i++) {
|
||||
this.items.push({
|
||||
title: 'Item ' + i
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Used to find and register headers in a view, and this directive's
|
||||
content will be moved up to the common navbar location, and created
|
||||
using the same context as the view's content area.
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'template[cell]'
|
||||
})
|
||||
export class ItemCellTemplate {
|
||||
constructor(@Host() list: List, viewContainer: ViewContainerRef, protoViewRef: ProtoViewRef) {
|
||||
console.log('Item cell template', list, viewContainer, protoViewRef);
|
||||
|
||||
this.protoViewRef = protoViewRef;
|
||||
this.viewContainer = viewContainer;
|
||||
|
||||
list.setItemTemplate(this);
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
<ion-content padding #content>
|
||||
<ion-toolbar><ion-title>Infinite List</ion-title></ion-toolbar>
|
||||
|
||||
<ion-list inset virtual [items]="items" [content]="content">
|
||||
<ion-item *cell #item>
|
||||
{{item.title}}
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
<f style="height: 15000px; width: 100%; background-color: green"></f>
|
||||
<ion-content padding>
|
||||
|
||||
TODO
|
||||
|
||||
</ion-content>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
|
||||
@@ -120,7 +120,25 @@ import {MenuType} from './menu-types';
|
||||
* but this can be overriden using the `type` property:
|
||||
*
|
||||
* ```html
|
||||
* <ion-menu type="overlay" [content]="mycontent"></ion-menu>
|
||||
* <ion-menu type="overlay" [content]="mycontent">...</ion-menu>
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* ### Persistent Menus
|
||||
*
|
||||
* By default, menus, and specifically their menu toggle buttons in the navbar,
|
||||
* only show on the root page within its `NavController`. For example, on Page 1
|
||||
* the menu toggle will show in the navbar. However, when navigating to Page 2,
|
||||
* because it is not the root Page for that `NavController`, the menu toggle
|
||||
* will not show in the navbar.
|
||||
*
|
||||
* Not showing the menu toggle button in the navbar is commonly seen within
|
||||
* native apps after navigating past the root Page. However, it is still possible
|
||||
* to always show the menu toggle button in the navbar by setting
|
||||
* `persistent="true"` on the `ion-menu` component.
|
||||
*
|
||||
* ```html
|
||||
* <ion-menu persistent="true" [content]="content">...</ion-menu>
|
||||
* ```
|
||||
*
|
||||
* @demo /docs/v2/demos/menu/
|
||||
@@ -137,36 +155,54 @@ export class MenuController {
|
||||
* Progamatically open the Menu.
|
||||
* @return {Promise} returns a promise when the menu is fully opened
|
||||
*/
|
||||
open(menuId?: string) {
|
||||
open(menuId?: string): Promise<boolean> {
|
||||
let menu = this.get(menuId);
|
||||
if (menu) {
|
||||
return menu.open();
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Progamatically close the Menu.
|
||||
* Progamatically close the Menu. If no `menuId` is given as the first
|
||||
* argument then it'll close any menu which is open. If a `menuId`
|
||||
* is given then it'll close that exact menu.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {Promise} returns a promise when the menu is fully closed
|
||||
*/
|
||||
close(menuId?: string) {
|
||||
let menu = this.get(menuId);
|
||||
close(menuId?: string): Promise<boolean> {
|
||||
let menu: Menu;
|
||||
|
||||
if (menuId) {
|
||||
// find the menu by its id
|
||||
menu = this.get(menuId);
|
||||
|
||||
} else {
|
||||
// find the menu that is open
|
||||
menu = this._menus.find(m => m.isOpen);
|
||||
}
|
||||
|
||||
if (menu) {
|
||||
// close the menu
|
||||
return menu.close();
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the menu. If it's closed, it will open, and if opened, it will
|
||||
* close.
|
||||
* Toggle the menu. If it's closed, it will open, and if opened, it
|
||||
* will close.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {Promise} returns a promise when the menu has been toggled
|
||||
*/
|
||||
toggle(menuId?: string) {
|
||||
toggle(menuId?: string): Promise<boolean> {
|
||||
let menu = this.get(menuId);
|
||||
if (menu) {
|
||||
return menu.toggle();
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,7 +212,7 @@ export class MenuController {
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {Menu} Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
enable(shouldEnable: boolean, menuId?: string) {
|
||||
enable(shouldEnable: boolean, menuId?: string): Menu {
|
||||
let menu = this.get(menuId);
|
||||
if (menu) {
|
||||
return menu.enable(shouldEnable);
|
||||
@@ -189,7 +225,7 @@ export class MenuController {
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {Menu} Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
swipeEnable(shouldEnable: boolean, menuId?: string) {
|
||||
swipeEnable(shouldEnable: boolean, menuId?: string): Menu {
|
||||
let menu = this.get(menuId);
|
||||
if (menu) {
|
||||
return menu.swipeEnable(shouldEnable);
|
||||
@@ -197,7 +233,26 @@ export class MenuController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a menu instance.
|
||||
* @return {boolean} Returns true if the menu is currently open, otherwise false.
|
||||
*/
|
||||
isOpen(menuId?: string): boolean {
|
||||
let menu = this.get(menuId);
|
||||
return menu && menu.isOpen || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean} Returns true if the menu is currently enabled, otherwise false.
|
||||
*/
|
||||
isEnabled(menuId?: string): boolean {
|
||||
let menu = this.get(menuId);
|
||||
return menu && menu.enabled || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a menu instance. If a `menuId` is not provided then it'll return
|
||||
* the first menu found. If a `menuId` is provided, then it'll first try to find
|
||||
* the menu using the menu's `id` attribute. If a menu is not found using the `id`
|
||||
* attribute, then it'll try to find the menu by its `side` name.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {Menu} Returns the instance of the menu if found, otherwise `null`.
|
||||
*/
|
||||
@@ -216,6 +271,14 @@ export class MenuController {
|
||||
return (this._menus.length ? this._menus[0] : null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array<Menu>} Returns an array of all menu instances.
|
||||
*/
|
||||
getMenus(): Array<Menu> {
|
||||
return this._menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {Menu} from './menu';
|
||||
import {SlideEdgeGesture} from '../../gestures/slide-edge-gesture';
|
||||
|
||||
import {SlideData} from '../../gestures/slide-gesture';
|
||||
import {assign} from '../../util/util';
|
||||
|
||||
|
||||
@@ -17,15 +17,13 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
threshold: 0,
|
||||
maxEdgeStart: menu.maxEdgeStart || 75
|
||||
}, options));
|
||||
|
||||
this.listen();
|
||||
}
|
||||
|
||||
canStart(ev) {
|
||||
canStart(ev: any) {
|
||||
let menu = this.menu;
|
||||
|
||||
if (!menu.isEnabled || !menu.isSwipeEnabled) {
|
||||
console.debug('menu can not start, isEnabled:', menu.isEnabled, 'isSwipeEnabled:', menu.isSwipeEnabled, 'side:', menu.side);
|
||||
if (!menu.enabled || !menu.swipeEnabled) {
|
||||
console.debug('menu can not start, isEnabled:', menu.enabled, 'isSwipeEnabled:', menu.swipeEnabled, 'side:', menu.side);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -70,20 +68,20 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
}
|
||||
|
||||
// Set CSS, then wait one frame for it to apply before sliding starts
|
||||
onSlideBeforeStart(slide, ev) {
|
||||
onSlideBeforeStart(slide: SlideData, ev: any) {
|
||||
console.debug('menu gesture, onSlideBeforeStart', this.menu.side);
|
||||
this.menu.setProgressStart();
|
||||
this.menu.swipeStart();
|
||||
}
|
||||
|
||||
onSlide(slide, ev) {
|
||||
onSlide(slide: SlideData, ev: any) {
|
||||
let z = (this.menu.side === 'right' ? slide.min : slide.max);
|
||||
let stepValue = (slide.distance / z);
|
||||
console.debug('menu gesture, onSlide', this.menu.side, 'distance', slide.distance, 'min', slide.min, 'max', slide.max, 'z', z, 'stepValue', stepValue);
|
||||
|
||||
this.menu.setProgessStep(stepValue);
|
||||
this.menu.swipeProgress(stepValue);
|
||||
}
|
||||
|
||||
onSlideEnd(slide, ev) {
|
||||
onSlideEnd(slide: SlideData, ev: any) {
|
||||
let z = (this.menu.side === 'right' ? slide.min : slide.max);
|
||||
|
||||
let shouldComplete = (Math.abs(ev.velocityX) > 0.2) ||
|
||||
@@ -93,10 +91,10 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
|
||||
console.debug('menu gesture, onSlide', this.menu.side, 'distance', slide.distance, 'delta', slide.delta, 'velocityX', ev.velocityX, 'min', slide.min, 'max', slide.max, 'shouldComplete', shouldComplete, 'currentStepValue', currentStepValue);
|
||||
|
||||
this.menu.setProgressEnd(shouldComplete, currentStepValue);
|
||||
this.menu.swipeEnd(shouldComplete, currentStepValue);
|
||||
}
|
||||
|
||||
getElementStartPos(slide, ev) {
|
||||
getElementStartPos(slide: SlideData, ev: any) {
|
||||
if (this.menu.side === 'right') {
|
||||
// right menu
|
||||
return this.menu.isOpen ? slide.min : slide.max;
|
||||
|
||||
@@ -68,7 +68,17 @@ export class MenuToggle {
|
||||
*/
|
||||
get isHidden() {
|
||||
if (this._inNavbar && this._viewCtrl) {
|
||||
return !this._viewCtrl.isRoot();
|
||||
if (this._viewCtrl.isRoot()) {
|
||||
// this is the root view, so it should always show
|
||||
return false;
|
||||
}
|
||||
|
||||
let menu = this._menu.get(this.menuToggle);
|
||||
if (menu) {
|
||||
// this is not the root view, so see if this menu
|
||||
// is configured to still be enabled if it's not the root view
|
||||
return !menu.persistent;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ import {Config} from '../../config/config';
|
||||
import {Platform} from '../../platform/platform';
|
||||
import {Keyboard} from '../../util/keyboard';
|
||||
import {MenuContentGesture, MenuTargetGesture} from './menu-gestures';
|
||||
import {Gesture} from '../../gestures/gesture';
|
||||
import {MenuController} from './menu-controller';
|
||||
import {MenuType} from './menu-types';
|
||||
import {isFalseProperty} from '../../util/util';
|
||||
import {isTrueProperty} from '../../util/util';
|
||||
|
||||
|
||||
/**
|
||||
@@ -17,38 +16,30 @@ import {isFalseProperty} from '../../util/util';
|
||||
@Component({
|
||||
selector: 'ion-menu',
|
||||
host: {
|
||||
'role': 'navigation',
|
||||
'[attr.side]': 'side',
|
||||
'[attr.type]': 'type',
|
||||
'[attr.swipeEnabled]': 'swipeEnabled'
|
||||
'role': 'navigation'
|
||||
},
|
||||
template: '<ng-content></ng-content><div tappable disable-activated class="backdrop"></div>',
|
||||
template:
|
||||
'<ng-content></ng-content>' +
|
||||
'<div tappable disable-activated class="backdrop"></div>',
|
||||
directives: [forwardRef(() => MenuBackdrop)]
|
||||
})
|
||||
export class Menu extends Ion {
|
||||
private _preventTime: number = 0;
|
||||
private _cntEle: HTMLElement;
|
||||
private _cntGesture: Gesture;
|
||||
private _menuGesture: Gesture;
|
||||
private _cntGesture: MenuTargetGesture;
|
||||
private _menuGesture: MenuContentGesture;
|
||||
private _type: MenuType;
|
||||
private _resizeUnreg: Function;
|
||||
|
||||
private _isEnabled: boolean = true;
|
||||
private _isSwipeEnabled: boolean = true;
|
||||
private _isPers: boolean = false;
|
||||
private _init: boolean = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
isOpen: boolean = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
isEnabled: boolean = true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
isSwipeEnabled: boolean = true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -59,7 +50,6 @@ export class Menu extends Ion {
|
||||
*/
|
||||
onContentClick: EventListener;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -83,17 +73,50 @@ export class Menu extends Ion {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Input() swipeEnabled: any;
|
||||
@Input()
|
||||
get enabled(): boolean {
|
||||
return this._isEnabled;
|
||||
}
|
||||
|
||||
set enabled(val: boolean) {
|
||||
this._isEnabled = isTrueProperty(val);
|
||||
this._setListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Input() maxEdgeStart;
|
||||
@Input()
|
||||
get swipeEnabled(): boolean {
|
||||
return this._isSwipeEnabled;
|
||||
}
|
||||
|
||||
set swipeEnabled(val: boolean) {
|
||||
this._isSwipeEnabled = isTrueProperty(val);
|
||||
this._setListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Output() opening: EventEmitter<any> = new EventEmitter();
|
||||
@Input()
|
||||
get persistent(): boolean {
|
||||
return this._isPers;
|
||||
}
|
||||
|
||||
set persistent(val: boolean) {
|
||||
this._isPers = isTrueProperty(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Input() maxEdgeStart: number;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Output() opening: EventEmitter<number> = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
private _menuCtrl: MenuController,
|
||||
@@ -112,6 +135,8 @@ export class Menu extends Ion {
|
||||
*/
|
||||
ngOnInit() {
|
||||
let self = this;
|
||||
self._init = true;
|
||||
|
||||
let content = self.content;
|
||||
self._cntEle = (content instanceof Node) ? content : content && content.getNativeElement && content.getNativeElement();
|
||||
|
||||
@@ -132,23 +157,29 @@ export class Menu extends Ion {
|
||||
}
|
||||
self._renderer.setElementAttribute(self._elementRef.nativeElement, 'type', self.type);
|
||||
|
||||
// add the gesture listeners
|
||||
self._zone.runOutsideAngular(function() {
|
||||
self._cntGesture = new MenuContentGesture(self, self.getContentElement());
|
||||
self._menuGesture = new MenuTargetGesture(self, self.getNativeElement());
|
||||
// add the gestures
|
||||
self._cntGesture = new MenuContentGesture(self, self.getContentElement());
|
||||
self._menuGesture = new MenuTargetGesture(self, self.getNativeElement());
|
||||
|
||||
self.onContentClick = function(ev: UIEvent) {
|
||||
if (self.isEnabled) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
self.close();
|
||||
}
|
||||
};
|
||||
// register listeners if this menu is enabled
|
||||
// check if more than one menu is on the same side
|
||||
let hasEnabledSameSideMenu = self._menuCtrl.getMenus().some(m => {
|
||||
return m.side === self.side && m.enabled;
|
||||
});
|
||||
|
||||
if (isFalseProperty(self.swipeEnabled)) {
|
||||
self.isSwipeEnabled = false;
|
||||
if (hasEnabledSameSideMenu) {
|
||||
// auto-disable if another menu on the same side is already enabled
|
||||
self._isEnabled = false;
|
||||
}
|
||||
self._setListeners();
|
||||
|
||||
// create a reusable click handler on this instance, but don't assign yet
|
||||
self.onContentClick = function(ev: UIEvent) {
|
||||
if (self._isEnabled) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
self.close();
|
||||
}
|
||||
};
|
||||
|
||||
self._cntEle.classList.add('menu-content');
|
||||
self._cntEle.classList.add('menu-content-' + self.type);
|
||||
@@ -157,6 +188,32 @@ export class Menu extends Ion {
|
||||
self._menuCtrl.register(self);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private _setListeners() {
|
||||
let self = this;
|
||||
|
||||
if (self._init) {
|
||||
// only listen/unlisten if the menu has initialized
|
||||
|
||||
if (self._isEnabled && self._isSwipeEnabled && !self._cntGesture.isListening) {
|
||||
// should listen, but is not currently listening
|
||||
console.debug('menu, gesture listen', self.side);
|
||||
self._zone.runOutsideAngular(function() {
|
||||
self._cntGesture.listen();
|
||||
self._menuGesture.listen();
|
||||
});
|
||||
|
||||
} else if (self._cntGesture.isListening && (!self._isEnabled || !self._isSwipeEnabled)) {
|
||||
// should not listen, but is currently listening
|
||||
console.debug('menu, gesture unlisten', self.side);
|
||||
self._cntGesture.unlisten();
|
||||
self._menuGesture.unlisten();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -176,7 +233,7 @@ export class Menu extends Ion {
|
||||
* @param {boolean} shouldOpen If the Menu is open or not.
|
||||
* @return {Promise} returns a promise once set
|
||||
*/
|
||||
setOpen(shouldOpen): Promise<boolean> {
|
||||
setOpen(shouldOpen: boolean): Promise<boolean> {
|
||||
// _isPrevented is used to prevent unwanted opening/closing after swiping open/close
|
||||
// or swiping open the menu while pressing down on the menuToggle button
|
||||
if ((shouldOpen && this.isOpen) || this._isPrevented()) {
|
||||
@@ -196,9 +253,9 @@ export class Menu extends Ion {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
setProgressStart() {
|
||||
swipeStart() {
|
||||
// user started swiping the menu open/close
|
||||
if (this._isPrevented() || !this.isEnabled || !this.isSwipeEnabled) return;
|
||||
if (this._isPrevented() || !this._isEnabled || !this._isSwipeEnabled) return;
|
||||
|
||||
this._before();
|
||||
this._getType().setProgressStart(this.isOpen);
|
||||
@@ -207,9 +264,9 @@ export class Menu extends Ion {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
setProgessStep(stepValue: number) {
|
||||
swipeProgress(stepValue: number) {
|
||||
// user actively dragging the menu
|
||||
if (this.isEnabled && this.isSwipeEnabled) {
|
||||
if (this._isEnabled && this._isSwipeEnabled) {
|
||||
this._prevent();
|
||||
this._getType().setProgessStep(stepValue);
|
||||
this.opening.next(stepValue);
|
||||
@@ -219,12 +276,12 @@ export class Menu extends Ion {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
setProgressEnd(shouldComplete: boolean, currentStepValue: number) {
|
||||
swipeEnd(shouldComplete: boolean, currentStepValue: number) {
|
||||
// user has finished dragging the menu
|
||||
if (this.isEnabled && this.isSwipeEnabled) {
|
||||
if (this._isEnabled && this._isSwipeEnabled) {
|
||||
this._prevent();
|
||||
this._getType().setProgressEnd(shouldComplete, currentStepValue, (isOpen) => {
|
||||
console.debug('menu, progress end', this.side);
|
||||
console.debug('menu, swipeEnd', this.side);
|
||||
this._after(isOpen);
|
||||
});
|
||||
}
|
||||
@@ -236,7 +293,7 @@ export class Menu extends Ion {
|
||||
private _before() {
|
||||
// this places the menu into the correct location before it animates in
|
||||
// this css class doesn't actually kick off any animations
|
||||
if (this.isEnabled) {
|
||||
if (this._isEnabled) {
|
||||
this.getNativeElement().classList.add('show-menu');
|
||||
this.getBackdropElement().classList.add('show-backdrop');
|
||||
|
||||
@@ -252,7 +309,7 @@ export class Menu extends Ion {
|
||||
// keep opening/closing the menu disabled for a touch more yet
|
||||
// only add listeners/css if it's enabled and isOpen
|
||||
// and only remove listeners/css if it's not open
|
||||
if ((this.isEnabled && isOpen) || !isOpen) {
|
||||
if ((this._isEnabled && isOpen) || !isOpen) {
|
||||
this._prevent();
|
||||
|
||||
this.isOpen = isOpen;
|
||||
@@ -318,7 +375,7 @@ export class Menu extends Ion {
|
||||
* @return {Menu} Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
enable(shouldEnable: boolean): Menu {
|
||||
this.isEnabled = shouldEnable;
|
||||
this.enabled = shouldEnable;
|
||||
if (!shouldEnable && this.isOpen) {
|
||||
this.close();
|
||||
}
|
||||
@@ -331,7 +388,7 @@ export class Menu extends Ion {
|
||||
* @return {Menu} Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
swipeEnable(shouldEnable: boolean): Menu {
|
||||
this.isSwipeEnabled = shouldEnable;
|
||||
this.swipeEnabled = shouldEnable;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ it('should toggle open menu', function() {
|
||||
|
||||
|
||||
it('should close menu', function() {
|
||||
element(by.css('[menuClose=left]')).click();
|
||||
element(by.css('.e2eCloseLeftMenu')).click();
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicApp, MenuController, Page, NavController, Alert} from 'ionic/ionic';
|
||||
import {App, IonicApp, MenuController, Page, NavController, Alert} from '../../../../../ionic/ionic';
|
||||
|
||||
|
||||
@Page({
|
||||
@@ -37,10 +37,12 @@ class Page2 {
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
rootPage;
|
||||
changeDetectionCount: number = 0;
|
||||
pages: Array<{title: string, component: any}>;
|
||||
|
||||
constructor(private app: IonicApp, private menu: MenuController) {
|
||||
this.rootView = Page1;
|
||||
this.changeDetectionCount = 0;
|
||||
this.rootPage = Page1;
|
||||
|
||||
this.pages = [
|
||||
{ title: 'Page 1', component: Page1 },
|
||||
@@ -56,7 +58,7 @@ class E2EApp {
|
||||
nav.setRoot(page.component).then(() => {
|
||||
// wait for the root page to be completely loaded
|
||||
// then close the menu
|
||||
this.menu.close('left');
|
||||
this.menu.close();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ion-menu [content]="content" side="left">
|
||||
<ion-menu [content]="content" side="left" persistent="true">
|
||||
|
||||
<ion-toolbar secondary>
|
||||
<ion-title>Left Menu</ion-title>
|
||||
@@ -12,7 +12,7 @@
|
||||
{{p.title}}
|
||||
</button>
|
||||
|
||||
<button ion-item menuClose="left" detail-none>
|
||||
<button ion-item menuClose="left" class="e2eCloseLeftMenu" detail-none>
|
||||
Close Menu
|
||||
</button>
|
||||
|
||||
@@ -138,6 +138,6 @@
|
||||
|
||||
</ion-menu>
|
||||
|
||||
<ion-nav id="nav" [root]="rootView" #content swipe-back-enabled="false"></ion-nav>
|
||||
<ion-nav id="nav" [root]="rootPage" #content swipe-back-enabled="false"></ion-nav>
|
||||
|
||||
<div [hidden]="isChangeDetecting()"></div>
|
||||
@@ -1,6 +1,10 @@
|
||||
|
||||
<ion-navbar *navbar>
|
||||
|
||||
<button menuToggle="left">
|
||||
<ion-icon name="menu"></ion-icon>
|
||||
</button>
|
||||
|
||||
<ion-title>
|
||||
Menu
|
||||
</ion-title>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user