mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
Merge remote-tracking branch 'origin/master'
Conflicts: src/components/app/_scaffolding.scss
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -26,3 +26,4 @@ temp
|
||||
dist
|
||||
|
||||
.idea
|
||||
/src/components/split-view/test/settings/main.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)
|
||||
}))
|
||||
|
95
src/components/app/_scaffolding.scss.orig
Normal file
95
src/components/app/_scaffolding.scss.orig
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) )
|
||||
}
|
||||
}
|
||||
|
@ -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: `
|
||||
<ion-view [view-title]="viewTitle">
|
||||
<div class="split-pane-container">
|
||||
<ion-view [nav-title]="navTitle" class="split-view">
|
||||
<div class="pane-container">
|
||||
<content></content>
|
||||
</div>
|
||||
</ion-view>
|
||||
<ion-nav-viewport split-viewport>
|
||||
</ion-nav-viewport>
|
||||
<style>
|
||||
ion-split-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
ion-split-view > .view.split-view {
|
||||
max-width: 300px;
|
||||
border-right: 1px solid black;
|
||||
z-index: 1;
|
||||
}
|
||||
ion-split-view > ion-nav-viewport[split-viewport] {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
</style>
|
||||
`,
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import {View} from 'ionic2/components'
|
||||
})
|
||||
@Template({
|
||||
inline: `
|
||||
<ion-view view-title="General">
|
||||
<ion-view nav-title="General Stuff">
|
||||
General Settings
|
||||
</ion-view>
|
||||
`,
|
||||
|
70
src/components/split-view/test/settings/groups/privacy.js
Normal file
70
src/components/split-view/test/settings/groups/privacy.js
Normal file
@ -0,0 +1,70 @@
|
||||
import {Component, Template} from 'angular2/angular2'
|
||||
import {View, NavView} from 'ionic2/components'
|
||||
|
||||
@Component({ selector: 'privacy-settings' })
|
||||
@Template({
|
||||
inline: `
|
||||
<ion-view nav-title="Privacy">
|
||||
Privacy
|
||||
<button class="button button-primary" (click)="next()">
|
||||
Next
|
||||
</button>
|
||||
</ion-view>`,
|
||||
directives: [View]
|
||||
})
|
||||
export class SettingsPrivacy {
|
||||
constructor(navView: NavView) {
|
||||
this.navView = navView
|
||||
}
|
||||
next() {
|
||||
this.navView.push(PrivacyP1)
|
||||
}
|
||||
}
|
||||
|
||||
@Component({ selector: 'privp1' })
|
||||
@Template({
|
||||
inline: `
|
||||
<ion-view view-title="Privacy Page 1">
|
||||
This is page 1
|
||||
<button class="button button-primary" (click)="next()">
|
||||
Next
|
||||
</button>
|
||||
<button class="button" (click)="pop()">
|
||||
Back
|
||||
</button>
|
||||
</ion-view>
|
||||
`,
|
||||
directives: [View]
|
||||
})
|
||||
class PrivacyP1 {
|
||||
constructor(navView: NavView) {
|
||||
this.navView = navView
|
||||
}
|
||||
next() {
|
||||
this.navView.push(PrivacyP2)
|
||||
}
|
||||
pop() {
|
||||
this.navView.pop()
|
||||
}
|
||||
}
|
||||
|
||||
@Component({ selector: 'privp2' })
|
||||
@Template({
|
||||
inline: `
|
||||
<ion-view view-title="Privacy Page 2">
|
||||
Page 2 here
|
||||
<button class="button" (click)="pop()">
|
||||
Back
|
||||
</button>
|
||||
</ion-view>
|
||||
`,
|
||||
directives: [View]
|
||||
})
|
||||
class PrivacyP2 {
|
||||
constructor(navView: NavView) {
|
||||
this.navView = navView
|
||||
}
|
||||
pop() {
|
||||
this.navView.pop()
|
||||
}
|
||||
}
|
@ -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: `
|
||||
<ion-split-view view-title="Settings" [default-view]="default">
|
||||
Hello, split
|
||||
</ion-split-view>
|
||||
`,
|
||||
directives: [SplitView]
|
||||
})
|
||||
class SettingsSplit {
|
||||
constructor() {
|
||||
this.default = SettingsGeneral
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: '[ion-app]'
|
||||
})
|
||||
@Template({
|
||||
inline: `
|
||||
<ion-nav-viewport [initial]="initial">
|
||||
</ion-nav-viewport>
|
||||
`,
|
||||
directives: [NavViewport]
|
||||
})
|
||||
class App {
|
||||
constructor() {
|
||||
this.initial = SettingsSplit
|
||||
}
|
||||
}
|
||||
|
||||
bootstrap(App)
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user