diff --git a/ionic/components/nav-bar/nav-bar.js b/ionic/components/nav-bar/nav-bar.js
index 9607fb9997..2d714d051c 100644
--- a/ionic/components/nav-bar/nav-bar.js
+++ b/ionic/components/nav-bar/nav-bar.js
@@ -1,3 +1,4 @@
+import {Parent} 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 {ElementRef} from 'angular2/src/core/compiler/element_ref';
@@ -38,7 +39,9 @@ import * as dom from '../../util/dom';
})
export class Navbar {
constructor(item: ViewItem, elementRef: ElementRef) {
- item.navbarElement(elementRef.domElement);
+ this.element = elementRef.domElement;
+ this.itemElements = [];
+ item.navbarView(this);
}
}
@@ -49,9 +52,9 @@ export class Navbar {
}
})
class BackButton {
- constructor(item: ViewItem, elementRef: ElementRef) {
+ constructor(@Parent() navbar: Navbar, item: ViewItem, elementRef: ElementRef) {
this.item = item;
- item.backButtonElement(elementRef.domElement);
+ navbar.backButtonElement = elementRef.domElement;
}
goBack(ev) {
@@ -65,8 +68,8 @@ class BackButton {
selector: '.navbar-title'
})
export class Title {
- constructor(item: ViewItem, elementRef: ElementRef) {
- item.titleElement(elementRef.domElement);
+ constructor(@Parent() navbar: Navbar, elementRef: ElementRef) {
+ navbar.titleElement = elementRef.domElement;
}
}
@@ -74,8 +77,8 @@ export class Title {
selector: '.navbar-item'
})
export class NavbarItem {
- constructor(item: ViewItem, elementRef: ElementRef) {
- item.navbarItemElements(elementRef.domElement);
+ constructor(@Parent() navbar: Navbar, elementRef: ElementRef) {
+ navbar.itemElements.push(elementRef.domElement);
}
}
diff --git a/ionic/components/tabs/tab.js b/ionic/components/tabs/tab.js
index 5df4ed97e1..c6c92b4bb4 100644
--- a/ionic/components/tabs/tab.js
+++ b/ionic/components/tabs/tab.js
@@ -8,8 +8,8 @@ import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_compone
import {Injector} from 'angular2/di';
import {ViewController} from '../view/view-controller';
-import {Tabs} from './tabs';
import {ViewItem} from '../view/view-item';
+import {Tabs} from './tabs';
import {Content} from '../content/content';
import {IonicComponent} from '../../config/component';
@@ -32,10 +32,7 @@ import {IonicComponent} from '../../config/component';
}
})
@View({
- template: `
-
-
- `,
+ template: '',
directives: [TabPaneAnchor]
})
export class Tab extends ViewController {
@@ -53,26 +50,32 @@ export class Tab extends ViewController {
super(tabs, compiler, elementRef, loader, injector);
this.tabs = tabs;
- // the navbar is already provided by the container of Tabs, which contains Tab
- // Views which come into this Tab should not create their own navbar, but use the parent's
- this.parentNavbar(true);
+ this.childNavbar(true);
let item = this.item = new ViewItem(tabs.parent);
item.setInstance(this);
item.setViewElement(elementRef.domElement);
- tabs.addTab(this.item);
+ tabs.addTab(this);
+
+ this.navbarView = item.navbarView = () => {
+ let activeItem = this.getActive();
+ return (activeItem && activeItem.navbarView()) || {};
+ };
this.panelId = 'tab-panel-' + item.id;
this.labeledBy = 'tab-button-' + item.id;
}
onInit() {
- if ( this.item._initial ) {
- this.tabs.select(this);
+ if (this._initialResolve) {
+ this.tabs.select(this).then(() => {
+ this._initialResolve();
+ this._initialResolve = null;
+ });
}
}
- loadInitial(callback) {
+ load(callback) {
if (!this._loaded && this.initial) {
let opts = {
animate: false,
@@ -88,6 +91,11 @@ export class Tab extends ViewController {
}
}
+ queueInitial() {
+ // this Tab will be used as the initial one for the first load of Tabs
+ return new Promise(res => { this._initialResolve = res; });
+ }
+
get isSelected() {
return this.tabs.isActive(this.item);
}
diff --git a/ionic/components/tabs/tabs.js b/ionic/components/tabs/tabs.js
index b05b1cdc2d..4be21ae67f 100644
--- a/ionic/components/tabs/tabs.js
+++ b/ionic/components/tabs/tabs.js
@@ -47,15 +47,26 @@ import {Config} from '../../config/component';
export class Tabs extends ViewController {
constructor(
- @Optional() viewCtrl: ViewController,
- @Optional() item: ViewItem,
+ @Optional() parentViewCtrl: ViewController,
+ @Optional() viewItem: ViewItem,
compiler: Compiler,
elementRef: ElementRef,
loader: DynamicComponentLoader,
injector: Injector
) {
- super(viewCtrl, compiler, elementRef, loader, injector);
- this.item = item;
+ super(parentViewCtrl, compiler, elementRef, loader, injector);
+ this.item = viewItem;
+
+ this.item.navbarView = () => {
+ let activeTab = this.getActive();
+ if (activeTab && activeTab.instance) {
+ return activeTab.instance.navbarView();
+ }
+ return {};
+ };
+
+ this.childNavbar(true);
+
Config(this, {
'tabBarPlacement': {
'default': 'bottom',
@@ -65,12 +76,15 @@ export class Tabs extends ViewController {
});
}
- addTab(tabItem) {
- this.add(tabItem);
+ addTab(tab) {
+ // tab.item refers to the ViewItem of the individual Tab being added to Tabs (ViewController)
+ // this.item refers to the ViewItem instsance on Tabs
+ this.add(tab.item);
if (this.length() === 1) {
- this.item && this.item.waitForResolve();
- tabItem._initial = true;
+ // this was the first tab added, queue this one to be loaded and selected
+ let promise = tab.queueInitial();
+ this.item && this.item.addPromise(promise);
}
}
@@ -83,28 +97,25 @@ export class Tabs extends ViewController {
}
if (!enteringItem || !enteringItem.instance || this.isTransitioning()) {
- return;
+ return Promise.reject();
}
- enteringItem.instance.loadInitial(() => {
- let opts = {
- animate: false
- };
+ return new Promise(resolve => {
+ enteringItem.instance.load(() => {
+ let opts = {
+ animate: false
+ };
- let leavingItem = this.getActive() || new ViewItem();
- leavingItem.shouldDestroy = false;
- leavingItem.shouldCache = true;
- leavingItem.willCache();
+ let leavingItem = this.getActive() || new ViewItem();
+ leavingItem.shouldDestroy = false;
+ leavingItem.shouldCache = true;
+ leavingItem.willCache();
- // set the Tab navbarView from the active view in the tab
- enteringItem.navbarView = (enteringItem.instance.getActive() || {}).navbarView;
- if (leavingItem.instance) {
- leavingItem.navbarView = (leavingItem.instance.getActive() || {}).navbarView;
- }
-
- this.transition(enteringItem, leavingItem, opts, () => {
- this.item && this.item.resolve();
+ this.transition(enteringItem, leavingItem, opts, () => {
+ resolve();
+ });
});
+
});
}
@@ -113,21 +124,3 @@ export class Tabs extends ViewController {
}
}
-// new IonicComponent(Tabs, {
-// properties: {
-// tabBarPlacement: {
-// defaults: {
-// ios: 'bottom',
-// android: 'top',
-// core: 'bottom'
-// }
-// },
-// tabBarIcons: {
-// defaults: {
-// ios: 'top',
-// android: 'top',
-// core: 'top'
-// }
-// }
-// }
-// });
diff --git a/ionic/components/view/view-controller.js b/ionic/components/view/view-controller.js
index 6250e2a653..5e07b9e35b 100644
--- a/ionic/components/view/view-controller.js
+++ b/ionic/components/view/view-controller.js
@@ -60,7 +60,7 @@ export class ViewController {
leavingItem.shouldCache = true;
leavingItem.willCache();
- // create a new NavStackItem
+ // create a new ViewItem
let enteringItem = new ViewItem(this, ComponentClass, params);
// add the item to the stack
@@ -387,11 +387,11 @@ export class ViewController {
}
}
- parentNavbar() {
+ childNavbar() {
if (arguments.length) {
- this._parentNavbar = arguments[0];
+ this._childNavbar = arguments[0];
}
- return this._parentNavbar;
+ return this._childNavbar;
}
add(item) {
diff --git a/ionic/components/view/view-item.js b/ionic/components/view/view-item.js
index ad6e7418aa..42d8c1f3ce 100644
--- a/ionic/components/view/view-item.js
+++ b/ionic/components/view/view-item.js
@@ -22,6 +22,7 @@ export class ViewItem {
this.protos = {};
this._nbItms = [];
+ this._promises = [];
}
addProtoViewRef(name, protoViewRef) {
@@ -44,7 +45,7 @@ export class ViewItem {
// figure out the sturcture of this Component
// does it have a navbar? Is it tabs? Should it not have a navbar or any toolbars?
- let itemStructure = this.sturcture = this.getProtoViewStructure(componentProtoViewRef);
+ let itemStructure = this.sturcture = this.inspectStructure(componentProtoViewRef);
// get the appropriate Pane which this ViewItem will fit into
viewCtrl.panes.get(itemStructure, pane => {
@@ -100,25 +101,25 @@ export class ViewItem {
// this item has finished loading
this.loaded();
- // all done, fire the callback
- if (this._wait) {
- this._waitCallback = callback;
-
- } else {
+ // fire callback when all child promises have been resolved
+ Promise.all(this._promises).then(() => {
callback();
- }
+ this._promises = [];
+ });
});
});
}
+ addPromise(childPromise) {
+ this._promises.push(childPromise);
+ }
- getProtoViewStructure(componentProtoViewRef) {
+ inspectStructure(componentProtoViewRef) {
let navbar = false;
let tabs = false;
- let toolbars = [];
- let key = '';
+ let key = '_';
componentProtoViewRef._protoView.elementBinders.forEach(rootElementBinder => {
if (!rootElementBinder.componentDirective || !rootElementBinder.nestedProtoView) return;
@@ -137,33 +138,20 @@ export class ViewItem {
});
});
- if (this.viewCtrl.parentNavbar()) {
+ if (this.viewCtrl.childNavbar()) {
navbar = false;
}
if (navbar) key += 'n'
if (tabs) key += 't'
- key += 'b' + toolbars.length;
return {
navbar,
tabs,
- toolbars,
key
};
}
- waitForResolve() {
- this._wait = true;
- }
-
- resolve() {
- if (this._wait) {
- this._waitCallback && this._waitCallback();
- this._wait = this._waitCallback = null;
- }
- }
-
setInstance(instance) {
this.instance = instance;
}
@@ -196,81 +184,31 @@ export class ViewItem {
return this.viewEle;
}
- navbarElement() {
+ navbarView() {
if (arguments.length) {
- this._nbEle = arguments[0];
- return;
- }
- if (this._nbEle) {
- // this ViewItem already has an assigned navbarElement
- return this._nbEle;
+ this._nbView = arguments[0];
+
+ } else if (this._nbView) {
+ return this._nbView;
}
- let instance = this.instance;
- if (instance && instance.parentNavbar && instance.parentNavbar()) {
- // this View doesn't actually have it's own navbar
- // for example, Tab does not have a navbar, but Tabs does
- // so if this is true, then get the active ViewItem inside this instance
- let activeChildViewItem = instance.getActive();
- if (activeChildViewItem) {
- return activeChildViewItem.navbarElement();
- }
- }
+ return {};
+ }
+
+ navbarElement() {
+ return this.navbarView().element;
}
titleElement() {
- if (arguments.length) {
- this._ttEle = arguments[0];
- return;
- }
- if (this._ttEle) {
- return this._ttEle;
- }
-
- let instance = this.instance;
- if (instance && instance.parentNavbar && instance.parentNavbar()) {
- let activeChildViewItem = instance.getActive();
- if (activeChildViewItem) {
- return activeChildViewItem.titleElement();
- }
- }
+ return this.navbarView().titleElement;
}
backButtonElement() {
- if (arguments.length) {
- this._bbEle = arguments[0];
- return;
- }
- if (this._bbEle) {
- return this._bbEle;
- }
-
- let instance = this.instance;
- if (instance && instance.parentNavbar && instance.parentNavbar()) {
- let activeChildViewItem = instance.getActive();
- if (activeChildViewItem) {
- return activeChildViewItem.backButtonElement();
- }
- }
+ return this.navbarView().backButtonElement;
}
navbarItemElements() {
- if (arguments.length) {
- this._nbItms.push(arguments[0]);
- return;
- }
- if (this._nbItms) {
- return this._nbItms;
- }
-
-
- let instance = this.instance;
- if (instance && instance.parentNavbar && instance.parentNavbar()) {
- let activeChildViewItem = instance.getActive();
- if (activeChildViewItem) {
- return activeChildViewItem.navbarItemElements();
- }
- }
+ return this.navbarView().itemElements;
}
diff --git a/ionic/transitions/ios-transition.js b/ionic/transitions/ios-transition.js
index 2472d797bd..f3219db822 100644
--- a/ionic/transitions/ios-transition.js
+++ b/ionic/transitions/ios-transition.js
@@ -19,63 +19,61 @@ class IOSTransition extends Transition {
constructor(nav, opts) {
super(nav, opts);
- const self = this;
-
// global duration and easing for all child animations
- self.duration(DURATION);
- self.easing(EASING);
+ this.duration(DURATION);
+ this.easing(EASING);
// entering item moves to center
- self.enteringView
+ this.enteringView
.to(TRANSLATEX, CENTER)
.to(OPACITY, 1);
- self.enteringTitle
+ this.enteringTitle
.fadeIn()
.to(TRANSLATEX, CENTER);
// leaving view moves off screen
- self.leavingView
+ this.leavingView
.from(TRANSLATEX, CENTER)
.from(OPACITY, 1);
- self.leavingTitle
+ this.leavingTitle
.from(TRANSLATEX, CENTER)
.from(OPACITY, 1);
// set properties depending on direction
if (opts.direction === 'back') {
// back direction
- self.enteringView
+ this.enteringView
.from(TRANSLATEX, OFF_LEFT)
.from(OPACITY, OFF_OPACITY)
.to(OPACITY, 1);
- self.enteringTitle
+ this.enteringTitle
.from(TRANSLATEX, OFF_LEFT);
- self.leavingView
+ this.leavingView
.to(TRANSLATEX, OFF_RIGHT)
.to(OPACITY, 1);
- self.leavingTitle
+ this.leavingTitle
.to(TRANSLATEX, OFF_RIGHT)
.to(OPACITY, 0);
} else {
// forward direction
- self.enteringView
+ this.enteringView
.from(TRANSLATEX, '99%')
.from(OPACITY, 1);
- self.enteringTitle
+ this.enteringTitle
.from(TRANSLATEX, '97%');
- self.leavingView
+ this.leavingView
.to(TRANSLATEX, OFF_LEFT)
.to(OPACITY, OFF_OPACITY);
- self.leavingTitle
+ this.leavingTitle
.to(TRANSLATEX, OFF_LEFT)
.to(OPACITY, 0);
}
diff --git a/ionic/transitions/transition.js b/ionic/transitions/transition.js
index e6c98e1e90..1c71c5b15a 100644
--- a/ionic/transitions/transition.js
+++ b/ionic/transitions/transition.js
@@ -12,60 +12,59 @@ export class Transition extends Animation {
constructor(nav, opts) {
super();
- const self = this;
-
// get the entering and leaving items
- let enteringItem = self.entering = nav.getStagedEnteringItem();
- let leavingItem = self.leaving = nav.getStagedLeavingItem();
+ let enteringItem = this.entering = nav.getStagedEnteringItem();
+ let leavingItem = this.leaving = nav.getStagedLeavingItem();
// create animation for the entering item's "ion-view" element
- self.enteringView = new Animation(enteringItem.viewElement());
- self.enteringView.before.addClass(SHOW_VIEW_CSS);
- self.add(self.enteringView);
+ this.enteringView = new Animation(enteringItem.viewElement());
+ this.enteringView.before.addClass(SHOW_VIEW_CSS);
+ this.add(this.enteringView);
if (opts.navbar !== false) {
- let enteringNavbar = self.enteringNavbar = new Animation(enteringItem.navbarElement());
+
+ let enteringNavbar = this.enteringNavbar = new Animation(enteringItem.navbarElement());
enteringNavbar.before.addClass(SHOW_NAVBAR_CSS);
if (enteringItem.enableBack) {
// only animate in the back button if the entering view has it enabled
- let enteringBackButton = self.enteringBackButton = new Animation(enteringItem.backButtonElement());
+ let enteringBackButton = this.enteringBackButton = new Animation(enteringItem.backButtonElement());
enteringBackButton
.before.addClass(SHOW_BACK_BUTTON)
.fromTo('opacity', 0.02, 1)
enteringNavbar.add(enteringBackButton);
}
- self.enteringTitle = new Animation(enteringItem.titleElement());
- enteringNavbar.add(self.enteringTitle);
- self.add(enteringNavbar);
+ this.enteringTitle = new Animation(enteringItem.titleElement());
+ enteringNavbar.add(this.enteringTitle);
+ this.add(enteringNavbar);
- self.enteringNavbarItems = new Animation(enteringItem.navbarItemElements())
- self.enteringNavbarItems.fromTo('opacity', 0.02, 1)
- enteringNavbar.add(self.enteringNavbarItems);
+ this.enteringNavbarItems = new Animation(enteringItem.navbarItemElements())
+ this.enteringNavbarItems.fromTo('opacity', 0.02, 1)
+ enteringNavbar.add(this.enteringNavbarItems);
}
if (leavingItem) {
- self.leavingView = new Animation(leavingItem.viewElement());
- self.leavingView.after.removeClass(SHOW_VIEW_CSS);
+ this.leavingView = new Animation(leavingItem.viewElement());
+ this.leavingView.after.removeClass(SHOW_VIEW_CSS);
- let leavingNavbar = self.leavingNavbar = new Animation(leavingItem.navbarElement());
+ let leavingNavbar = this.leavingNavbar = new Animation(leavingItem.navbarElement());
leavingNavbar.after.removeClass(SHOW_NAVBAR_CSS);
- let leavingBackButton = self.leavingBackButton = new Animation(leavingItem.backButtonElement());
+ let leavingBackButton = this.leavingBackButton = new Animation(leavingItem.backButtonElement());
leavingBackButton
.after.removeClass(SHOW_BACK_BUTTON)
.fadeOut();
leavingNavbar.add(leavingBackButton);
- self.leavingTitle = new Animation(leavingItem.titleElement());
- leavingNavbar.add(self.leavingTitle);
+ this.leavingTitle = new Animation(leavingItem.titleElement());
+ leavingNavbar.add(this.leavingTitle);
- self.leavingNavbarItems = new Animation(leavingItem.navbarItemElements())
- self.leavingNavbarItems.fadeOut();
- leavingNavbar.add(self.leavingNavbarItems);
+ this.leavingNavbarItems = new Animation(leavingItem.navbarItemElements())
+ this.leavingNavbarItems.fadeOut();
+ leavingNavbar.add(this.leavingNavbarItems);
- self.add(self.leavingView, leavingNavbar);
+ this.add(this.leavingView, leavingNavbar);
}
}
diff --git a/scripts/e2e/ionic.template.html b/scripts/e2e/ionic.template.html
index ead7d6449d..7a67ef4554 100644
--- a/scripts/e2e/ionic.template.html
+++ b/scripts/e2e/ionic.template.html
@@ -5,8 +5,7 @@
-
-
+