betterz iOS toolbars

This commit is contained in:
Adam Bradley
2015-05-15 12:25:24 -05:00
parent ba6561cbe2
commit 0032858e38
12 changed files with 118 additions and 38 deletions

View File

@ -18,6 +18,12 @@ export class Animation {
this.children = []; this.children = [];
this._addStartClasses = [];
this._removeStartClasses = [];
this._addEndClasses = [];
this._removeEndClasses = [];
this.elements(ele); this.elements(ele);
} }
@ -53,7 +59,7 @@ export class Animation {
return this; return this;
} }
_setupElements(clearCache, onNextFrame) { _prepare(clearCache, onNextFrame) {
// ensure another animation wasnt about to start // ensure another animation wasnt about to start
if (this._nextAF) { if (this._nextAF) {
@ -105,7 +111,7 @@ export class Animation {
this._options = util.extend(opts, this._options); this._options = util.extend(opts, this._options);
// get the elements ready // get the elements ready
for (var i = 0, ii = this._ele.length; i < ii; i++) { for (let i = 0, ii = this._ele.length; i < ii; i++) {
processElement('start', this, i, clearCache); processElement('start', this, i, clearCache);
} }
@ -118,7 +124,7 @@ export class Animation {
return Promise.resolve(); return Promise.resolve();
} }
_queueAnimation() { _queue() {
if (this._ele.length) { if (this._ele.length) {
if (this._call === null) { if (this._call === null) {
@ -173,9 +179,9 @@ export class Animation {
var clearCache = (this._aniType !== 'start'); var clearCache = (this._aniType !== 'start');
var promise = this._setupElements(clearCache, () => { var promise = this._prepare(clearCache, () => {
this._aniType = 'start'; this._aniType = 'start';
this._queueAnimation(); this._queue();
}); });
promises.push(promise); promises.push(promise);
@ -193,7 +199,7 @@ export class Animation {
var clearCache = (this._aniType !== 'progress'); var clearCache = (this._aniType !== 'progress');
var promise = this._setupElements(clearCache, () => { var promise = this._prepare(clearCache, () => {
this._aniType = 'progress'; this._aniType = 'progress';
}); });
@ -212,7 +218,7 @@ export class Animation {
this.children[i].progress(value); this.children[i].progress(value);
} }
this._queueAnimation(); this._queue();
} }
} }
@ -228,6 +234,26 @@ export class Animation {
return this; return this;
} }
addStartClass(className) {
this._addStartClasses.push(className);
return this;
}
removeStartClass(className) {
this._removeStartClasses.push(className);
return this;
}
addEndClass(className) {
this._addEndClasses.push(className);
return this;
}
removeEndClass(className) {
this._removeEndClasses.push(className);
return this;
}
isAnimating() { isAnimating() {
var eleData; var eleData;
if (this._ele) { if (this._ele) {

View File

@ -79,8 +79,15 @@ export let Collide = {
rootPropertyValueCache: {}, rootPropertyValueCache: {},
/* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */ /* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */
transformCache: {} transformCache: {},
startAddCls: null,
startRmvCls: null,
endAddCls: null,
endRmvCls: null
}; };
return element.$collide;
}, },
/* get/set element data */ /* get/set element data */

View File

@ -46,6 +46,20 @@ export function completeCall(callIndex, isStopped) {
} }
} }
if (eleData.endAddCls) {
for (var k = 0; k < eleData.endAddCls.length; k++) {
element.classList.add(eleData.endAddCls[k]);
}
eleData.endAddCls = null;
}
if (eleData.endRmvCls) {
for (var k = 0; k < eleData.endRmvCls.length; k++) {
element.classList.remove(eleData.endRmvCls[k]);
}
eleData.endRmvCls = null;
}
/* If the element's queue is empty (if only the 'inprogress' item is left at position 0) or if its queue is about to run /* If the element's queue is empty (if only the 'inprogress' item is left at position 0) or if its queue is about to run
a non-Collide-initiated entry, turn off the isAnimating flag. A non-Collide-initiatied queue entry's logic might alter a non-Collide-initiated entry, turn off the isAnimating flag. A non-Collide-initiatied queue entry's logic might alter
an element's CSS values and thereby cause Collide's cached value data to go stale. To detect if a queue entry was initiated by Collide, an element's CSS values and thereby cause Collide's cached value data to go stale. To detect if a queue entry was initiated by Collide,

View File

@ -23,6 +23,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
var elements = animation._ele; var elements = animation._ele;
var elementsLength = elements.length; var elementsLength = elements.length;
var element = elements[elementIndex]; var element = elements[elementIndex];
var eleData;
var opts = animation._options; var opts = animation._options;
var propertiesMap = animation._properties; var propertiesMap = animation._properties;
@ -50,9 +51,16 @@ export function processElement(action, animation, elementIndex, clearCache) {
******************/ ******************/
if (data(element) === undefined) { if (data(element) === undefined) {
Collide.initData(element); eleData = Collide.initData(element);
} else {
eleData = data(element);
} }
if (animation._addStartClasses.length) eleData.startAddCls = animation._addStartClasses.slice();
if (animation._removeStartClasses.length) eleData.startRmvCls = animation._removeStartClasses.slice();
if (animation._addEndClasses.length) eleData.endAddCls = animation._addEndClasses.slice();
if (animation._removeEndClasses.length) eleData.endRmvCls = animation._removeEndClasses.slice();
/****************** /******************
Option: Delay Option: Delay
@ -236,7 +244,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
/* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale) /* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale)
to transfer over end values to use as start values. If it's set to true and there is a previous to transfer over end values to use as start values. If it's set to true and there is a previous
Collide call to pull values from, do so. */ Collide call to pull values from, do so. */
var eleData = data(element); eleData = data(element);
if (clearCache) { if (clearCache) {
eleData.tweensContainer = undefined; eleData.tweensContainer = undefined;
} else if (eleData.tweensContainer && eleData.isAnimating === true) { } else if (eleData.tweensContainer && eleData.isAnimating === true) {
@ -345,7 +353,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */ Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */
/* Note: Since SVG elements have some of their properties directly applied as HTML attributes, /* Note: Since SVG elements have some of their properties directly applied as HTML attributes,
there is no way to check for their explicit browser support, and so we skip skip this check for them. */ there is no way to check for their explicit browser support, and so we skip skip this check for them. */
if (!data(element).isSVG && rootProperty !== 'tween' && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) { if (!eleData.isSVG && rootProperty !== 'tween' && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) {
if (Collide.debug) console.log('Skipping [' + rootProperty + '] due to a lack of browser support.'); if (Collide.debug) console.log('Skipping [' + rootProperty + '] due to a lack of browser support.');
continue; continue;
} }
@ -370,7 +378,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
/* The previous call's rootPropertyValue is extracted from the element's data cache since that's the /* The previous call's rootPropertyValue is extracted from the element's data cache since that's the
instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue
attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */ attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */
rootPropertyValue = data(element).rootPropertyValueCache[rootProperty]; rootPropertyValue = eleData.rootPropertyValueCache[rootProperty];
/* If values were not transferred from a previous Collide call, query the DOM as needed. */ /* If values were not transferred from a previous Collide call, query the DOM as needed. */
} else { } else {
@ -607,8 +615,8 @@ export function processElement(action, animation, elementIndex, clearCache) {
/* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */ /* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */
if (opts.queue === '') { if (opts.queue === '') {
data(element).tweensContainer = tweensContainer; eleData.tweensContainer = tweensContainer;
data(element).opts = opts; eleData.opts = opts;
} }
} }

View File

@ -109,6 +109,20 @@ function tick(timestamp) {
continue; continue;
} }
if (eleData.startAddCls) {
for (var k = 0; k < eleData.startAddCls.length; k++) {
element.classList.add(eleData.startAddCls[k]);
}
eleData.startAddCls = null;
}
if (eleData.startRmvCls) {
for (var k = 0; k < eleData.startRmvCls.length; k++) {
element.classList.remove(eleData.startRmvCls[k]);
}
eleData.startRmvCls = null;
}
var transformPropertyExists = false; var transformPropertyExists = false;

View File

@ -76,6 +76,10 @@ ion-toolbar {
// by default .nav-item is hidden // by default .nav-item is hidden
// and the transition animation will display it // and the transition animation will display it
display: none; display: none;
&.show-nav-item {
display: block;
}
} }
ion-content { ion-content {

View File

@ -1,14 +1,14 @@
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view'; import {View} from 'angular2/src/core/annotations_impl/view';
import {NavController, NavParams, Header, Toolbar} from 'ionic/ionic'; import {NavController, NavParams, Header, Toolbar, ToolbarTitle} from 'ionic/ionic';
import {ThirdPage} from './third-page'; import {ThirdPage} from './third-page';
@Component() @Component()
@View({ @View({
templateUrl: 'pages/second-page.html', templateUrl: 'pages/second-page.html',
directives: [Header, Toolbar] directives: [Header, Toolbar, ToolbarTitle]
}) })
export class SecondPage { export class SecondPage {
constructor( constructor(

View File

@ -1,13 +1,13 @@
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view'; import {View} from 'angular2/src/core/annotations_impl/view';
import {NavController, Header, Toolbar} from 'ionic/ionic'; import {NavController, Header, Toolbar, ToolbarTitle} from 'ionic/ionic';
@Component() @Component()
@View({ @View({
templateUrl: 'pages/third-page.html', templateUrl: 'pages/third-page.html',
directives: [Header, Toolbar] directives: [Header, Toolbar, ToolbarTitle]
}) })
export class ThirdPage { export class ThirdPage {
constructor( constructor(

View File

@ -39,6 +39,7 @@ $toolbar-ios-button-background-color: transparent !default;
.toolbar [side="primary"] { .toolbar [side="primary"] {
@include flex-order(map-get($toolbar-order-ios, 'primary')); @include flex-order(map-get($toolbar-order-ios, 'primary'));
} }
.toolbar [side="secondary"] { .toolbar [side="secondary"] {
@include flex-order(map-get($toolbar-order-ios, 'secondary')); @include flex-order(map-get($toolbar-order-ios, 'secondary'));
} }
@ -46,8 +47,10 @@ $toolbar-ios-button-background-color: transparent !default;
ion-title { ion-title {
@include flex-order(map-get($toolbar-order-ios, 'title')); @include flex-order(map-get($toolbar-order-ios, 'title'));
font-size: $toolbar-ios-title-font-size; font-size: $toolbar-ios-title-font-size;
font-weight: 500;
text-align: center; text-align: center;
} }
.toolbar-back-button { .toolbar-back-button {
@include flex-order(map-get($toolbar-order-ios, 'back-button')); @include flex-order(map-get($toolbar-order-ios, 'back-button'));
} }

View File

@ -20,16 +20,20 @@ $toolbar-secondary-flex-order: 10;
} }
ion-toolbar { ion-toolbar {
/*@include flex-display();
@include flex-direction(row); @include flex-direction(row);
@include flex-align-items(center); @include flex-align-items(center);
@include flex-justify-content(space-between);*/ @include flex-justify-content(space-between);
// by default ion-toolbar is hidden // by default ion-toolbar is display:none and
// and the transition animation will display it // the transition animation will add the show class
display: none; display: none;
&.show-toolbar {
@include flex-display();
}
} }
// buttons are primary by default // buttons are primary by default
ion-toolbar .button, ion-toolbar .button,
ion-toolbar [side="primary"] { ion-toolbar [side="primary"] {
@ -40,7 +44,7 @@ ion-toolbar [side="secondary"] {
@include flex-order(map-get($toolbar-order-core, 'secondary')); @include flex-order(map-get($toolbar-order-core, 'secondary'));
} }
.toolbar-title.toolbar-title { ion-title {
// double selector to override the following // double selector to override the following
@include flex-display(); @include flex-display();
@include flex(1); @include flex(1);

View File

@ -44,26 +44,26 @@ class IOSTransition extends Animation {
// entering item moves to center // entering item moves to center
// before starting, set enteringItem to display: block // before starting, set enteringItem to display: block
enteringContent enteringContent
.display('block') .addStartClass('show-nav-item')
.to(TRANSLATE_X, 0) .to(TRANSLATE_X, 0)
.to(OPACITY, 1); .to(OPACITY, 1);
enteringToolbars enteringToolbars
.display('block') .addStartClass('show-toolbar')
.to(TRANSLATE_X, 0) .to(TRANSLATE_X, 0)
.to(OPACITY, 1); .to(OPACITY, 1);
// leaving view moves off screen // leaving view moves off screen
// when completed, set leavingItem to display: none // when completed, set leavingItem to display: none
leavingContent leavingContent
.removeEndClass('show-nav-item')
.from(TRANSLATE_X, 0) .from(TRANSLATE_X, 0)
.from(OPACITY, 1) .from(OPACITY, 1);
.display('none');
leavingToolbars leavingToolbars
.removeEndClass('show-toolbar')
.from(TRANSLATE_X, 0) .from(TRANSLATE_X, 0)
.from(OPACITY, 1) .from(OPACITY, 1);
.display('none');
// set properties depending on direction // set properties depending on direction
if (opts.direction === 'back') { if (opts.direction === 'back') {

View File

@ -10,26 +10,26 @@ class NoneTransition {
// show entering contet // show entering contet
let enteringContent = enteringItem.getContent(); let enteringContent = enteringItem.getContent();
enteringContent.style.display = 'block'; enteringContent.classList.add('show-nav-item');
enteringContent.style.transform = 'translateX(0%)'; enteringContent.style.transform = 'translateX(0%)';
// show entering headers // show entering headers
let toolbarElements = enteringItem.getToolbars(); let enteringToolbars = enteringItem.getToolbars();
for (let i = 0; i < toolbarElements.length; i++) { for (let i = 0; i < enteringToolbars.length; i++) {
toolbarElements[i].style.display = 'block'; enteringToolbars[i].classList.add('show-toolbar');
toolbarElements[i].style.transform = 'translateX(0%)'; enteringToolbars[i].style.transform = 'translateX(0%)';
} }
// hide the leaving item // hide the leaving item
if (leavingItem) { if (leavingItem) {
let leavingContent = leavingItem.getContent(); let leavingContent = leavingItem.getContent();
if (leavingContent) { if (leavingContent) {
leavingContent.style.display = ''; leavingContent.classList.remove('show-nav-item');
} }
let leavingHeaderElements = leavingItem.getToolbars(); let leavingToolbars = leavingItem.getToolbars();
for (let i = 0; i < leavingHeaderElements.length; i++) { for (let i = 0; i < leavingToolbars.length; i++) {
leavingHeaderElements[i].style.display = ''; leavingToolbars[i].classList.remove('show-toolbar');
} }
} }
} }