refactor(content): add dimension read/write methods

This commit is contained in:
Adam Bradley
2016-06-17 15:23:08 -05:00
parent 1d8ba4a5e7
commit 1986710537
3 changed files with 130 additions and 105 deletions

View File

@@ -1,12 +1,14 @@
import {Component, ElementRef, Optional, NgZone, ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
import {Ion} from '../ion';
import {App} from '../app/app';
import {Ion} from '../ion';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {nativeRaf, nativeTimeout, transitionEnd} from '../../util/dom';
import {ViewController} from '../nav/view-controller';
import {ScrollView} from '../../util/scroll-view';
import {Tabs} from '../tabs/tabs';
import {ViewController} from '../nav/view-controller';
/**
* @name Content
@@ -57,9 +59,14 @@ import {ScrollView} from '../../util/scroll-view';
}
})
export class Content extends Ion {
private _paddingTop: number = 0;
private _paddingBottom: number = 0;
private _scrollPadding: number = 0;
private _computedTop: number;
private _computedBottom: number;
private _paddingTop: number;
private _paddingBottom: number;
private _scrollPadding: number;
private _headerHeight: number;
private _footerHeight: number;
private _tabbarOnTop: boolean = null;
private _inputPolling: boolean = false;
private _scroll: ScrollView;
private _scLsn: Function;
@@ -72,7 +79,8 @@ export class Content extends Ion {
private _app: App,
private _keyboard: Keyboard,
private _zone: NgZone,
@Optional() viewCtrl: ViewController
@Optional() viewCtrl: ViewController,
@Optional() private _tabs: Tabs
) {
super(_elementRef);
this._sbPadding = _config.getBoolean('statusbarPadding', false);
@@ -308,6 +316,7 @@ export class Content extends Ion {
/**
* @private
* DOM WRITE
*/
addCssClass(className: string) {
this.getNativeElement().classList.add(className);
@@ -315,6 +324,7 @@ export class Content extends Ion {
/**
* @private
* DOM WRITE
*/
removeCssClass(className: string) {
this.getNativeElement().classList.remove(className);
@@ -322,6 +332,7 @@ export class Content extends Ion {
/**
* @private
* DOM WRITE
*/
setScrollElementStyle(prop: string, val: any) {
this._scrollEle.style[prop] = val;
@@ -368,6 +379,7 @@ export class Content extends Ion {
/**
* @private
* DOM WRITE
* Adds padding to the bottom of the scroll element when the keyboard is open
* so content below the keyboard can be scrolled into view.
*/
@@ -382,16 +394,7 @@ export class Content extends Ion {
/**
* @private
*/
setContentPadding(paddingTop: number, paddingBottom: number) {
this._paddingTop = paddingTop;
this._paddingBottom = paddingBottom;
this._scrollEle.style.paddingTop = (paddingTop > 0 ? paddingTop + 'px' : '');
this._scrollEle.style.paddingBottom = (paddingBottom > 0 ? paddingBottom + 'px' : '');
}
/**
* @private
* DOM WRITE
*/
clearScrollPaddingFocusOut() {
if (!this._inputPolling) {
@@ -406,4 +409,97 @@ export class Content extends Ion {
}
}
/**
* @private
* DOM READ
*/
readDimensions() {
this._computedTop = 0 ;
this._computedBottom = 0;
this._paddingTop = 0;
this._paddingBottom = 0;
this._headerHeight = 0;
this._footerHeight = 0;
let ele: HTMLElement = this._elementRef.nativeElement;
let parentEle: HTMLElement = ele.parentElement;
let computedStyle: any;
for (var i = 0; i < parentEle.children.length; i++) {
ele = <HTMLElement>parentEle.children[i];
if (ele.tagName === 'ION-CONTENT') {
computedStyle = getComputedStyle(ele);
this._computedTop = parsePxUnit(computedStyle.paddingTop);
this._paddingTop += this._computedTop;
this._computedBottom = parsePxUnit(computedStyle.paddingBottom);
this._paddingBottom += this._computedBottom;
} else if (ele.tagName === 'ION-HEADER') {
this._headerHeight = ele.clientHeight;
this._paddingTop += this._headerHeight;
} else if (ele.tagName === 'ION-FOOTER') {
this._footerHeight = ele.clientHeight;
this._paddingBottom += this._footerHeight;
}
}
ele = parentEle;
let tabbarEle: HTMLElement;
let tabbarOnTop: boolean;
while (ele && ele.tagName !== 'ION-MODAL' && !ele.classList.contains('tab-subpage')) {
if (ele.tagName === 'ION-TABS') {
tabbarEle = <HTMLElement>ele.firstElementChild;
tabbarOnTop = ele.getAttribute('tabbarplacement') === 'top';
if (tabbarOnTop) {
this._paddingTop += tabbarEle.clientHeight;
} else {
this._paddingBottom += tabbarEle.clientHeight;
}
if (this._tabbarOnTop === null) {
// this is the first tabbar found, remember it's position
this._tabbarOnTop = tabbarOnTop;
}
}
ele = ele.parentElement;
}
}
/**
* @private
* DOM WRITE
*/
writeDimensions() {
// only add inline padding styles if the computed padding value, which would
// have come from the app's css, is different than the new padding value
if (this._paddingTop !== this._computedTop) {
this._scrollEle.style.paddingTop = (this._paddingTop > 0 ? this._paddingTop + 'px' : '');
}
if (this._paddingBottom !== this._computedBottom) {
this._scrollEle.style.paddingBottom = (this._paddingBottom > 0 ? this._paddingBottom + 'px' : '');
}
if (this._tabbarOnTop && this._tabs) {
if (this._tabbarOnTop) {
this._tabs.setTabbarPosition(this._headerHeight, -1);
} else {
this._tabs.setTabbarPosition(-1, 0);
}
}
}
}
function parsePxUnit(val: string): number {
return (val.indexOf('px') > 0) ? parseInt(val, 10) : 0;
}

View File

@@ -8,25 +8,31 @@ import {Navbar} from '../navbar/navbar';
import {ViewController} from '../nav/view-controller';
/**
* @private
*/
@Directive({
selector: 'ion-header'
})
export class Header {
constructor(@Optional() viewCtr: ViewController) {
viewCtr && viewCtr.setHeader(this);
constructor(@Optional() viewCtrl: ViewController) {
viewCtrl && viewCtrl.setHeader(this);
}
}
/**
* @private
*/
@Directive({
selector: 'ion-footer'
})
export class Footer {
constructor(@Optional() viewCtr: ViewController) {
viewCtr && viewCtr.setFooter(this);
constructor(@Optional() viewCtrl: ViewController) {
viewCtrl && viewCtrl.setFooter(this);
}
}

View File

@@ -11,11 +11,6 @@ import {ViewController} from '../components/nav/view-controller';
*/
export class PageTransition extends Transition {
enteringPage: Animation;
paddingTop = 0;
paddingBottom = 0;
headerHeight = 0;
footerHeight = 0;
tabbarOnTop: boolean = null;
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(enteringView, leavingView, opts);
@@ -25,97 +20,26 @@ export class PageTransition extends Transition {
this.add(this.enteringPage);
this.before.addDomReadFn(this.readDimensions.bind(this));
this.before.addDomWriteFn(this.writeContentPadding.bind(this));
this.before.addDomWriteFn(this.writeDimensions.bind(this));
}
/**
* DOM READ
*/
readDimensions() {
let pageElementRef = this.enteringView.pageRef();
if (!pageElementRef) return;
let pageEle = <HTMLElement>pageElementRef.nativeElement;
if (pageEle.tagName !== 'ION-PAGE') {
pageEle = <HTMLElement>pageEle.querySelector('ion-page');
if (!pageEle) {
return;
}
}
let ele: HTMLElement;
let computedStyle: any;
for (var i = 0; i < pageEle.children.length; i++) {
ele = <HTMLElement>pageEle.children[i];
if (ele.tagName === 'ION-CONTENT') {
computedStyle = getComputedStyle(ele);
this.paddingTop += parsePxUnit(computedStyle.paddingTop);
this.paddingBottom += parsePxUnit(computedStyle.paddingBottom);
} else if (ele.tagName === 'ION-HEADER') {
this.headerHeight = ele.clientHeight;
this.paddingTop += this.headerHeight;
} else if (ele.tagName === 'ION-FOOTER') {
this.footerHeight = ele.clientHeight;
this.paddingBottom += this.footerHeight;
}
}
ele = pageEle;
let tabbarEle: HTMLElement;
let tabbarOnTop: boolean;
while (ele && ele.tagName !== 'ION-MODAL' && !ele.classList.contains('tab-subpage')) {
if (ele.tagName === 'ION-TABS') {
tabbarEle = <HTMLElement>ele.firstElementChild;
tabbarOnTop = ele.getAttribute('tabbarplacement') === 'top';
if (tabbarOnTop) {
this.paddingTop += tabbarEle.clientHeight;
} else {
this.paddingBottom += tabbarEle.clientHeight;
}
if (this.tabbarOnTop === null) {
// this is the first tabbar found, remember it's position
this.tabbarOnTop = tabbarOnTop;
}
}
ele = ele.parentElement;
let content = <Content>this.enteringView.getContent();
if (content && content instanceof Content) {
content.readDimensions();
}
}
/**
* DOM WRITE
*/
writeContentPadding() {
if (this.paddingTop || this.paddingBottom) {
let content = <Content>this.enteringView.getContent();
if (content && content instanceof Content) {
content.setContentPadding(this.paddingTop, this.paddingBottom);
}
}
if (this.tabbarOnTop !== null) {
let tab = this.enteringView.getNav();
if (tab && tab.parent) {
let tabs = <Tabs>tab.parent;
if (tabs instanceof Tabs) {
if (this.tabbarOnTop) {
tabs.setTabbarPosition(this.headerHeight, -1);
} else {
tabs.setTabbarPosition(-1, 0);
}
}
}
writeDimensions() {
let content = <Content>this.enteringView.getContent();
if (content && content instanceof Content) {
content.writeDimensions();
}
}
@@ -129,4 +53,3 @@ export class PageTransition extends Transition {
function parsePxUnit(val: string): number {
return (val.indexOf('px') > 0) ? parseInt(val, 10) : 0;
}