mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
NavItem renamed to ViewItem
This commit is contained in:
@@ -9,9 +9,10 @@ import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
||||
import {Compiler} from 'angular2/angular2';
|
||||
import {bind} from 'angular2/di';
|
||||
|
||||
import {ViewItem} from './view-item';
|
||||
import {NavController} from '../nav/nav-controller';
|
||||
import {NavItem, NavParams} from '../nav/nav-item';
|
||||
import {Pane, NavBarContainer} from '../nav/pane';
|
||||
import {PaneController} from '../nav/pane';
|
||||
import {NavParams} from '../nav/nav-item';
|
||||
import {Transition} from '../../transitions/transition';
|
||||
import {ClickBlock} from '../../util/click-block';
|
||||
import * as util from 'ionic/util';
|
||||
@@ -30,85 +31,20 @@ export class ViewController {
|
||||
this.parent = parent;
|
||||
this.compiler = compiler;
|
||||
this.elementRef = elementRef;
|
||||
this.domElement = elementRef.domElement;
|
||||
this.loader = loader;
|
||||
this.injector = injector;
|
||||
|
||||
this.items = [];
|
||||
this.navCtrl = new NavController(this);
|
||||
this.panes = new PaneController(this);
|
||||
|
||||
this.sbTransition = null;
|
||||
this.sbActive = false;
|
||||
this.panes = {};
|
||||
|
||||
this.id = ++itemIds;
|
||||
this.childIds = -1;
|
||||
}
|
||||
|
||||
setPaneAnchor(elementRef) {
|
||||
this.anchorElementRef = elementRef;
|
||||
}
|
||||
|
||||
getPane(itemStructure, callback) {
|
||||
// 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
|
||||
callback(this.panes[itemStructure.key]);
|
||||
|
||||
} else {
|
||||
// create a new nav pane
|
||||
this.panes[itemStructure.key] = null;
|
||||
|
||||
let injector = this.injector.resolveAndCreateChild([
|
||||
bind(ViewController).toValue(this)
|
||||
]);
|
||||
|
||||
// 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 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 Pane, ie: nav bars, tab bars, etc.
|
||||
// add only the sections it needs
|
||||
if (itemStructure.navbar) {
|
||||
sectionsToAdd.push(NavBarContainer);
|
||||
}
|
||||
|
||||
// add the sections which this type of Pane requires
|
||||
sectionsToAdd.forEach(SectionClass => {
|
||||
// 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(pane);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
addPane(pane) {
|
||||
for (let np in this.panes) {
|
||||
if (this.panes[np] === null) {
|
||||
this.panes[np] = pane;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
push(ComponentClass, params = {}, opts = {}) {
|
||||
if (!ComponentClass || this.isTransitioning()) {
|
||||
return Promise.reject();
|
||||
@@ -126,13 +62,13 @@ export class ViewController {
|
||||
opts.direction = opts.direction || 'forward';
|
||||
|
||||
// the active item is going to be the leaving one (if one exists)
|
||||
let leavingItem = this.getActive() || new NavItem();
|
||||
let leavingItem = this.getActive() || new ViewItem();
|
||||
leavingItem.shouldDestroy = false;
|
||||
leavingItem.shouldCache = true;
|
||||
leavingItem.willCache();
|
||||
|
||||
// create a new NavStackItem
|
||||
let enteringItem = new NavItem(this, ComponentClass, params);
|
||||
let enteringItem = new ViewItem(this, ComponentClass, params);
|
||||
|
||||
// add the item to the stack
|
||||
this.add(enteringItem);
|
||||
@@ -158,7 +94,7 @@ export class ViewController {
|
||||
|
||||
// get the active item and set that it is staged to be leaving
|
||||
// was probably the one popped from the stack
|
||||
let leavingItem = this.getActive() || new NavItem();
|
||||
let leavingItem = this.getActive() || new ViewItem();
|
||||
leavingItem.shouldDestroy = true;
|
||||
leavingItem.shouldCache = false;
|
||||
leavingItem.willUnload();
|
||||
@@ -259,7 +195,7 @@ export class ViewController {
|
||||
|
||||
// get the active item and set that it is staged to be leaving
|
||||
// was probably the one popped from the stack
|
||||
let leavingItem = this.getActive() || new NavItem();
|
||||
let leavingItem = this.getActive() || new ViewItem();
|
||||
leavingItem.shouldDestroy = true;
|
||||
leavingItem.shouldCache = false;
|
||||
leavingItem.willLeave();
|
||||
@@ -377,7 +313,7 @@ export class ViewController {
|
||||
if (opts.animate) {
|
||||
// block possible clicks during transition
|
||||
ClickBlock(true, 520);
|
||||
this.getNavElement().classList.add('transitioning');
|
||||
this.getContainerElement().classList.add('transitioning');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +332,7 @@ export class ViewController {
|
||||
}
|
||||
});
|
||||
|
||||
this.getNavElement().classList.remove('transitioning');
|
||||
this.getContainerElement().classList.remove('transitioning');
|
||||
|
||||
// allow clicks again
|
||||
ClickBlock(false);
|
||||
@@ -468,8 +404,8 @@ export class ViewController {
|
||||
return null;
|
||||
}
|
||||
|
||||
getNavElement() {
|
||||
return this.domElement;
|
||||
getContainerElement() {
|
||||
return this.elementRef.domElement;
|
||||
}
|
||||
|
||||
navbarViewContainer(nbContainer) {
|
||||
@@ -526,7 +462,7 @@ export class ViewController {
|
||||
}
|
||||
|
||||
width() {
|
||||
return this.domElement.offsetWidth;
|
||||
return this.getContainerElement().offsetWidth;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
304
ionic/components/view/view-item.js
Normal file
304
ionic/components/view/view-item.js
Normal file
@@ -0,0 +1,304 @@
|
||||
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
||||
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||
import {bind} from 'angular2/di';
|
||||
|
||||
import {ViewController} from '../view/view-controller';
|
||||
import {NavController} from '../nav/nav-controller';
|
||||
import {NavParams} from '../nav/nav-params';
|
||||
|
||||
|
||||
export class ViewItem {
|
||||
|
||||
constructor(viewController, ComponentClass, params = {}) {
|
||||
this.viewController = viewController;
|
||||
this.ComponentClass = ComponentClass;
|
||||
this.params = new NavParams(this.params);
|
||||
this.instance = null;
|
||||
this.state = 0;
|
||||
|
||||
this._titleEle = undefined;
|
||||
this._backBtn = undefined;
|
||||
this.disposals = [];
|
||||
|
||||
// if it's possible to go back from this nav item
|
||||
this.enableBack = false;
|
||||
|
||||
this.protos = {};
|
||||
}
|
||||
|
||||
addProtoViewRef(name, protoViewRef) {
|
||||
this.protos[name] = protoViewRef;
|
||||
}
|
||||
|
||||
stage(callback) {
|
||||
let viewController = this.viewController;
|
||||
|
||||
// update if it's possible to go back from this nav item
|
||||
this.enableBack = viewController && !!viewController.getPrevious(this);
|
||||
|
||||
if (this.instance || !viewController) {
|
||||
// already compiled this view
|
||||
return callback();
|
||||
}
|
||||
|
||||
// compile the Component
|
||||
viewController.compiler.compileInHost(this.ComponentClass).then(componentProtoViewRef => {
|
||||
|
||||
// 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 = getProtoViewStructure(componentProtoViewRef);
|
||||
|
||||
// get the appropriate Pane which this ViewItem will fit into
|
||||
viewController.panes.get(itemStructure, pane => {
|
||||
|
||||
// create a new injector just for this ViewItem
|
||||
let injector = viewController.injector.resolveAndCreateChild([
|
||||
bind(ViewController).toValue(viewController),
|
||||
bind(NavController).toValue(viewController.navCtrl),
|
||||
bind(NavParams).toValue(this.params),
|
||||
bind(ViewItem).toValue(this)
|
||||
]);
|
||||
|
||||
// add the content of the view to the content area
|
||||
let viewContainer = pane.contentContainerRef;
|
||||
let hostViewRef = viewContainer.create(componentProtoViewRef, -1, null, injector);
|
||||
|
||||
let newLocation = new ElementRef(hostViewRef, 0);
|
||||
|
||||
this.setInstance( viewController.loader._viewManager.getComponent(newLocation) );
|
||||
this.setViewElement( hostViewRef._view.render._view.rootNodes[0] );
|
||||
|
||||
this.disposals.push(() => {
|
||||
viewContainer.remove( viewContainer.indexOf(hostViewRef) );
|
||||
});
|
||||
|
||||
// get the view's context so when creating the navbar
|
||||
// it uses the same context as the content
|
||||
let context = {
|
||||
boundElementIndex: 0,
|
||||
parentView: {
|
||||
_view: hostViewRef._view.componentChildViews[0]
|
||||
}
|
||||
};
|
||||
|
||||
// get the item container's nav bar
|
||||
let navbarViewContainer = viewController.navbarViewContainer();
|
||||
|
||||
// get the item's navbar protoview
|
||||
let navbarProtoView = this.protos.navbar;
|
||||
|
||||
// add a navbar view if the pane has a navbar container, and the
|
||||
// item's instance has a navbar protoview to go to inside of it
|
||||
if (navbarViewContainer && navbarProtoView) {
|
||||
this.navbarView = navbarViewContainer.create(navbarProtoView, -1, context, injector);
|
||||
|
||||
this.disposals.push(() => {
|
||||
navbarViewContainer.remove( navbarViewContainer.indexOf(this.navbarView) );
|
||||
});
|
||||
}
|
||||
|
||||
// this item has finished loading
|
||||
this.loaded();
|
||||
|
||||
// all done, fire the callback
|
||||
if (this._wait) {
|
||||
this._waitCallback = callback;
|
||||
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
waitForResolve() {
|
||||
this._wait = true;
|
||||
}
|
||||
|
||||
resolve() {
|
||||
if (this._wait) {
|
||||
this._waitCallback && this._waitCallback();
|
||||
this._wait = this._waitCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
setInstance(instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
setViewElement(viewEle) {
|
||||
this.viewEle = viewEle;
|
||||
viewEle && viewEle.classList.add('nav-item');
|
||||
}
|
||||
|
||||
cache() {
|
||||
this.didCache();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
for (let i = 0; i < this.disposals.length; i++) {
|
||||
this.disposals[i]();
|
||||
}
|
||||
|
||||
this.didUnload();
|
||||
|
||||
// just to help prevent any possible memory leaks
|
||||
for (let name in this) {
|
||||
if (this.hasOwnProperty(name)) {
|
||||
this[name] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewElement() {
|
||||
return this.viewEle;
|
||||
}
|
||||
|
||||
navbarElement() {
|
||||
let navbarView = this.navbarView;
|
||||
if (navbarView && navbarView._view) {
|
||||
return navbarView._view.render._view.rootNodes[0];
|
||||
}
|
||||
}
|
||||
|
||||
contentElement() {
|
||||
return this.viewEle.querySelector('ion-content');
|
||||
}
|
||||
|
||||
titleElement() {
|
||||
if (this._titleEle === undefined) {
|
||||
let navbarElement = this.navbarElement();
|
||||
if (navbarElement) {
|
||||
let titleEle = navbarElement.querySelector('ion-title');
|
||||
if (titleEle) {
|
||||
this._titleEle = titleEle;
|
||||
return this._titleEle;
|
||||
}
|
||||
}
|
||||
this._titleEle = null;
|
||||
}
|
||||
return this._titleEle;
|
||||
}
|
||||
|
||||
backButtonElement() {
|
||||
if (this._backBtn === undefined) {
|
||||
let navbarElement = this.navbarElement();
|
||||
if (navbarElement) {
|
||||
let backBtn = navbarElement.querySelector('back-button');
|
||||
if (backBtn) {
|
||||
this._backBtn = backBtn;
|
||||
return this._backBtn;
|
||||
}
|
||||
}
|
||||
this._backBtn = null;
|
||||
}
|
||||
return this._backBtn;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The view has loaded. This event only happens once per view being
|
||||
created. If a view leaves but is cached, then this will not
|
||||
fire again on a subsequent viewing. This method is a good place
|
||||
to put your setup code for the view; however, it is not the
|
||||
recommended method to use when a view becomes active.
|
||||
*/
|
||||
loaded() {
|
||||
this.instance && this.instance.viewLoaded && this.instance.viewLoaded();
|
||||
}
|
||||
|
||||
/*
|
||||
The view is about to enter and become the active view.
|
||||
*/
|
||||
willEnter() {
|
||||
this.instance && this.instance.viewWillEnter && this.instance.viewWillEnter();
|
||||
}
|
||||
|
||||
/*
|
||||
The view has fully entered and is now the active view. This
|
||||
will fire, whether it was the first load or loaded from the cache.
|
||||
*/
|
||||
didEnter() {
|
||||
this.instance && this.instance.viewDidEnter && this.instance.viewDidEnter();
|
||||
}
|
||||
|
||||
/*
|
||||
The view has is about to leave and no longer be the active view.
|
||||
*/
|
||||
willLeave() {
|
||||
this.instance && this.instance.viewWillLeave && this.instance.viewWillLeave();
|
||||
}
|
||||
|
||||
/*
|
||||
The view has finished leaving and is no longer the active view. This
|
||||
will fire, whether it is cached or unloaded.
|
||||
*/
|
||||
didLeave() {
|
||||
this.instance && this.instance.viewDidLeave && this.instance.viewDidLeave();
|
||||
}
|
||||
|
||||
/*
|
||||
The view is about to become cached.
|
||||
*/
|
||||
willCache() {
|
||||
this.instance && this.instance.viewWillCache && this.instance.viewWillCache();
|
||||
}
|
||||
|
||||
/*
|
||||
The view is now cached.
|
||||
*/
|
||||
didCache() {
|
||||
this.instance && this.instance.viewDidCache && this.instance.viewDidCache();
|
||||
}
|
||||
|
||||
/*
|
||||
The view is about to be destroyed and have its elements removed.
|
||||
*/
|
||||
willUnload() {
|
||||
this.instance && this.instance.viewWillUnload && this.instance.viewWillUnload();
|
||||
}
|
||||
|
||||
/*
|
||||
The view has been destroyed and its elements have been removed.
|
||||
*/
|
||||
didUnload() {
|
||||
this.instance && this.instance.viewDidUnload && this.instance.viewDidUnload();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getProtoViewStructure(componentProtoViewRef) {
|
||||
let navbar = true;
|
||||
let tabs = false;
|
||||
let toolbars = [];
|
||||
let key = '_';
|
||||
|
||||
// componentProtoViewRef._protoView.elementBinders.forEach(rootElementBinder => {
|
||||
// if (!rootElementBinder.componentDirective || !rootElementBinder.nestedProtoView) return;
|
||||
|
||||
// rootElementBinder.nestedProtoView.elementBinders.forEach(nestedElementBinder => {
|
||||
// let componentDirective = nestedElementBinder.componentDirective;
|
||||
// if (componentDirective && componentDirective.metadata.id == 'Tab') {
|
||||
// navbar = tabs = true;
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
if (navbar) {
|
||||
key += 'n'
|
||||
}
|
||||
|
||||
if (toolbars.length) {
|
||||
key += 'b' + toolbars.length;
|
||||
}
|
||||
|
||||
return {
|
||||
navbar: navbar,
|
||||
tabs: tabs,
|
||||
toolbars: toolbars,
|
||||
key: key
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user