diff --git a/.gitignore b/.gitignore index ad37266e79..99b5582a3a 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ temp dist .idea +/src/components/split-view/test/settings/main.js diff --git a/gulpfile.js b/gulpfile.js index 12c9d3b3c4..e3d21ad880 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -73,7 +73,9 @@ gulp.task('ionic-js', ['ionic-compile'], function() { return gulp.src(buildConfig.distLib + '/ionic2.js') .pipe(through2.obj(function(file, enc, next) { var contents = file.contents.toString() - contents = contents.replace(/"src\//g, '"ionic2/') + contents = contents + .replace(/"src\//g, '"ionic2/') + .replace(new RegExp(' = void 0 in ','g'), ' in '); file.contents = new Buffer(contents) next(null, file) })) diff --git a/src/components/app/_scaffolding.scss.orig b/src/components/app/_scaffolding.scss.orig new file mode 100644 index 0000000000..27ed831366 --- /dev/null +++ b/src/components/app/_scaffolding.scss.orig @@ -0,0 +1,95 @@ +html { + height: 100%; +} + +[ion-app] { + @include flex-display(); + @include flex-direction(column); + + overflow: hidden; + height: 100%; + max-width: 100%; + max-height: 100%; + margin: 0; + padding: 0; + + .nav-viewport { +<<<<<<< HEAD + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + } + + .nav-viewport.tab { + position: relative; + } + + .nav-view { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +======= + /* position: absolute; */ + /* width: 100%; */ + /* height: 100%; */ + position: relative; + flex: 1; +>>>>>>> origin/master + } + + .pane { + position: relative; + height: 100%; + width: 100%; + + @include flex-display(); + @include flex-direction(column); + @include flex(1); + } + + .view-cover { + height: 100vh !important; + + .tab-bar { + z-index: 1 + } + } + + .pane > .pane-container { + position: relative; + overflow: hidden; + + @include flex-display(); + @include flex-order(40); + @include flex(1); + @include flex-direction(column); + } + + .pane-container > .pane { + position: absolute; + min-height: 100%; + } + + .pane > .pane-container > .content { + position: relative; + z-index: $z-index-content; + @include flex(1); + } + + .scroll-content { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow-y: scroll; + -webkit-overflow-scrolling: touch; + } + +} diff --git a/src/components/nav-view/nav-view.js b/src/components/nav-view/nav-view.js index b2c8feb694..e86b425256 100644 --- a/src/components/nav-view/nav-view.js +++ b/src/components/nav-view/nav-view.js @@ -30,7 +30,9 @@ export class NavView { set item(navItem) { if (this.initialized) return; this.initialized = true; + this.Class = navItem.Class; this.loader.load(navItem.Class, this.location).then(instance => { + this.instance = instance navItem.finishSetup(this, instance) }) } @@ -45,16 +47,12 @@ export class NavView { /** * Go back */ - pop() { - return this.viewport.pop() + pop(opts) { + return this.viewport.pop(opts) } - popTo(index: Number) { - if (this._stack.length < index + 1) return - while (tab._stack.length > index + 1) { - tab.pop({ sync: true }) // pop with no animation - } - return tab.pop() //pop last one with animation + popTo(index, opts) { + return this.viewport.popTo(index, opts) } } diff --git a/src/components/nav-viewport/nav-viewport.js b/src/components/nav-viewport/nav-viewport.js index f0770a729b..0808ffb2d5 100644 --- a/src/components/nav-viewport/nav-viewport.js +++ b/src/components/nav-viewport/nav-viewport.js @@ -35,6 +35,15 @@ export class NavViewport { return this._ngForLoopArray } + containsClass(Class) { + for (let i = 0; i < this._stack.length; i++) { + if (this._stack[i].Class === Class) { + return true + } + } + return false + } + set initial(Class) { if (!this.initialized) { this.initialized = true @@ -54,15 +63,18 @@ export class NavViewport { // TODO make sure the timing is together // TODO allow starting an animation in the middle (eg gestures). Leave // most of this up to the animation's implementation. - push(Class: Function, { sync = this._stack.length === 0 } = {}) { - let opts = {sync} + push(Class: Function, opts = {}) { + util.defaults(opts, { + sync: this._stack.length === 0 + }) + let pushedItem = new NavItem(Class) this._stack.push(pushedItem) this._ngForLoopArray.push(pushedItem) return pushedItem.waitForSetup().then(() => { - let current = this.getPrevious(pushedItem) - current && current.leave( util.extend({reverse:true}, opts) ) + let current = this._getPrevious(pushedItem) + current && current.leaveReverse(opts) return pushedItem.enter(opts) }) } @@ -72,27 +84,71 @@ export class NavViewport { * * @param shouldAnimate whether to animate */ - pop({ sync = false } = {}) { - let opts = {sync} + pop(opts = {}) { + util.defaults(opts, { + sync: false + }) let current = this._stack.pop() - let previous = this._stack[this._stack.length - 1] + let dest = this.peek() - previous && previous.enter( util.extend({reverse:true}, opts) ) - return current && current.leave(opts).then(remove) + dest && dest.enterReverse(opts) + return current && current.leave(opts).then(() => this._destroy(current)) } - getPrevious(item) { + peek() { + return this._stack[this._stack.length - 1] + } + + popAll() { + while (this._stack.length) { + const item = this._stack.pop() + this._destroy(item) + } + } + + // Pop from the current item to the item at the specified index. + // Removes every item in the stack between the current and the given index, + // then performs a normal pop. + popTo(index, opts = {}) { + // Abort if we're already here. + if (this._stack.length <= index + 1) { + return Promise.resolve() + } + + // Save the current navItem, and remove all the other ones in front of our + // target nav item. + const current = this._stack.pop() + while (this._stack.length > index + 1) { + const item = this._stack.pop() + this._destroy(item) + } + + // Now put the current navItem back on the stack and run a normal pop animation. + this._stack.push(current) + return this.pop(opts) + } + + setStack(stack) { + this._stack = stack.slice() + this._ngForLoopArray = stack.slice() + } + + remove(index) { + const item = this._stack[index] + this._stack.splice(index, 1) + this._destroy(item) + } + + _destroy(navItem) { + console.warn( +`Component "${navItem.Class.name}" was popped from the nav stack, But we're keeping its element in the DOM for now because of an ng2 bug.` + ); + //util.array.remove(this._ngForLoopArray, navItem) + } + + _getPrevious(item) { return this._stack[ this._stack.indexOf(item) - 1 ] } - - // Animate a new view *in* - _animateIn(view) { - - } - - // Animate an old view *out* - _animateOut(view) { - } } class NavItem { @@ -139,6 +195,9 @@ class NavItem { return Promise.resolve() } } + enterReverse(opts) { + return this.enter( util.extend({reverse: true}, opts) ) + } enter({ reverse = false, sync = false } = {}) { return this._animate({ isShown: true, @@ -151,4 +210,7 @@ class NavItem { animation: sync ? null : (reverse ? 'leave-reverse' : 'leave') }) } + leaveReverse(opts) { + return this.leave( util.extend({reverse: true}, opts) ) + } } diff --git a/src/components/split-view/split-view.js b/src/components/split-view/split-view.js index d048a42007..3e362a6743 100644 --- a/src/components/split-view/split-view.js +++ b/src/components/split-view/split-view.js @@ -2,6 +2,9 @@ import {Component, Parent, Decorator, Template, NgElement} from 'angular2/angula import {NavViewport} from 'ionic2/components/nav-viewport/nav-viewport' import {View} from 'ionic2/components/view/view' import {NavView} from 'ionic2/components/nav-view/nav-view' +import * as util from 'ionic2/util' + +// TODO consider more explicit API, a la tabs /** * SplitViewportDecorator is temporary until the SplitView is able to query @@ -23,18 +26,34 @@ class SplitViewportDecorator { selector: 'ion-split-view', bind: { defaultView: 'defaultView', - viewTitle: 'viewTitle' - } + navTitle: 'navTitle' + }, }) @Template({ inline: ` - -
+ +
+ `, directives: [SplitViewportDecorator, NavViewport, View] }) @@ -45,34 +64,57 @@ export class SplitView { ) { this.domElement = element.domElement this.navView = navView + + // TODO mq.addEventListener() doesn't work with zone.js + // let checkScreen = () => { + // const mq = window.matchMedia('(min-width: 720px)') + // this.setEnabled(mq.matches) + // } + // window.addEventListener('resize', checkScreen) + // checkScreen() + this.setEnabled(true) } - set defaultView(def) { - this.splitViewport.push(def) + // Sets the first view to be shown in the viewport to the right of the splitView. + set defaultView(DefaultClass) { + this.splitViewport.push(DefaultClass, {sync: true}) + } + + isActive(Class) { + for (let item of this.splitViewport._stack) { + if (item.Class === Class) return true + } + return false } setNavViewport(viewport) { this.splitViewport = viewport - this.navView.push = function(Class, opts) { - opts = opts || {} - util.defaults(opts, { sync: true }) - if (this.splitViewport._stack.indexOf(Class) !== -1) { - this.splitViewport.popTo(0) - } else { - while (this.splitViewport._stack.length) { - this.splitViewport.pop({sync: true}) + this.navView.__$push = this.navView.push + this.navView.push = (Class, opts) => { + if (this.isEnabled) { + opts = opts || {} + util.defaults(opts, { sync: true }) + if (this.splitViewport.containsClass(Class)) { + return this.splitViewport.popTo(0) + } else { + this.splitViewport.popAll() + return this.splitViewport.push(Class, opts) } - this.splitViewport.push(Class, opts) + } else { + return this.navView.__$push(Class, opts) } - } + }; } // TODO set enabled depending on some condition (media query in this case) setEnabled(isEnabled) { - this.isSplitView = isEnabled - if (isEnabled) { + if (isEnabled !== this.isEnabled) { + if (isEnabled) { + this.splitViewport + } + this.isEnabled = isEnabled } } } diff --git a/src/components/split-view/test/settings/groups/general.js b/src/components/split-view/test/settings/groups/general.js index 182c02ddf2..8119c09c2c 100644 --- a/src/components/split-view/test/settings/groups/general.js +++ b/src/components/split-view/test/settings/groups/general.js @@ -6,7 +6,7 @@ import {View} from 'ionic2/components' }) @Template({ inline: ` - + General Settings `, diff --git a/src/components/split-view/test/settings/groups/privacy.js b/src/components/split-view/test/settings/groups/privacy.js new file mode 100644 index 0000000000..6dcb036f02 --- /dev/null +++ b/src/components/split-view/test/settings/groups/privacy.js @@ -0,0 +1,70 @@ +import {Component, Template} from 'angular2/angular2' +import {View, NavView} from 'ionic2/components' + +@Component({ selector: 'privacy-settings' }) +@Template({ + inline: ` + + Privacy + +`, + directives: [View] +}) +export class SettingsPrivacy { + constructor(navView: NavView) { + this.navView = navView + } + next() { + this.navView.push(PrivacyP1) + } +} + +@Component({ selector: 'privp1' }) +@Template({ + inline: ` + +This is page 1 + + + +`, + directives: [View] +}) +class PrivacyP1 { + constructor(navView: NavView) { + this.navView = navView + } + next() { + this.navView.push(PrivacyP2) + } + pop() { + this.navView.pop() + } +} + +@Component({ selector: 'privp2' }) +@Template({ + inline: ` + +Page 2 here + + +`, + directives: [View] +}) +class PrivacyP2 { + constructor(navView: NavView) { + this.navView = navView + } + pop() { + this.navView.pop() + } +} diff --git a/src/components/split-view/test/settings/main.js b/src/components/split-view/test/settings/main.js deleted file mode 100644 index 9d9ec72f40..0000000000 --- a/src/components/split-view/test/settings/main.js +++ /dev/null @@ -1,38 +0,0 @@ -import {Component, Template, bootstrap} from 'angular2/angular2' -import {SplitView, NavViewport} from 'ionic2/components' -import {SettingsGeneral} from 'app/groups/general' - -@Component({ - selector: 'settings-split' -}) -@Template({ - inline: ` - - Hello, split - - `, - directives: [SplitView] -}) -class SettingsSplit { - constructor() { - this.default = SettingsGeneral - } -} - -@Component({ - selector: '[ion-app]' -}) -@Template({ - inline: ` - - - `, - directives: [NavViewport] -}) -class App { - constructor() { - this.initial = SettingsSplit - } -} - -bootstrap(App) diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index 29f35ffa00..e7e0c590c0 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -36,11 +36,9 @@ export class Tabs { @NgElement() ngElement: NgElement ) { this.domElement = ngElement.domElement - this.domElement.classList.add('pane') this.config = Tabs.config.invoke(this) - this.tabs = [] } @@ -56,10 +54,7 @@ export class Tabs { if (this.selectedTab !== tab) { this.select(tab) } else if (tab._stack.length >= 2) { - while (tab._stack.length > 2) { - tab.pop({ sync: true }) // pop with no animation - } - tab.pop() //pop last one with animation + tab.popTo(0) } }