From 5c06eaff7e15b1bc9efd08892782f03f6ea25e77 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Jun 2015 15:03:05 -0500 Subject: [PATCH] house of pane --- ionic/components/app/structure.scss | 14 +--- ionic/components/app/test/hn/pages/single.js | 2 +- ionic/components/app/util.scss | 25 +++++++ ionic/components/nav/nav-base.js | 67 ++++++++++--------- ionic/components/nav/nav-item.js | 6 +- ionic/components/nav/nav.js | 3 +- ionic/components/nav/{nav-pane.js => pane.js} | 34 +++++----- ionic/components/nav/swipe-handle.js | 32 +++++---- ionic/components/split-view/split-view.js | 1 - ionic/components/tabs/tab.js | 10 ++- ionic/components/tabs/tabs.js | 1 - ionic/components/tabs/test/advanced/main.html | 3 +- .../tabs/test/advanced/pages/tabs.html | 12 +--- scripts/e2e/angular.template.html | 6 ++ 14 files changed, 118 insertions(+), 98 deletions(-) rename ionic/components/nav/{nav-pane.js => pane.js} (63%) diff --git a/ionic/components/app/structure.scss b/ionic/components/app/structure.scss index 0142e46d74..3a7d7499b8 100644 --- a/ionic/components/app/structure.scss +++ b/ionic/components/app/structure.scss @@ -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 { diff --git a/ionic/components/app/test/hn/pages/single.js b/ionic/components/app/test/hn/pages/single.js index 1050740678..04be7b8cee 100644 --- a/ionic/components/app/test/hn/pages/single.js +++ b/ionic/components/app/test/hn/pages/single.js @@ -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' diff --git a/ionic/components/app/util.scss b/ionic/components/app/util.scss index 9e1cbd2e85..78f9cab6ce 100644 --- a/ionic/components/app/util.scss +++ b/ionic/components/app/util.scss @@ -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 diff --git a/ionic/components/nav/nav-base.js b/ionic/components/nav/nav-base.js index 435c2ef9ee..638c05299b 100644 --- a/ionic/components/nav/nav-base.js +++ b/ionic/components/nav/nav-base.js @@ -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; diff --git a/ionic/components/nav/nav-item.js b/ionic/components/nav/nav-item.js index cbaa3890b6..1ab13365df 100644 --- a/ionic/components/nav/nav-item.js +++ b/ionic/components/nav/nav-item.js @@ -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 diff --git a/ionic/components/nav/nav.js b/ionic/components/nav/nav.js index 57ea0fb829..238e1a90d2 100644 --- a/ionic/components/nav/nav.js +++ b/ionic/components/nav/nav.js @@ -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'; diff --git a/ionic/components/nav/nav-pane.js b/ionic/components/nav/pane.js similarity index 63% rename from ionic/components/nav/nav-pane.js rename to ionic/components/nav/pane.js index b619f2b3c9..195c931399 100644 --- a/ionic/components/nav/nav-pane.js +++ b/ionic/components/nav/pane.js @@ -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: ` - +
+
`, - 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: ` `, - 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; } diff --git a/ionic/components/nav/swipe-handle.js b/ionic/components/nav/swipe-handle.js index 6226c66450..37e2b184ff 100644 --- a/ionic/components/nav/swipe-handle.js +++ b/ionic/components/nav/swipe-handle.js @@ -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); + } + } diff --git a/ionic/components/split-view/split-view.js b/ionic/components/split-view/split-view.js index e8f0fed47c..8234350b49 100644 --- a/ionic/components/split-view/split-view.js +++ b/ionic/components/split-view/split-view.js @@ -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 diff --git a/ionic/components/tabs/tab.js b/ionic/components/tabs/tab.js index 15ce3e2f6f..54f52737df 100644 --- a/ionic/components/tabs/tab.js +++ b/ionic/components/tabs/tab.js @@ -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); diff --git a/ionic/components/tabs/tabs.js b/ionic/components/tabs/tabs.js index 2028a9ad8f..e1e4a6a188 100644 --- a/ionic/components/tabs/tabs.js +++ b/ionic/components/tabs/tabs.js @@ -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'; diff --git a/ionic/components/tabs/test/advanced/main.html b/ionic/components/tabs/test/advanced/main.html index 282773a6ce..94cd0153aa 100644 --- a/ionic/components/tabs/test/advanced/main.html +++ b/ionic/components/tabs/test/advanced/main.html @@ -1,3 +1,2 @@ - - + diff --git a/ionic/components/tabs/test/advanced/pages/tabs.html b/ionic/components/tabs/test/advanced/pages/tabs.html index abad0e52ab..82fb5b1c71 100644 --- a/ionic/components/tabs/test/advanced/pages/tabs.html +++ b/ionic/components/tabs/test/advanced/pages/tabs.html @@ -1,16 +1,8 @@ - - + - - + - - diff --git a/scripts/e2e/angular.template.html b/scripts/e2e/angular.template.html index 84c768eb71..697929f664 100644 --- a/scripts/e2e/angular.template.html +++ b/scripts/e2e/angular.template.html @@ -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; + }