mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 04:14:21 +08:00
update to angular 2.0.0-alpha.21, update toolbar system
This commit is contained in:
@ -36,9 +36,13 @@ gulp.task('lib', ['fonts', 'dependencies'])
|
||||
gulp.task('watch', ['default'], function() {
|
||||
gulp.watch(buildConfig.src.scss, ['sass'])
|
||||
gulp.watch([].concat(
|
||||
buildConfig.src.js, buildConfig.src.e2e, buildConfig.src.html,
|
||||
buildConfig.src.js, buildConfig.src.html,
|
||||
'scripts/e2e/index.template.html'
|
||||
), ['e2e'])
|
||||
gulp.watch([].concat(
|
||||
buildConfig.src.e2e, buildConfig.src.html,
|
||||
'scripts/e2e/index.template.html'
|
||||
), ['ionic-js'])
|
||||
})
|
||||
|
||||
gulp.task('karma', function() {
|
||||
@ -75,7 +79,7 @@ gulp.task('clean', function(done) {
|
||||
del([buildConfig.dist], done)
|
||||
})
|
||||
|
||||
gulp.task('e2e', ['ionic-js', 'sass', 'ng2-copy'], function() {
|
||||
gulp.task('e2e', ['ionic-js', 'sass'], function() {
|
||||
var indexContents = _.template( fs.readFileSync('scripts/e2e/index.template.html') )({
|
||||
buildConfig: buildConfig
|
||||
});
|
||||
|
@ -11,14 +11,12 @@ export * from 'ionic/components/form/form'
|
||||
export * from 'ionic/components/input/input'
|
||||
export * from 'ionic/components/layout/layout'
|
||||
export * from 'ionic/components/list/list'
|
||||
export * from 'ionic/components/nav-pane/nav-pane' //TODO remove
|
||||
export * from 'ionic/components/nav/nav'
|
||||
export * from 'ionic/components/nav/nav-item'
|
||||
export * from 'ionic/components/nav/decorators'
|
||||
export * from 'ionic/components/radio/radio-button'
|
||||
export * from 'ionic/components/radio/radio-group'
|
||||
export * from 'ionic/components/search-bar/search-bar'
|
||||
export * from 'ionic/components/scroll/pull-to-refresh'
|
||||
export * from 'ionic/components/split-view/split-view'
|
||||
export * from 'ionic/components/switch/switch'
|
||||
export * from 'ionic/components/tabs/tabs'
|
||||
|
@ -32,6 +32,10 @@ html {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 50px;
|
||||
@include flex-order($flex-order-toolbar-top);
|
||||
}
|
||||
footer.toolbar-container {
|
||||
@include flex-order($flex-order-toolbar-bottom);
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
@ -44,7 +48,7 @@ html {
|
||||
}
|
||||
|
||||
.nav-item-container {
|
||||
// container of many .nav-pane's, each one containing one view
|
||||
// container of many .nav-item's, each one containing one view
|
||||
position: relative;
|
||||
@include flex(1);
|
||||
@include flex-order($flex-order-view-content);
|
||||
@ -58,28 +62,20 @@ html {
|
||||
@include flex-order($flex-order-view-content);
|
||||
}
|
||||
|
||||
.nav-pane {
|
||||
// container of one ion-view
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.nav-pane-cover-parent {
|
||||
// .nav-pane that should completely cover siblings and parent
|
||||
.nav-item-cover-parent {
|
||||
// .nav-item that should completely cover siblings and parent
|
||||
top: -50px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
ion-view {
|
||||
// user created view, contained by .nav-pane
|
||||
.nav-item,
|
||||
.nav-item-child {
|
||||
// user created view, contained by .nav-item
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
ion-content {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Component, View as NgView, NgElement, PropertySetter} from 'angular2/angular2'
|
||||
import {Component, View as NgView, NgElement} from 'angular2/angular2'
|
||||
import {IonicComponent} from 'ionic/config/component'
|
||||
|
||||
|
||||
@ -28,15 +28,20 @@ import {IonicComponent} from 'ionic/config/component'
|
||||
})
|
||||
export class Checkbox {
|
||||
constructor(
|
||||
@NgElement() ngElement: NgElement,
|
||||
@PropertySetter('attr.role') setAriaRole: Function,
|
||||
@PropertySetter('attr.aria-checked') setAriaChecked: Function,
|
||||
@PropertySetter('attr.aria-invalid') setAriaInvalid: Function,
|
||||
@PropertySetter('attr.aria-disabled') setAriaDisabled: Function
|
||||
@NgElement() ngElement: NgElement
|
||||
// @PropertySetter('attr.role') setAriaRole: Function,
|
||||
// @PropertySetter('attr.aria-checked') setAriaChecked: Function,
|
||||
// @PropertySetter('attr.aria-invalid') setAriaInvalid: Function,
|
||||
// @PropertySetter('attr.aria-disabled') setAriaDisabled: Function
|
||||
) {
|
||||
this.domElement = ngElement.domElement
|
||||
this.domElement.classList.add('item')
|
||||
|
||||
let setAriaRole = (v) => this.domElement.setAttribute('aria-role', v)
|
||||
let setAriaChecked = (v) => this.domElement.setAttribute('aria-checked', v)
|
||||
let setAriaInvalid = (v) => this.domElement.setAttribute('aria-invalid', v)
|
||||
let setAriaDisabled = (v) => this.domElement.setAttribute('aria-disabled', v)
|
||||
|
||||
this.config = Checkbox.config.invoke(this)
|
||||
|
||||
setAriaRole('checkbox')
|
||||
|
@ -1,4 +1,8 @@
|
||||
import {NgElement, Component, View as NgView, PropertySetter} from 'angular2/angular2';
|
||||
import {
|
||||
NgElement,
|
||||
Component,
|
||||
View as NgView,
|
||||
} from 'angular2/angular2';
|
||||
|
||||
@Component({
|
||||
selector: 'ion-content'
|
||||
@ -13,6 +17,7 @@ export class Content {
|
||||
constructor(
|
||||
@NgElement() element:NgElement
|
||||
) {
|
||||
console.log('constructing content', element.domElement);
|
||||
this.domElement = element.domElement;
|
||||
this.domElement.classList.add('content');
|
||||
}
|
||||
|
6
ionic/components/nav/nav-bar.js
Normal file
6
ionic/components/nav/nav-bar.js
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
export class NavBarContainer {
|
||||
}
|
||||
|
||||
export class NavBar extends Toolbar {
|
||||
}
|
@ -1,20 +1,24 @@
|
||||
import {NgElement} from 'angular2/angular2';
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
export class NavControllerBase {
|
||||
/*
|
||||
* Used be tabs and nav
|
||||
*/
|
||||
export class NavBase {
|
||||
constructor(
|
||||
element: NgElement
|
||||
) {
|
||||
this.domElement = element.domElement
|
||||
this.domElement.classList.add('nav')
|
||||
this.domElement = element.domElement;
|
||||
this.domElement.classList.add('nav');
|
||||
|
||||
// this is our sane stack of items. This is synchronous and says an item
|
||||
// is removed even if it's still animating out.
|
||||
this._stack = []
|
||||
this._stack = [];
|
||||
|
||||
// _ngForLoopArray is what adds/removes components from the dom. It won't
|
||||
// remove a component until it's done animating out.
|
||||
this._ngForLoopArray = []
|
||||
// The _ng* arrays are what add/remove components from the dom.
|
||||
// These arrays won't remove a component until they're
|
||||
// done animating out.
|
||||
this._ngNavItems = [];
|
||||
}
|
||||
|
||||
containsClass(Class) {
|
||||
@ -52,7 +56,7 @@ export class NavControllerBase {
|
||||
|
||||
let pushedItem = new NavStackData(Class, params)
|
||||
this._stack.push(pushedItem)
|
||||
this._ngForLoopArray.push(pushedItem)
|
||||
this._ngNavItems.push(pushedItem)
|
||||
|
||||
return pushedItem.waitForSetup().then(() => {
|
||||
let current = this._getPrevious(pushedItem)
|
||||
@ -71,15 +75,19 @@ export class NavControllerBase {
|
||||
sync: false
|
||||
})
|
||||
let current = this._stack.pop()
|
||||
let dest = this.peek()
|
||||
let dest = this.last()
|
||||
|
||||
dest && dest.enterReverse(opts)
|
||||
return current && current.leave(opts).then(() => this._destroy(current))
|
||||
return current && current.leave(opts)
|
||||
.then(() => this._destroy(current))
|
||||
}
|
||||
|
||||
peek() {
|
||||
last() {
|
||||
return this._stack[this._stack.length - 1]
|
||||
}
|
||||
length() {
|
||||
return this._stack.length;
|
||||
}
|
||||
|
||||
popAll() {
|
||||
while (this._stack.length) {
|
||||
@ -112,7 +120,7 @@ export class NavControllerBase {
|
||||
|
||||
setStack(stack) {
|
||||
this._stack = stack.slice()
|
||||
this._ngForLoopArray = stack.slice()
|
||||
this._ngNavItems = stack.slice()
|
||||
}
|
||||
|
||||
remove(index) {
|
||||
@ -123,14 +131,19 @@ export class NavControllerBase {
|
||||
|
||||
_destroy(navItem) {
|
||||
console.warn(
|
||||
`Component "${navItem.Class.name}" was popped from the nav stack, But were keeping its element in the DOM for now because of an ng2 bug.`
|
||||
`Component "${navItem.Class.name}" was popped from the nav stack, but wer'e keeping its element in the DOM for now because of an ng2 bug.`
|
||||
);
|
||||
//util.array.remove(this._ngForLoopArray, navItem)
|
||||
// util.array.remove(this._ngNavItems, navItem)
|
||||
}
|
||||
|
||||
_getPrevious(item) {
|
||||
return this._stack[ this._stack.indexOf(item) - 1 ]
|
||||
}
|
||||
|
||||
getToolbars(pos: String) {
|
||||
let last = this.last();
|
||||
return last && last.navItem && last.navItem._toolbars[pos] || [];
|
||||
}
|
||||
}
|
||||
|
||||
class NavStackData {
|
@ -1,73 +1,132 @@
|
||||
import {
|
||||
Component,
|
||||
DynamicComponent,
|
||||
Parent,
|
||||
Decorator,
|
||||
Ancestor,
|
||||
NgElement,
|
||||
DynamicComponentLoader,
|
||||
ElementRef,
|
||||
Query,
|
||||
View as NgView,
|
||||
} from 'angular2/angular2';
|
||||
|
||||
import {
|
||||
Injectable,
|
||||
bind,
|
||||
Optional,
|
||||
} from 'angular2/di';
|
||||
import {Nav} from 'ionic/components/nav/nav'
|
||||
import {Tab} from 'ionic/components/tabs/tab'
|
||||
|
||||
import {Toolbar} from 'ionic/components/toolbar/toolbar';
|
||||
import {NavInjectable} from 'ionic/components/nav/nav';
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
/*
|
||||
* NavController is the public interface for pushing, popping, etc that is injected
|
||||
* by users.
|
||||
* Each nav item exposes a new NavController.
|
||||
*/
|
||||
export class NavController {
|
||||
constructor() {
|
||||
// Contains data passed to this NavController's NavItem
|
||||
this.params = {};
|
||||
// this.navItem and this.nav are set by NavItem below.
|
||||
}
|
||||
|
||||
addToolbar(placement: String, toolbar: Toolbar) {
|
||||
if (!this.navItem._toolbars[placement]) {
|
||||
return console.error(
|
||||
`Toolbar must have a placement of top or bottom, found toolbar ${toolbar} with placement ${placement}!`
|
||||
);
|
||||
}
|
||||
this.navItem._toolbars[placement].push(toolbar);
|
||||
}
|
||||
|
||||
removeToolbar(placement: String, toolbar: Toolbar) {
|
||||
let bars = this.navItem._toolbars[placement];
|
||||
bars && util.array.remove(bars, toolbar);
|
||||
}
|
||||
|
||||
push() {
|
||||
return this.nav.push.apply(this.nav, arguments);
|
||||
}
|
||||
pop() {
|
||||
return this.nav.pop.apply(this.nav, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: '.nav-item',
|
||||
properties: {
|
||||
_item: 'item'
|
||||
},
|
||||
injectables: [
|
||||
// Allow all descendants to inject NavController and do nav operations.
|
||||
NavController
|
||||
]
|
||||
})
|
||||
@NgView({
|
||||
// See below for this.
|
||||
template: '<div class="nav-item-child"></div>',
|
||||
directives: [NavItemDynamicComponent]
|
||||
})
|
||||
export class NavItem {
|
||||
constructor(
|
||||
// TODO for now, we can't inject tab as if it's a Nav
|
||||
navInjectable: NavInjectable,
|
||||
navCtrl: NavController,
|
||||
element: NgElement
|
||||
) {
|
||||
this.domElement = element.domElement;
|
||||
this._toolbars = {
|
||||
top: [],
|
||||
bottom: []
|
||||
};
|
||||
this.navCtrl = navCtrl;
|
||||
navCtrl.nav = navInjectable.nav;
|
||||
navCtrl.navItem = this;
|
||||
}
|
||||
|
||||
set _item(data) {
|
||||
var navChild = this.dynamicComponentChild;
|
||||
|
||||
if (this.initialized) return;
|
||||
this.initialized = true;
|
||||
|
||||
this.Class = data.Class;
|
||||
|
||||
util.extend(this.navCtrl.params, data.params || {});
|
||||
|
||||
navChild._loader.loadIntoExistingLocation(this.Class, navChild._elementRef).then((instance) => {
|
||||
this.instance = instance;
|
||||
data.finishSetup(this, instance);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In angular 2.0.0-alpha.21, DynamicComponents are not allowed to publish injectables
|
||||
* (bug, see https://github.com/angular/angular/issues/1596).
|
||||
* To fix this problem, we have the `NavItem` above publish a `NavController ` injectable
|
||||
* so the rest of the app has access to nav operations. Then we have a DynamicComponent
|
||||
* instantiate the user's page.
|
||||
* The `NavItem` class above can be turned into a DynamicComponent and this class can be removed
|
||||
* once injectables are allowed on regular Components.
|
||||
*/
|
||||
@DynamicComponent({
|
||||
selector: 'ion-nav-item',
|
||||
selector: '.nav-item-child',
|
||||
properties: {
|
||||
_item: 'item'
|
||||
}
|
||||
})
|
||||
export class NavItem {
|
||||
export class NavItemDynamicComponent {
|
||||
constructor(
|
||||
@NgElement() element: NgElement,
|
||||
loader: DynamicComponentLoader,
|
||||
elementRef: ElementRef
|
||||
elementRef: ElementRef,
|
||||
@Ancestor() navItem: NavItem
|
||||
|
||||
// FIXME: this is temporary until ng2 lets us inject tabs as a Nav
|
||||
// @Optional() @Parent() viewportNav: Nav,
|
||||
// @Optional() @Parent() viewportTab: Tab
|
||||
) {
|
||||
this._loader = loader;
|
||||
this._elementRef = elementRef;
|
||||
// this.viewport = viewportTab || viewportNav;
|
||||
this.domElement = element.domElement;
|
||||
this.params = {};
|
||||
navItem.dynamicComponentChild = this;
|
||||
}
|
||||
|
||||
set _item(data) {
|
||||
if (this.initialized) return;
|
||||
this.initialized = true;
|
||||
this.Class = data.Class;
|
||||
this._item = data;
|
||||
|
||||
if(data.parms) {
|
||||
util.extend(this.params, data.params);
|
||||
}
|
||||
|
||||
this._loader.loadIntoExistingLocation(data.Class, this._elementRef).then(instance => {
|
||||
this.instance = instance
|
||||
data.finishSetup(this, instance)
|
||||
})
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Push out of this view into another view
|
||||
// */
|
||||
// push(Class: Function, opts = {}) {
|
||||
// return this.viewport.push(Class, opts)
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Go back
|
||||
// */
|
||||
// pop(opts) {
|
||||
// return this.viewport.pop(opts)
|
||||
// }
|
||||
|
||||
// popTo(index, opts) {
|
||||
// return this.viewport.popTo(index, opts)
|
||||
// }
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
$transition-duration: 500ms;
|
||||
|
||||
|
||||
.nav-pane {
|
||||
.nav-item {
|
||||
display: none;
|
||||
|
||||
&.shown {
|
@ -1,43 +1,62 @@
|
||||
import {
|
||||
Component,
|
||||
View as NgView,
|
||||
If,
|
||||
For,
|
||||
NgElement,
|
||||
Query,
|
||||
QueryList,
|
||||
Descendants
|
||||
} from 'angular2/angular2';
|
||||
import {NavControllerBase} from 'ionic/components/nav/nav-controller';
|
||||
import {NavItem} from 'ionic/components/nav/nav-item';
|
||||
import {Toolbar} from 'ionic/components/toolbar/toolbar';
|
||||
import {NavBase} from 'ionic/components/nav/nav-base';
|
||||
import {NavItem, NavItemDynamicComponent} from 'ionic/components/nav/nav-item';
|
||||
import {ToolbarContainer} from 'ionic/components/toolbar/toolbar';
|
||||
|
||||
/**
|
||||
* We need a way for children to get ahold of the instantiated `Nav`.
|
||||
* Until angular supports components adding themselves to the Injector,
|
||||
* Nav is going to add an instance of a "NavInjectable" class to the injector.
|
||||
* This NavInjectable will have a pointer to the Nav class on `this.nav`.
|
||||
* Now descendant components (only our private ones) will have access to NavInjectable,
|
||||
* and be able to get access to the Nav through `navInjectable.nav` (@see navItem)
|
||||
*/
|
||||
export class NavInjectable {}
|
||||
|
||||
@Component({
|
||||
selector: 'ion-nav',
|
||||
properties: {
|
||||
initial: 'initial'
|
||||
}
|
||||
},
|
||||
injectables: [
|
||||
// Add NavInjectable to the injector for this and all descendants
|
||||
NavInjectable
|
||||
]
|
||||
})
|
||||
@NgView({
|
||||
template: `
|
||||
<header class="toolbar-container">
|
||||
<ion-toolbar class="view-toolbar">
|
||||
<ion-nav-title>
|
||||
Test Nonfunctional Toolbar
|
||||
</ion-nav-title>
|
||||
</ion-toolbar>
|
||||
<!-- COLLECTION OF TOOLBARS FOR EACH OF ITS VIEWS WITHIN THIS NAV-VIEWPORT -->
|
||||
<!-- TOOLBARS FOR EACH VIEW SHOULD HAVE THE SAME CONTEXT AS ITS VIEW -->
|
||||
</header>
|
||||
|
||||
<div class="nav-item-container">
|
||||
<!-- COLLECTION OF PANES WITHIN THIS NAV-VIEWPORT, EACH PANE AS ONE VIEW -->
|
||||
<!-- EACH VIEW HAS A TOOLBAR WHICH NEEDS TO HAVE THE SAME CONTEXT -->
|
||||
<ion-nav-item class="nav-pane" *for="#item of _ngForLoopArray" [item]="item"></section>
|
||||
<header class="toolbar-container" [class.hide]="getToolbars('top').length == 0">
|
||||
<div *for="#toolbar of getToolbars('top')" [toolbar-create]="toolbar">
|
||||
</div>
|
||||
</header>
|
||||
<section class="nav-item-container">
|
||||
<div class="nav-item"
|
||||
*for="#item of _ngNavItems"
|
||||
[item]="item"></div>
|
||||
</section>
|
||||
<footer class="toolbar-container" [class.hide]="getToolbars('bottom').length == 0">
|
||||
<div *for="#toolbar of getToolbars('bottom')" [toolbar-create]="toolbar">
|
||||
</div>
|
||||
</footer>
|
||||
`,
|
||||
directives: [NavItem, For, Toolbar]
|
||||
directives: [NavItem, For, If, ToolbarContainer]
|
||||
})
|
||||
export class Nav extends NavControllerBase {
|
||||
export class Nav extends NavBase {
|
||||
constructor(
|
||||
element: NgElement
|
||||
element: NgElement,
|
||||
navInjectable: NavInjectable
|
||||
) {
|
||||
super(element);
|
||||
// Add the nav to navInjectable.
|
||||
navInjectable.nav = this;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Component, View as NgView, NgElement, PropertySetter} from 'angular2/angular2'
|
||||
import {Component, View as NgView, NgElement} from 'angular2/angular2'
|
||||
import {IonicComponent} from 'ionic/config/component'
|
||||
|
||||
|
||||
@ -27,15 +27,20 @@ import {IonicComponent} from 'ionic/config/component'
|
||||
})
|
||||
export class Switch {
|
||||
constructor(
|
||||
element: NgElement,
|
||||
@PropertySetter('attr.role') setAriaRole: Function,
|
||||
@PropertySetter('attr.aria-checked') setChecked: Function,
|
||||
@PropertySetter('attr.aria-invalid') setInvalid: Function,
|
||||
@PropertySetter('attr.aria-disabled') setDisabled: Function
|
||||
element: NgElement
|
||||
// @PropertySetter('attr.role') setAriaRole: Function,
|
||||
// @PropertySetter('attr.aria-checked') setChecked: Function,
|
||||
// @PropertySetter('attr.aria-invalid') setInvalid: Function,
|
||||
// @PropertySetter('attr.aria-disabled') setDisabled: Function
|
||||
) {
|
||||
this.domElement = element.domElement
|
||||
this.config = Switch.config.invoke(this)
|
||||
|
||||
let setAriaRole = (v) => this.domElement.setAttribute('aria-role', v)
|
||||
let setAriaChecked = (v) => this.domElement.setAttribute('aria-checked', v)
|
||||
let setAriaInvalid = (v) => this.domElement.setAttribute('aria-invalid', v)
|
||||
let setAriaDisabled = (v) => this.domElement.setAttribute('aria-disabled', v)
|
||||
|
||||
this.domElement.classList.add('item')
|
||||
|
||||
setAriaRole('checkbox')
|
||||
|
@ -3,14 +3,24 @@ import {
|
||||
NgElement,
|
||||
View as NgView,
|
||||
Ancestor,
|
||||
PropertySetter,
|
||||
For
|
||||
For,
|
||||
If,
|
||||
} from 'angular2/angular2';
|
||||
import {NavControllerBase} from 'ionic/components/nav/nav-controller';
|
||||
import {bind} from 'angular2/di';
|
||||
|
||||
import {NavInjectable} from 'ionic/components/nav/nav';
|
||||
import {NavBase} from 'ionic/components/nav/nav-base';
|
||||
import {NavItem} from 'ionic/components/nav/nav-item';
|
||||
import {Tabs} from 'ionic/components/tabs/tabs';
|
||||
import * as util from 'ionic/util';
|
||||
import {IonicComponent} from 'ionic/config/component';
|
||||
import {ToolbarContainer} from 'ionic/components/toolbar/toolbar';
|
||||
|
||||
/*
|
||||
* See components/nav/nav for an explanation of NavInjectable.
|
||||
* Allow a tab to publish itself on the injector in a similar manner.
|
||||
*/
|
||||
class TabNavInjectable {}
|
||||
|
||||
@Component({
|
||||
selector: 'ion-tab',
|
||||
@ -19,34 +29,50 @@ import {IonicComponent} from 'ionic/config/component';
|
||||
icon: 'tab-icon',
|
||||
initial: 'initial'
|
||||
},
|
||||
injectables: [
|
||||
// Child components will inject `NavInjectable` but it will get the tabs one.
|
||||
bind(NavInjectable).toClass(TabNavInjectable)
|
||||
]
|
||||
})
|
||||
@NgView({
|
||||
template: `
|
||||
<header class="toolbar-container">
|
||||
<ion-toolbar class="view-toolbar">
|
||||
<ion-nav-title>
|
||||
Test Nonfunctional Toolbar
|
||||
</ion-nav-title>
|
||||
</ion-toolbar>
|
||||
</header>
|
||||
<div class="nav-item-container">
|
||||
<!-- COLLECTION OF PANES WITHIN THIS NAV-VIEWPORT, EACH PANE AS ONE VIEW -->
|
||||
<!-- EACH VIEW HAS A TOOLBAR WHICH NEEDS TO HAVE THE SAME CONTEXT -->
|
||||
<ion-nav-item class="nav-pane" *for="#item of _ngForLoopArray" [item]="item"></section>
|
||||
<header class="toolbar-container" [class.hide]="nav.getToolbars('top').length == 0">
|
||||
<div *for="#toolbar of nav.getToolbars('top')" [toolbar-create]="toolbar">
|
||||
</div>
|
||||
</header>
|
||||
<section class="nav-item-container">
|
||||
<div class="nav-item"
|
||||
*for="#item of nav._ngNavItems"
|
||||
[item]="item"></div>
|
||||
</section>
|
||||
<footer class="toolbar-container" [class.hide]="nav.getToolbars('bottom').length == 0">
|
||||
<div *for="#toolbar of nav.getToolbars('bottom')" [toolbar-create]="toolbar">
|
||||
</div>
|
||||
</footer>
|
||||
`,
|
||||
directives: [For, NavItem]
|
||||
directives: [NavItem, For, If, ToolbarContainer]
|
||||
})
|
||||
export class Tab extends NavControllerBase {
|
||||
export class Tab {
|
||||
constructor(
|
||||
element: NgElement,
|
||||
@Ancestor() tabs: Tabs,
|
||||
@PropertySetter('class.hide') setHidden: Function,
|
||||
@PropertySetter('attr.role') setRole: Function,
|
||||
@PropertySetter('attr.id') setId: Function,
|
||||
@PropertySetter('attr.aria-labelledby') setLabelby: Function
|
||||
navInjectable: NavInjectable,
|
||||
@Ancestor() tabs: Tabs
|
||||
// @PropertySetter('class.hide') setHidden: Function,
|
||||
// @PropertySetter('attr.role') setRole: Function,
|
||||
// @PropertySetter('attr.id') setId: Function,
|
||||
// @PropertySetter('attr.aria-labelledby') setLabelby: Function
|
||||
) {
|
||||
super(element);
|
||||
this.nav = new NavBase(element);
|
||||
this.domElement = element.domElement;
|
||||
|
||||
// Allow children to get this nav instance from injecting the NavInjectable
|
||||
navInjectable.nav = this.nav;
|
||||
|
||||
let setHidden = (v) => this.domElement.classList[v?'add':'remove']('hide');
|
||||
let setRole = (v) => this.domElement.setAttribute('role', v);
|
||||
let setId = (v) => this.domElement.setAttribute('id', v);
|
||||
let setLabelby = (v) => this.domElement.setAttribute('aria-labelledby', v);
|
||||
|
||||
this.config = Tab.config.invoke(this);
|
||||
this.setHidden = setHidden
|
||||
|
||||
@ -59,6 +85,10 @@ export class Tab extends NavControllerBase {
|
||||
tabs.addTab(this)
|
||||
}
|
||||
|
||||
set initial(value) {
|
||||
this.nav.initial = value;
|
||||
}
|
||||
|
||||
setSelected(isSelected) {
|
||||
this.isSelected = !!isSelected
|
||||
this.setHidden(!this.isSelected)
|
||||
|
@ -1,5 +1,8 @@
|
||||
import {NgElement, Component, View as NgView, For, PropertySetter} from 'angular2/angular2'
|
||||
import {IonicComponent} from 'ionic/config/component'
|
||||
import {NgElement, Component, View as NgView, For, PropertySetter, Query} from 'angular2/angular2';
|
||||
import {QueryList} from 'angular2/src/core/compiler/query_list';
|
||||
import {IonicComponent} from 'ionic/config/component';
|
||||
import {Toolbar} from 'ionic/components/toolbar/toolbar';
|
||||
import {Tab} from 'ionic/components/tabs/tab';
|
||||
|
||||
@Component({
|
||||
selector: 'ion-tabs',
|
||||
@ -9,15 +12,25 @@ import {IonicComponent} from 'ionic/config/component'
|
||||
}
|
||||
})
|
||||
@NgView({
|
||||
//[attr.aria-activedescendant]="'tab-item-' + selectedTab.tabId"
|
||||
template: `
|
||||
<header class="toolbar-container">
|
||||
<!-- COLLECTION OF TOOLBARS FOR EACH VIEW WITHIN EACH TAB-VIEWPORT -->
|
||||
<!-- TOOLBARS FOR EACH VIEW SHOULD HAVE THE SAME CONTEXT AS ITS VIEW -->
|
||||
</header>
|
||||
<!-- TODO: Once the reprojected toolbar preserves the context of the Tabs, then
|
||||
remove this for loop and use the one in the ion-toolbar below. -->
|
||||
<button *for="#t of tabs"
|
||||
role="tab"
|
||||
class="button button-primary"
|
||||
[attr.id]="'tab-item-' + t.tabId"
|
||||
[attr.aria-controls]="'tab-content-' + t.tabId"
|
||||
[attr.aria-selected]="t.isSelected"
|
||||
[style.color]="t.isSelected ? 'red' : ''"
|
||||
(^click)="onClickTabItem($event, t)">
|
||||
<icon [class-name]="'tab-bar-item-icon ' + t.icon" [hidden]="!t.icon"></icon>
|
||||
<span class="tab-bar-item-text" [hidden]="!t.title">{{t.title}}</span>
|
||||
</button>
|
||||
|
||||
<nav class="tab-bar-container" role="tablist"
|
||||
[attr.aria-activedescendant]="'tab-item-' + selectedTab.tabId">
|
||||
<div class="tab-bar">
|
||||
<!-- TODO: set the ion-toolbar being on top or bottom depending upon configuration. -->
|
||||
<header *ion-toolbar class="tab-bar">
|
||||
The tabbar buttons should be in this bar.
|
||||
<button *for="#t of tabs"
|
||||
role="tab"
|
||||
class="tab-bar-item"
|
||||
@ -28,48 +41,51 @@ import {IonicComponent} from 'ionic/config/component'
|
||||
<icon [class-name]="'tab-bar-item-icon ' + t.icon" [hidden]="!t.icon"></icon>
|
||||
<span class="tab-bar-item-text" [hidden]="!t.title">{{t.title}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section class="tab-pane-container">
|
||||
<content></content>
|
||||
</section>
|
||||
`,
|
||||
directives: [For]
|
||||
directives: [For, Toolbar]
|
||||
})
|
||||
export class Tabs {
|
||||
constructor(
|
||||
@NgElement() ngElement: NgElement
|
||||
/*
|
||||
TODO once QueryList#onChange is fixed, switch to a queryList of tabs, for the
|
||||
sake of simplicity
|
||||
@Query(Tab) tabs:QueryList
|
||||
*/
|
||||
) {
|
||||
console.log("Tabs");
|
||||
this.domElement = ngElement.domElement
|
||||
this.config = Tabs.config.invoke(this)
|
||||
this.domElement = ngElement.domElement;
|
||||
this.config = Tabs.config.invoke(this);
|
||||
|
||||
this.tabs = []
|
||||
this.tabs = [];
|
||||
}
|
||||
|
||||
addTab(tab) {
|
||||
this.tabs.push(tab)
|
||||
this.tabs.push(tab);
|
||||
if (this.tabs.length == 1) {
|
||||
this.select(tab)
|
||||
this.select(tab);
|
||||
}
|
||||
}
|
||||
|
||||
onClickTabItem(ev, tab) {
|
||||
ev.preventDefault()
|
||||
if (this.selectedTab !== tab) {
|
||||
this.select(tab)
|
||||
} else if (tab._stack.length >= 2) {
|
||||
tab.popTo(0)
|
||||
this.select(tab);
|
||||
} else if (tab.nav._stack.length >= 2) {
|
||||
tab.nav.popTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
select(tab) {
|
||||
this.tabs.forEach(otherTab => {
|
||||
otherTab.setSelected(false)
|
||||
otherTab.setSelected(false);
|
||||
})
|
||||
tab.setSelected(true)
|
||||
this.selectedTab = tab
|
||||
tab.setSelected(true);
|
||||
this.selectedTab = tab;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,17 +23,11 @@ $tab-bar-item-max-width: 160px !default;
|
||||
@include flex-order($flex-order-tab-bar-bottom);
|
||||
}
|
||||
|
||||
.tab-bar-container {
|
||||
@include flex-justify-content(center);
|
||||
position: relative;
|
||||
background: $tab-bar-background-color;
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
@include flex-display();
|
||||
@include flex-justify-content(center);
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: $tab-bar-background-color;
|
||||
}
|
||||
|
||||
.tab-bar-item {
|
||||
|
@ -1,16 +1,27 @@
|
||||
<ion-nav-items side="primary">
|
||||
<button class="button" (click)="instanceCheck()">
|
||||
<icon class="ion-star"></icon>
|
||||
<header *ion-toolbar>
|
||||
|
||||
<button class="button button-primary" side="primary">
|
||||
Button 1
|
||||
</button>
|
||||
<button class="button" side="primary">
|
||||
Button 2
|
||||
</button>
|
||||
</ion-nav-items>
|
||||
|
||||
<ion-content class="padding">
|
||||
<h1 class="toolbar-title">
|
||||
My Title
|
||||
</h1>
|
||||
|
||||
<button class="button toolbar-secondary" side="secondary">
|
||||
Button 3
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<ion-content>
|
||||
<p>
|
||||
<button class="button button-primary" (click)="signIn()">
|
||||
Sign In
|
||||
</button>
|
||||
<button class="button button-primary button-outline" (click)="instanceCheck()">
|
||||
<button class="button button-primary button-outline">
|
||||
<icon class="ion-star"></icon>
|
||||
</button>
|
||||
</p>
|
||||
@ -19,6 +30,16 @@
|
||||
<input>
|
||||
</p>
|
||||
|
||||
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
|
||||
</ion-content>
|
||||
|
@ -1,27 +1,32 @@
|
||||
import {Component, View as NgView, Ancestor} from 'angular2/angular2'
|
||||
import {NavPane, Content, Nav} from 'ionic/ionic'
|
||||
import {TabsPage} from 'pages/tabs'
|
||||
import {
|
||||
Component,
|
||||
View as NgView,
|
||||
Ancestor,
|
||||
} from 'angular2/angular2';
|
||||
import {
|
||||
NavItem,
|
||||
Content,
|
||||
NavController,
|
||||
Toolbar,
|
||||
ToolbarTitle,
|
||||
} from 'ionic/ionic';
|
||||
import {TabsPage} from 'pages/tabs';
|
||||
|
||||
@Component({
|
||||
selector: 'sign-in-page'
|
||||
})
|
||||
@Component()
|
||||
@NgView({
|
||||
templateUrl: 'pages/sign-in.html',
|
||||
directives: [Content]
|
||||
directives: [Content, Toolbar, ToolbarTitle]
|
||||
})
|
||||
export class SignInPage {
|
||||
constructor(
|
||||
nav: Nav
|
||||
nav: NavController
|
||||
) {
|
||||
this.nav = nav;
|
||||
this.instanceVal = Math.random()
|
||||
}
|
||||
signIn() {
|
||||
console.log('click');
|
||||
this.nav.push(TabsPage, {
|
||||
my: 'param'
|
||||
})
|
||||
}
|
||||
instanceCheck() {
|
||||
window.alert("Instance: " + this.instanceVal)
|
||||
}
|
||||
}
|
||||
|
@ -2,16 +2,16 @@ import {
|
||||
Component,
|
||||
View as NgView,
|
||||
Parent,
|
||||
} from 'angular2/angular2'
|
||||
} from 'angular2/angular2';
|
||||
import {
|
||||
View,
|
||||
Tabs,
|
||||
Tab,
|
||||
Aside,
|
||||
Content,
|
||||
Nav,
|
||||
NavItem,
|
||||
} from 'ionic/ionic'
|
||||
NavController,
|
||||
} from 'ionic/ionic';
|
||||
import {Toolbar, ToolbarTitle} from 'ionic/components/toolbar/toolbar';
|
||||
|
||||
@Component({
|
||||
selector: 'tabs-page'
|
||||
@ -20,10 +20,10 @@ import {
|
||||
templateUrl: 'pages/tabs.html',
|
||||
directives: [Tabs, Tab, View, Content]
|
||||
})
|
||||
|
||||
export class TabsPage {
|
||||
constructor(
|
||||
navItem: NavItem,
|
||||
nav: Nav
|
||||
nav: NavController
|
||||
) {
|
||||
this.tab1Initial = Tab1Page1
|
||||
this.tab2Initial = Tab2Page1
|
||||
@ -36,18 +36,22 @@ export class TabsPage {
|
||||
//
|
||||
@Component({ selector: 't1p1' })
|
||||
@NgView({
|
||||
template: `<ion-content class="padding">
|
||||
template: `
|
||||
<header *ion-toolbar>
|
||||
<h1 class="toolbar-title">Tabs 1 Page 1</h1>
|
||||
</header>
|
||||
<ion-content class="padding">
|
||||
<p>Tab 1 Page 1.</p>
|
||||
<button class="button button-primary" (click)="next()">
|
||||
Go to Tab 1, Page 2 (push)
|
||||
</button>
|
||||
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
|
||||
</ion-content>`,
|
||||
directives: [View, Content]
|
||||
directives: [Content, Toolbar, ToolbarTitle]
|
||||
})
|
||||
class Tab1Page1 {
|
||||
// TODO change to 'Nav' injection when we're allowed to inject a tab as a nav.
|
||||
constructor(nav: Tab) {
|
||||
constructor(nav: NavController) {
|
||||
this.nav = nav;
|
||||
}
|
||||
next() {
|
||||
@ -57,19 +61,22 @@ class Tab1Page1 {
|
||||
|
||||
@Component({ selector: 't1p2' })
|
||||
@NgView({
|
||||
template: `<ion-content class="padding">
|
||||
template: `
|
||||
<header *ion-toolbar>
|
||||
<h1 class="toolbar-title">Tabs 1 Page 2</h1>
|
||||
</header>
|
||||
<ion-content class="padding">
|
||||
<p>Tab 1 Page 2.</p>
|
||||
<button class="button button-primary" (click)="pop()">
|
||||
Back to Tab 1, Page 1 (pop)
|
||||
</button>
|
||||
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
|
||||
</ion-content>
|
||||
`,
|
||||
directives: [View, Content]
|
||||
</ion-content>`,
|
||||
directives: [Content]
|
||||
})
|
||||
class Tab1Page2 {
|
||||
// TODO change to 'Nav' injection when we're allowed to inject a tab as a nav.
|
||||
constructor(nav: Tab) {
|
||||
constructor(nav: NavController) {
|
||||
this.nav = nav;
|
||||
}
|
||||
pop() { this.nav.pop(); }
|
||||
@ -98,7 +105,7 @@ class Tab1Page2 {
|
||||
})
|
||||
class Tab2Page1 {
|
||||
// TODO change to 'Nav' injection when we're allowed to inject a tab as a nav.
|
||||
constructor(nav: Tab) {
|
||||
constructor(nav: NavController) {
|
||||
this.nav = nav
|
||||
}
|
||||
next() {
|
||||
@ -131,7 +138,7 @@ class Tab2Page1 {
|
||||
})
|
||||
class Tab2Page2 {
|
||||
// TODO change to 'Nav' injection when we're allowed to inject a tab as a nav.
|
||||
constructor(nav: Tab) {
|
||||
constructor(nav: NavController) {
|
||||
this.nav = nav
|
||||
}
|
||||
pop() { this.nav.pop() }
|
||||
|
@ -1,6 +1,12 @@
|
||||
|
||||
// iOS Toolbar
|
||||
// --------------------------------------------------
|
||||
$toolbar-order-ios: (
|
||||
back-button: 1,
|
||||
primary: 2,
|
||||
title: 3,
|
||||
secondary: 4
|
||||
);
|
||||
|
||||
$toolbar-ios-height: 4.4rem !default;
|
||||
$toolbar-ios-background: #f7f7f8 !default;
|
||||
@ -16,22 +22,23 @@ $toolbar-ios-button-background-color: transparent !default;
|
||||
height: $toolbar-ios-height;
|
||||
background: $toolbar-ios-background;
|
||||
|
||||
.toolbar-primary-item {
|
||||
@include flex-order(2);
|
||||
.toolbar [side="primary"] {
|
||||
@include flex-order(map-get($toolbar-order-ios, 'primary'));
|
||||
}
|
||||
.toolbar [side="secondary"] {
|
||||
@include flex-order(map-get($toolbar-order-ios, 'secondary'));
|
||||
}
|
||||
|
||||
.toolbar-title {
|
||||
@include flex-order(3);
|
||||
@include flex-order(map-get($toolbar-order-ios, 'title'));
|
||||
font-size: $toolbar-ios-title-font-size;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.toolbar-inner-title {
|
||||
opacity: 0; // JS will set to 1 after adjusting alignment
|
||||
.toolbar-back-button {
|
||||
@include flex-order(map-get($toolbar-order-ios, 'back-button'));
|
||||
}
|
||||
|
||||
.toolbar-secondary-item {
|
||||
@include flex-order(4);
|
||||
.toolbar-title-hide {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
|
@ -1,86 +1,201 @@
|
||||
import {NgElement, Component, View as NgView, Ancestor, Optional} from 'angular2/angular2'
|
||||
import {BackButton} from 'ionic/components/toolbar/back-button'
|
||||
import {IonicComponent} from 'ionic/config/component'
|
||||
import {raf} from 'ionic/util/dom'
|
||||
import {
|
||||
NgElement,
|
||||
Component,
|
||||
Decorator,
|
||||
View as NgView,
|
||||
Viewport,
|
||||
ViewContainerRef,
|
||||
onDestroy,
|
||||
Ancestor,
|
||||
ElementRef,
|
||||
onChange,
|
||||
} from 'angular2/angular2';
|
||||
import {BackButton} from 'ionic/components/toolbar/back-button';
|
||||
import {IonicComponent} from 'ionic/config/component';
|
||||
import {NavController} from 'ionic/components/nav/nav-item';
|
||||
import {raf} from 'ionic/util/dom';
|
||||
import {platform} from 'ionic/platform/platform';
|
||||
|
||||
@Component({
|
||||
selector: 'ion-toolbar',
|
||||
@Viewport({
|
||||
selector: '[ion-toolbar]',
|
||||
properties: {
|
||||
title: 'nav-title'
|
||||
placement: 'placement'
|
||||
}
|
||||
})
|
||||
@NgView({
|
||||
template: `
|
||||
<div class="toolbar-items">
|
||||
<button class="button back-button toolbar-item" style="display:none"></button>
|
||||
<div class="toolbar-title">
|
||||
<div class="toolbar-inner-title">
|
||||
{{ title }}
|
||||
<content select="ion-nav-title"></content>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolbar-item toolbar-primary-item">
|
||||
<content select="ion-nav-items[side=primary]"></content>
|
||||
</div>
|
||||
<div class="toolbar-item toolbar-secondary-item">
|
||||
<content select="ion-nav-items[side=secondary]"></content>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
directives: [BackButton]
|
||||
})
|
||||
export class Toolbar {
|
||||
constructor(
|
||||
@NgElement() ngEle:NgElement
|
||||
viewContainer: ViewContainerRef,
|
||||
elementRef: ElementRef,
|
||||
@Ancestor() navCtrl: NavController,
|
||||
element: NgElement
|
||||
// context: Object TODO wait for angular to implement this
|
||||
) {
|
||||
this.domElement = ngEle.domElement
|
||||
this.config = Toolbar.config.invoke(this)
|
||||
this.viewContainer = viewContainer;
|
||||
this.elementRef = elementRef;
|
||||
this.navCtrl = navCtrl;
|
||||
|
||||
// TODO: make more better plz
|
||||
setTimeout(() => {
|
||||
this.alignTitle()
|
||||
}, 32)
|
||||
}
|
||||
// TODO use config to add these classes
|
||||
this.viewContainer.domElement.classList.add('toolbar');
|
||||
this.viewContainer.domElement.classList.add(`toolbar-${platform.getName()}`);
|
||||
|
||||
alignTitle() {
|
||||
let ele = this.domElement
|
||||
this.titleEle = this.titleEle || ele.querySelector('.toolbar-inner-title')
|
||||
|
||||
this.textAlign = this.textAlign || window.getComputedStyle(this.titleEle).textAlign
|
||||
|
||||
if (this.textAlign !== 'center') return
|
||||
|
||||
// dont bother if the title is already too long
|
||||
if (this.titleEle.offsetWidth < this.titleEle.scrollWidth) {
|
||||
if (!this.isTitleVisible) {
|
||||
this.titleEle.style.opacity = this.isTitleVisible = 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let leftMargin = this.titleEle.offsetLeft
|
||||
let rightMargin = ele.offsetWidth - (leftMargin + this.titleEle.offsetWidth)
|
||||
let centerMargin = leftMargin - rightMargin
|
||||
|
||||
this.titleEle.style.margin = `0 ${centerMargin}px 0 0`
|
||||
|
||||
raf(() => {
|
||||
if (this.titleEle.offsetWidth < this.titleEle.scrollWidth) {
|
||||
this.titleEle.style.margin = ''
|
||||
this.titleEle.style.textAlign = 'left'
|
||||
}
|
||||
if (!this.isTitleVisible) {
|
||||
this.titleEle.style.opacity = this.isTitleVisible = 1
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
back() {
|
||||
if (this.viewport && this.viewport._stack.length) {
|
||||
this.viewport.pop()
|
||||
// TODO Make a better way than this
|
||||
if (/header/i.test(this.viewContainer.domElement.tagName)) {
|
||||
this.placement = 'top';
|
||||
} else {
|
||||
this.placement = 'bottom';
|
||||
}
|
||||
}
|
||||
|
||||
set placement(pos) {
|
||||
this.viewContainer.domElement.classList.add(`toolbar-${pos}`);
|
||||
this._placement = pos;
|
||||
this.navCtrl.addToolbar(this._placement, this);
|
||||
this.viewContainer.domElement.setAttribute('placement', pos);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.navCtrl.removeToolbar(this);
|
||||
}
|
||||
}
|
||||
|
||||
new IonicComponent(Toolbar, {})
|
||||
|
||||
@Component({
|
||||
selector: '.toolbar-title',
|
||||
// events: {
|
||||
// 'window:resize': 'align()',
|
||||
// }
|
||||
})
|
||||
@NgView({
|
||||
template: `
|
||||
<div class="toolbar-inner-title toolbar-title-hide">
|
||||
<content></content>
|
||||
</div>`
|
||||
})
|
||||
export class ToolbarTitle {
|
||||
constructor(
|
||||
element: NgElement
|
||||
) {
|
||||
this.domElement = element.domElement;
|
||||
|
||||
// TODO find better way to get parent toolbar
|
||||
let current = this.domElement;
|
||||
while (current = current.parentNode) {
|
||||
if (current.classList.contains('toolbar')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.toolbarElement = current;
|
||||
this.align();
|
||||
}
|
||||
|
||||
align() {
|
||||
if (!this.toolbarElement) return;
|
||||
const toolbarElement = this.toolbarElement;
|
||||
const titleElement = this._titleElement || (this._titleElement = this.domElement.querySelector('.toolbar-inner-title'));
|
||||
const style = this._style || (this._style = window.getComputedStyle(titleElement));
|
||||
|
||||
const titleOffsetWidth = titleElement.offsetWidth;
|
||||
const titleOffsetLeft = titleElement.offsetLeft;
|
||||
const titleScrollWidth = titleElement.scrollWidth;
|
||||
const toolbarOffsetWidth = toolbarElement.offsetWidth;
|
||||
|
||||
//only align if the title is center and if it isn't already overflowing
|
||||
if (style.textAlign !== 'center' || titleOffsetWidth < titleScrollWidth) {
|
||||
this._showTitle();
|
||||
} else {
|
||||
let rightMargin = toolbarOffsetWidth - (titleOffsetLeft + titleOffsetWidth);
|
||||
let centerMargin = titleOffsetLeft - rightMargin;
|
||||
|
||||
titleElement.style.margin = `0 ${centerMargin}px 0 0`;
|
||||
|
||||
raf(() => {
|
||||
if (titleElement.offsetWidth < titleElement.scrollWidth) {
|
||||
this.titleElement.style.margin = ''
|
||||
this.titleElement.style.textAlign = 'left'
|
||||
}
|
||||
this._showTitle();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
_showTitle() {
|
||||
if (this._shown) return;
|
||||
this._shown = true;
|
||||
this._titleElement.classList.remove('toolbar-title-hide');
|
||||
}
|
||||
}
|
||||
|
||||
@Decorator({
|
||||
selector: '[toolbar-create]',
|
||||
properties: {
|
||||
'toolbar': 'toolbar-create'
|
||||
},
|
||||
})
|
||||
export class ToolbarContainer {
|
||||
constructor(
|
||||
viewContainer: ViewContainerRef,
|
||||
element: NgElement
|
||||
) {
|
||||
this.viewContainer = viewContainer;
|
||||
this.domElement = element.domElement;
|
||||
}
|
||||
|
||||
set toolbar(bar: Toolbar) {
|
||||
if (bar) {
|
||||
// TODO create with correct context
|
||||
this.viewContainer.create(-1, bar.viewContainer._defaultProtoView, bar.elementRef.elementInjector);
|
||||
console.log('creating viewportContainer', performance.now())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Component({
|
||||
// selector: 'ion-toolbar',
|
||||
// properties: {
|
||||
// title: 'nav-title'
|
||||
// }
|
||||
// })
|
||||
// @NgView({
|
||||
// template: `
|
||||
// <div class="toolbar-items">
|
||||
// <button class="button back-button toolbar-item" style="display:none"></button>
|
||||
|
||||
// <div class="toolbar-title">
|
||||
// <div class="toolbar-inner-title">
|
||||
// {{ title }}
|
||||
// <content select=".toolbar-title"></content>
|
||||
// </div>
|
||||
// </div>
|
||||
|
||||
// <div class="toolbar-item toolbar-primary-item">
|
||||
// <content select=".primary"></content>
|
||||
// </div>
|
||||
// <div class="toolbar-item toolbar-secondary-item">
|
||||
// <content select=".secondary"></content>
|
||||
// </div>
|
||||
// </div>
|
||||
// `,
|
||||
// directives: [BackButton]
|
||||
// })
|
||||
// export class Toolbar {
|
||||
// constructor(
|
||||
// @NgElement() ngEle:NgElement
|
||||
// ) {
|
||||
// this.domElement = ngEle.domElement;
|
||||
// this.config = Toolbar.config.invoke(this);
|
||||
|
||||
// // TODO: make more better plz
|
||||
// setTimeout(() => {
|
||||
// this.alignTitle()
|
||||
// }, 32);
|
||||
// }
|
||||
|
||||
|
||||
// back() {
|
||||
// if (this.viewport && this.viewport._stack.length) {
|
||||
// this.viewport.pop()
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
// new IonicComponent(Toolbar, {})
|
||||
|
@ -3,7 +3,16 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
$toolbar-background: #f7f7f8 !default;
|
||||
|
||||
$toolbar-order-core: (
|
||||
back-button: 1,
|
||||
title: 2,
|
||||
primary: 3,
|
||||
secondary: 4
|
||||
);
|
||||
$toolbar-primary-flex-order: 1;
|
||||
$toolbar-primary-flex-order: 1;
|
||||
$toolbar-title-flex-order: 5;
|
||||
$toolbar-secondary-flex-order: 10;
|
||||
|
||||
.toolbar {
|
||||
@include flex-display();
|
||||
@ -13,48 +22,28 @@ $toolbar-background: #f7f7f8 !default;
|
||||
background: $toolbar-background;
|
||||
}
|
||||
|
||||
.toolbar-top {
|
||||
.toolbar[placement="top"] {
|
||||
@include flex-order($flex-order-toolbar-top);
|
||||
}
|
||||
|
||||
.toolbar-bottom {
|
||||
.toolbar[placement="bottom"] {
|
||||
@include flex-order($flex-order-toolbar-bottom);
|
||||
}
|
||||
|
||||
.toolbar-items {
|
||||
@include flex-display();
|
||||
@include flex(1);
|
||||
@include flex-justify-content(space-between);
|
||||
// buttons are primary by default
|
||||
.toolbar .button,
|
||||
.toolbar [side="primary"] {
|
||||
@include flex-order(map-get($toolbar-order-core, 'primary'));
|
||||
}
|
||||
|
||||
.toolbar-item,
|
||||
.toolbar-item ion-nav-items {
|
||||
@include flex-display();
|
||||
@include flex-align-items(center);
|
||||
}
|
||||
|
||||
.toolbar .button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
@include flex-display();
|
||||
@include flex-order(1);
|
||||
}
|
||||
|
||||
.back-button-icon {
|
||||
margin-right: 5px;
|
||||
min-width: 12px;
|
||||
.toolbar [side="secondary"] {
|
||||
@include flex-order(map-get($toolbar-order-core, 'secondary'));
|
||||
}
|
||||
|
||||
.toolbar-title {
|
||||
@include flex-display();
|
||||
@include flex(1);
|
||||
@include flex-align-items(center);
|
||||
@include flex-order(2);
|
||||
@include flex-order(map-get($toolbar-order-core, 'title'));
|
||||
}
|
||||
|
||||
.toolbar-inner-title {
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
@ -62,12 +51,16 @@ $toolbar-background: #f7f7f8 !default;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.toolbar-primary-item {
|
||||
@include flex-order(3);
|
||||
// Override [ion-app] h1 margin-top
|
||||
h1.toolbar-title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.toolbar-secondary-item {
|
||||
@include flex-order(4);
|
||||
.toolbar-back-button {
|
||||
@include flex-order(map-get($toolbar-order-core, 'back-button'));
|
||||
}
|
||||
|
||||
.toolbar .button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import {NgElement} from 'angular2/angular2'
|
||||
// HACKYFILLS (hack + polyfill)
|
||||
import {NgElement, ViewContainerRef} from 'angular2/angular2'
|
||||
Object.defineProperties(NgElement.prototype, {
|
||||
domElement: {
|
||||
get: function() {
|
||||
@ -7,6 +8,14 @@ Object.defineProperties(NgElement.prototype, {
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperties(ViewContainerRef.prototype, {
|
||||
domElement: {
|
||||
get: function() {
|
||||
return this._defaultProtoView.render.delegate.element;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export * from 'ionic/components'
|
||||
export * from 'ionic/platform/platform'
|
||||
export * from 'ionic/routing/router'
|
||||
|
@ -41,7 +41,7 @@
|
||||
"components/layout/layout",
|
||||
"components/list/list",
|
||||
"components/modal/modal",
|
||||
"components/nav-pane/nav-pane",
|
||||
"components/nav/nav-item",
|
||||
"components/radio/radio",
|
||||
"components/search-bar/search-bar",
|
||||
"components/switch/switch",
|
||||
|
@ -33,7 +33,7 @@
|
||||
"yargs": "^3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"angular2": "2.0.0-alpha.20",
|
||||
"angular2": "2.0.0-alpha.21",
|
||||
"es6-module-loader": "^0.16.5",
|
||||
"hammerjs": "^2.0.4",
|
||||
"rtts_assert": "^2.0.0-alpha.20",
|
||||
|
Reference in New Issue
Block a user