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

View File

@ -79,8 +79,15 @@ export let Collide = {
rootPropertyValueCache: {},
/* 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 */

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

View File

@ -23,6 +23,7 @@ export function processElement(action, animation, elementIndex, clearCache) {
var elements = animation._ele;
var elementsLength = elements.length;
var element = elements[elementIndex];
var eleData;
var opts = animation._options;
var propertiesMap = animation._properties;
@ -50,9 +51,16 @@ export function processElement(action, animation, elementIndex, clearCache) {
******************/
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
@ -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)
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. */
var eleData = data(element);
eleData = data(element);
if (clearCache) {
eleData.tweensContainer = undefined;
} 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. */
/* 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. */
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.');
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
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. */
rootPropertyValue = data(element).rootPropertyValueCache[rootProperty];
rootPropertyValue = eleData.rootPropertyValueCache[rootProperty];
/* If values were not transferred from a previous Collide call, query the DOM as needed. */
} 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. */
if (opts.queue === '') {
data(element).tweensContainer = tweensContainer;
data(element).opts = opts;
eleData.tweensContainer = tweensContainer;
eleData.opts = opts;
}
}

View File

@ -109,6 +109,20 @@ function tick(timestamp) {
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;

View File

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

View File

@ -1,14 +1,14 @@
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
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';
@Component()
@View({
templateUrl: 'pages/second-page.html',
directives: [Header, Toolbar]
directives: [Header, Toolbar, ToolbarTitle]
})
export class SecondPage {
constructor(

View File

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

View File

@ -39,6 +39,7 @@ $toolbar-ios-button-background-color: transparent !default;
.toolbar [side="primary"] {
@include flex-order(map-get($toolbar-order-ios, 'primary'));
}
.toolbar [side="secondary"] {
@include flex-order(map-get($toolbar-order-ios, 'secondary'));
}
@ -46,8 +47,10 @@ $toolbar-ios-button-background-color: transparent !default;
ion-title {
@include flex-order(map-get($toolbar-order-ios, 'title'));
font-size: $toolbar-ios-title-font-size;
font-weight: 500;
text-align: center;
}
.toolbar-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 {
/*@include flex-display();
@include flex-direction(row);
@include flex-align-items(center);
@include flex-justify-content(space-between);*/
@include flex-justify-content(space-between);
// by default ion-toolbar is hidden
// and the transition animation will display it
// by default ion-toolbar is display:none and
// the transition animation will add the show class
display: none;
&.show-toolbar {
@include flex-display();
}
}
// buttons are primary by default
ion-toolbar .button,
ion-toolbar [side="primary"] {
@ -40,7 +44,7 @@ ion-toolbar [side="secondary"] {
@include flex-order(map-get($toolbar-order-core, 'secondary'));
}
.toolbar-title.toolbar-title {
ion-title {
// double selector to override the following
@include flex-display();
@include flex(1);

View File

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

View File

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