house of pane

This commit is contained in:
Adam Bradley
2015-06-05 15:03:05 -05:00
parent 4fa2e42a9f
commit 5c06eaff7e
14 changed files with 118 additions and 98 deletions

View File

@ -28,7 +28,7 @@ ion-nav {
height: 100%;
}
ion-nav-pane {
ion-pane {
position: absolute;
top: 0;
right: 0;
@ -98,18 +98,6 @@ ion-content {
will-change: scroll-position;
}
$swipe-handle-width: 20px !default;
swipe-handle {
position: absolute;
top: 0;
left: 0;
display: block;
width: $swipe-handle-width;
height: 100%;
z-index: $z-index-swipe-handle;
}
// Hardware Acceleration
.transitioning {

View File

@ -3,7 +3,7 @@ import {Ancestor} from 'angular2/src/core/annotations_impl/visibility';
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view';
import {NavController, NavParams, NavbarTemplate, Navbar, Content, Nav, NavPane, List, Item} from 'ionic/ionic';
import {NavController, NavParams, NavbarTemplate, Navbar, Content, Nav, List, Item} from 'ionic/ionic';
import {HackerNews} from '../hn'

View File

@ -93,6 +93,31 @@ $content-padding: 10px !default;
}
// Swipe Handle
// --------------------------------------------------
$swipe-handle-width: 20px !default;
$swipe-handle-top: 80px !default;
$swipe-handle-bottom: 80px !default;
.swipe-handle {
position: absolute;
top: $swipe-handle-top;
left: 0;
bottom: $swipe-handle-bottom;
width: $swipe-handle-width;
z-index: $z-index-swipe-handle;
background: red;
opacity: 0.2;
transform: translate3d(-999px, 0px, 0px);
&.show-handle {
transform: translate3d(0px, 0px, 0px);
}
}
// Node Inserted Animation
// --------------------------------------------------
// Used by the toolbar to know when the title has been rendered

View File

@ -11,22 +11,22 @@ import {bind} from 'angular2/di';
import {NavController} from './nav-controller';
import {NavItem, NavParams} from './nav-item';
import {NavPane, NavBarSection} from './nav-pane';
import {Pane, NavBarSection} from './pane';
import {Transition, ClickBlock} from 'ionic/ionic';
import * as util from 'ionic/util';
let itemsIds = -1;
export class NavBase {
constructor(
parentNavBase: NavBase,
parent: NavBase,
compiler: Compiler,
elementRef: ElementRef,
loader: DynamicComponentLoader,
injector: Injector
) {
this.parent = parent;
this.compiler = compiler;
this.elementRef = elementRef;
this.domElement = elementRef.domElement;
@ -39,7 +39,7 @@ export class NavBase {
this.sbActive = false;
this.panes = {};
this.id = ++itemsIds;
this.id = ++itemIds;
this.childIds = -1;
}
@ -52,9 +52,9 @@ export class NavBase {
}
getPane(itemStructure, callback) {
// this gets or creates the NavPane which similar nav items live in
// Nav items with just a navbar/content would all use the same NavPane
// Tabs and view's without a navbar would get a different NavPanes
// this gets or creates the Pane which similar nav items live in
// Nav items with just a navbar/content would all use the same Pane
// Tabs and view's without a navbar would get a different Panes
if (this.panes[itemStructure.key]) {
// nav pane which the entering component already exists
@ -64,34 +64,38 @@ export class NavBase {
// create a new nav pane
this.panes[itemStructure.key] = null;
// add a NavPane element
// when the NavPane is added, it'll also add its reference to the panes object
this.loader.loadNextToExistingLocation(NavPane, this.anchorElementRef, null).then(() => {
let injector = this.injector.resolveAndCreateChild([
bind(NavBase).toValue(this)
]);
// get the navPane reference by name
let navPane = this.panes[itemStructure.key];
// add a Pane element
// when the Pane is added, it'll also add its reference to the panes object
this.loader.loadNextToExistingLocation(Pane, this.anchorElementRef, injector).then(() => {
// get the element inside the NavPane to add sections to
let sectionViewContainerRef = navPane.sectionAnchorElementRef;
// get the pane reference by name
let pane = this.panes[itemStructure.key];
// get the element inside the Pane to add sections to
let sectionViewContainerRef = pane.sectionAnchorElementRef;
let promises = [];
let sectionsToAdd = []
// decide which sections should be added to this NavPane, ie: nav bars, tab bars, etc.
// decide which sections should be added to this Pane, ie: nav bars, tab bars, etc.
// add only the sections it needs
if (itemStructure.navbar) {
sectionsToAdd.push(NavBarSection);
}
// add the sections which this type of NavPane requires
// add the sections which this type of Pane requires
sectionsToAdd.forEach(SectionClass => {
// as each section is compiled and added to the NavPane
// the section will add a reference to itself in the NavPane's sections object
// as each section is compiled and added to the Pane
// the section will add a reference to itself in the Pane's sections object
promises.push( this.loader.loadNextToExistingLocation(SectionClass, sectionViewContainerRef, null) );
});
// wait for all of the sections to resolve
Promise.all(promises).then(() => {
callback(navPane);
callback(pane);
});
});
@ -99,10 +103,10 @@ export class NavBase {
}
}
addPane(navPane) {
addPane(pane) {
for (let np in this.panes) {
if (this.panes[np] === null) {
this.panes[np] = navPane;
this.panes[np] = pane;
return;
}
}
@ -384,6 +388,16 @@ export class NavBase {
}
}
swipeBackEnabled() {
if (this.items.length > 1) {
let activeItem = this.getActive();
if (activeItem) {
return activeItem.enableBack;
}
}
return false;
}
transitionStart(opts) {
if (opts.isAnimated) {
// block possible clicks during transition
@ -513,7 +527,7 @@ export class NavBase {
instances.push(item.instance);
}
}
return instances
return instances;
}
isActive(item) {
@ -528,14 +542,6 @@ export class NavBase {
return this.domElement.offsetWidth;
}
get swipeBackEnabled() {
// let activeItem = this.nav.getActive();
// if (activeItem) {
// return activeItem.enableBack;
// }
return false;
}
}
const ACTIVE_STATE = 1;
@ -545,3 +551,4 @@ const STAGED_LEAVING_STATE = 4;
const ACTIVELY_ENTERING_STATE = 5;
const ACTIVELY_LEAVING_STATE = 6;
let itemIds = -1;

View File

@ -4,9 +4,7 @@ import {bind} from 'angular2/di';
import * as util from 'ionic/util';
import {NavController} from './nav-controller';
import {Nav} from './nav';
import {NavBase} from './nav-base';
import {TabPane, NavPane, NavPaneSection} from './nav';
export class NavItem {
@ -34,7 +32,7 @@ export class NavItem {
stage(callback) {
// update if it's possible to go back from this nav item
//this.enableBack = !!this.navBase.getPrevious(this);
this.enableBack = !!this.navBase.getPrevious(this);
if (this.instance) {
// already compiled this view
@ -48,7 +46,7 @@ export class NavItem {
// does it have a navbar? Is it tabs? Should it not have a navbar or any toolbars?
let itemStructure = getProtoViewStructure(componentProtoViewRef);
// get the appropriate NavPane which this NavItem will fit into
// get the appropriate Pane which this NavItem will fit into
this.navBase.getPane(itemStructure, pane => {
// create a new injector just for this NavItem

View File

@ -1,6 +1,6 @@
import {Parent} from 'angular2/src/core/annotations_impl/visibility';
import {Component, Directive, onInit} from 'angular2/src/core/annotations_impl/annotations';
import {Optional} from 'angular2/src/di/annotations_impl'
import {Optional} from 'angular2/src/di/annotations_impl';
import {View} from 'angular2/src/core/annotations_impl/view';
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
@ -9,7 +9,6 @@ import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
import {Compiler} from 'angular2/angular2';
import {NavBase} from './nav-base';
import {SwipeHandle} from './swipe-handle';
import {IonicComponent} from '../../config/component';

View File

@ -5,19 +5,21 @@ import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
import {Nav} from './nav';
import {SwipeHandle} from './swipe-handle';
@Component({selector:'ion-nav-pane'})
@Component({selector:'ion-pane'})
@View({
template: `
<template nav-section-anchor></template>
<template pane-anchor></template>
<section class="content-container">
<template content-anchor></template>
<div class="swipe-handle"></div>
</section>
`,
directives: [NavPaneSectionAnchor, NavContentAnchor]
directives: [PaneAnchor, PaneContentAnchor, SwipeHandle]
})
export class NavPane {
export class Pane {
constructor(@Parent() nav: Nav, viewContainerRef: ViewContainerRef) {
this.viewContainerRef = viewContainerRef;
this.sections = {};
@ -30,11 +32,11 @@ export class NavPane {
@Directive({
selector: 'template[nav-section-anchor]'
selector: 'template[pane-anchor]'
})
class NavPaneSectionAnchor {
constructor(@Parent() navPane: NavPane, elementRef: ElementRef) {
navPane.sectionAnchorElementRef = elementRef;
class PaneAnchor {
constructor(@Parent() pane: Pane, elementRef: ElementRef) {
pane.sectionAnchorElementRef = elementRef;
}
}
@ -42,9 +44,9 @@ class NavPaneSectionAnchor {
@Directive({
selector: 'template[content-anchor]'
})
class NavContentAnchor {
constructor(@Parent() navPane: NavPane, viewContainerRef: ViewContainerRef) {
navPane.contentContainerRef = viewContainerRef;
class PaneContentAnchor {
constructor(@Parent() pane: Pane, viewContainerRef: ViewContainerRef) {
pane.contentContainerRef = viewContainerRef;
}
}
@ -58,12 +60,12 @@ class NavContentAnchor {
template: `
<template section-anchor></template>
`,
directives: [NavBarSectionAnchor]
directives: [PaneSectionAnchor]
})
export class NavBarSection {
constructor(@Parent() navPane: NavPane, viewContainerRef: ViewContainerRef, elementRef: ElementRef) {
this.navPane = navPane;
navPane.addSection('navbar', this);
constructor(@Parent() pane: Pane, viewContainerRef: ViewContainerRef, elementRef: ElementRef) {
this.pane = pane;
pane.addSection('navbar', this);
}
}
@ -72,7 +74,7 @@ export class NavBarSection {
@Directive({
selector: 'template[section-anchor]'
})
class NavBarSectionAnchor {
class PaneSectionAnchor {
constructor(@Parent() navBarSection: NavBarSection, viewContainerRef: ViewContainerRef) {
navBarSection.viewContainerRef = viewContainerRef;
}

View File

@ -1,23 +1,27 @@
import {ElementRef} from 'angular2/angular2'
import {Parent} from 'angular2/src/core/annotations_impl/visibility';
import {Directive} from 'angular2/src/core/annotations_impl/annotations';
import {Optional} from 'angular2/src/di/annotations_impl';
import {Gesture} from 'ionic/gestures/gesture';
import {Nav} from './nav';
import {NavBase} from './nav-base';
@Directive({
selector: 'swipe-handle',
selector: '.swipe-handle',
hostProperties: {
'!nav.swipeBackEnabled': 'hidden'
'showHandle()': 'class.show-handle'
}
})
export class SwipeHandle {
constructor(@Parent() nav: Nav, elementRef: ElementRef) {
constructor(
@Optional() navBase: NavBase,
elementRef: ElementRef
) {
if (!navBase) return;
this.navBase = navBase;
let gesture = new Gesture(elementRef.domElement);
this.nav = nav;
gesture.listen();
gesture.on('panend', onDragEnd);
@ -58,7 +62,7 @@ export class SwipeHandle {
}
}
nav.swipeBackEnd(completeSwipeBack, progress, playbackRate);
navBase.swipeBackEnd(completeSwipeBack, progress, playbackRate);
startX = null;
}
@ -69,14 +73,18 @@ export class SwipeHandle {
ev.stopPropagation();
startX = ev.gesture.center.x;
swipeableAreaWidth = nav.width() - startX;
swipeableAreaWidth = navBase.width() - startX;
nav.swipeBackStart();
navBase.swipeBackStart();
}
nav.swipeBackProgress( (ev.gesture.center.x - startX) / swipeableAreaWidth );
navBase.swipeBackProgress( (ev.gesture.center.x - startX) / swipeableAreaWidth );
}
}
showHandle() {
return (this.navBase ? this.navBase.swipeBackEnabled() : false);
}
}

View File

@ -1,6 +1,5 @@
import {Component, Parent, Decorator, View, NgElement} from 'angular2/angular2'
import {Nav} from 'ionic/components/nav/nav'
//import {NavPane} from 'ionic/components/nav-pane/nav-pane'
import * as util from 'ionic/util'
// TODO consider more explicit API, a la tabs

View File

@ -43,7 +43,6 @@ import {IonicComponent} from 'ionic/config/component';
export class Tab {
constructor(
@Parent() tabs: Tabs,
@Optional() parentNavBase: NavBase,
compiler: Compiler,
elementRef: ElementRef,
loader: DynamicComponentLoader,
@ -51,13 +50,12 @@ export class Tab {
viewContainerRef: ViewContainerRef
) {
this.navBase = new NavBase(parentNavBase, compiler, elementRef, loader, injector);
this.parentNavBase = parentNavBase;
if (parentNavBase) {
this.sections = parentNavBase.panes['_n'].sections;
this.navBase = new NavBase(tabs.navBase, compiler, elementRef, loader, injector);
if (tabs.navBase.parent) {
this.sections = tabs.navBase.parent.panes['_n'].sections;
}
this.item = new NavItem(parentNavBase);
this.item = new NavItem(this.navBase);
this.item.setInstance(this);
this.item.setViewElement(elementRef.domElement);
tabs.add(this.item);

View File

@ -13,7 +13,6 @@ import {IonicComponent} from '../../config/component';
import {Tab} from './tab';
import {TabButton} from './tab-button';
import {Icon} from '../icon/icon';
import {Nav, NavPane} from '../nav/nav';
import {NavItem} from '../nav/nav-item';
import {NavBase} from '../nav/nav-base';

View File

@ -1,3 +1,2 @@
<ion-nav [initial]="initial">
</ion-nav>
<ion-nav [initial]="initial"></ion-nav>

View File

@ -1,16 +1,8 @@
<ion-tabs>
<ion-tab [initial]="tab1Initial" tab-title="Tab 1" tab-icon="ion-home">
</ion-tab>
<ion-tab [initial]="tab1Initial" tab-title="Tab 1" tab-icon="ion-home"></ion-tab>
<ion-tab [initial]="tab2Initial" tab-title="Tab 2" tab-icon="ion-star" class="tab2">
</ion-tab>
<ion-tab [initial]="tab2Initial" tab-title="Tab 2" tab-icon="ion-star" class="tab2"></ion-tab>
</ion-tabs>
<style>
.tab2 f {
background: green
}
</style>

View File

@ -19,6 +19,12 @@
f:last-of-type {
background: red;
}
ion-tab:nth-of-type(2) f {
background: green;
}
ion-tab:nth-of-type(3) f {
background: yellow;
}
</style>
</head>
<body>