Merge branch '2.0' into pr/5379

# Conflicts:
#	ionic/components/slides/slides.ts
This commit is contained in:
Brandy Carney
2016-02-17 15:30:13 -05:00
214 changed files with 4647 additions and 1658 deletions

View File

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

View File

@@ -1,6 +1,6 @@
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](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.

View File

@@ -1,3 +1,7 @@
general:
branches:
ignore:
- ins_n_outs
machine:
node:
version: 4.1.0

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {App, Page, ActionSheet, NavController} from 'ionic/ionic';
import {App, Page, ActionSheet, NavController} from '../../../../../ionic/ionic';
@Page({

View File

@@ -94,6 +94,12 @@ ion-alert {
text-align: $alert-ios-message-text-align;
}
.alert-message {
&:empty {
padding: 0 0 12px 0;
}
}
// iOS Alert Input
// --------------------------------------------------

View File

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

View File

@@ -52,10 +52,6 @@ ion-alert {
.alert-message {
overflow: auto;
&:empty {
padding: 0;
}
}
.alert-input {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {App, Page, Animation} from 'ionic/ionic';
import {App, Page, Animation} from '../../../../../ionic/ionic';
@Page({

View File

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

View File

@@ -1,4 +1,4 @@
import {App, IonicApp} from 'ionic/ionic';
import {App, IonicApp} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App, IonicApp} from 'ionic/ionic';
import {App, IonicApp} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {App, IonicApp} from 'ionic/ionic';
import {App, IonicApp} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {Button, Config} from 'ionic/ionic';
import {Button, Config} from '../../../../ionic/ionic';
export function run() {

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {App, IonicApp} from 'ionic/ionic';
import {App, IonicApp} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App, IonicApp} from 'ionic/ionic';
import {App, IonicApp} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App, IonicApp} from 'ionic/ionic';
import {App, IonicApp} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App, IonicApp} from 'ionic/ionic';
import {App, IonicApp} from '../../../../../ionic/ionic';
@App({

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
import {FormBuilder, Validators} from 'angular2/common';

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {TextInput} from 'ionic/ionic';
import {TextInput} from '../../../../ionic/ionic';
export function run() {

View File

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

View File

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

View File

@@ -30,6 +30,7 @@
padding: 0;
border: 0;
overflow: hidden;
min-height: inherit;
flex: 1;
flex-direction: inherit;

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App, Page, NavController, NavParams} from 'ionic/ionic';
import {App, Page, NavController, NavParams} from '../../../../../ionic/ionic';
@Page({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App, Page, IonicApp, Alert, NavController} from 'ionic/ionic';
import {App, Page, IonicApp, Alert, NavController} from '../../../../../ionic/ionic';
@Page({

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

@@ -1,4 +1,4 @@
import {App} from 'ionic/ionic';
import {App} from '../../../../../ionic/ionic';
@App({

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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