mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 05:21:52 +08:00
fix(popover): position MD popover on top of element clicked
fixes #6683
This commit is contained in:
@ -4,7 +4,7 @@ import {App, Page, Popover, NavController, Content, NavParams} from 'ionic-angul
|
|||||||
|
|
||||||
@Page({
|
@Page({
|
||||||
template: `
|
template: `
|
||||||
<ion-list radio-group [(ngModel)]="fontFamily" (change)="changeFontFamily()">
|
<ion-list radio-group [(ngModel)]="fontFamily" (ionChange)="changeFontFamily()">
|
||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<button (click)="changeFontSize('smaller')" ion-item detail-none class="text-button text-smaller">A</button>
|
<button (click)="changeFontSize('smaller')" ion-item detail-none class="text-button text-smaller">A</button>
|
||||||
|
@ -10,7 +10,8 @@ import {isPresent, isUndefined, isDefined} from '../../util/util';
|
|||||||
import {nativeRaf, CSS} from '../../util/dom';
|
import {nativeRaf, CSS} from '../../util/dom';
|
||||||
import {ViewController} from '../nav/view-controller';
|
import {ViewController} from '../nav/view-controller';
|
||||||
|
|
||||||
const POPOVER_BODY_PADDING = 2;
|
const POPOVER_IOS_BODY_PADDING = 2;
|
||||||
|
const POPOVER_MD_BODY_PADDING = 12;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Popover
|
* @name Popover
|
||||||
@ -240,8 +241,7 @@ class PopoverTransition extends Transition {
|
|||||||
super(opts);
|
super(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mdPositionView(nativeEle: HTMLElement, ev) {
|
||||||
positionView(nativeEle: HTMLElement, ev) {
|
|
||||||
let originY = 'top';
|
let originY = 'top';
|
||||||
let originX = 'left';
|
let originX = 'left';
|
||||||
|
|
||||||
@ -257,19 +257,73 @@ class PopoverTransition extends Transition {
|
|||||||
let bodyWidth = window.innerWidth;
|
let bodyWidth = window.innerWidth;
|
||||||
let bodyHeight = window.innerHeight;
|
let bodyHeight = window.innerHeight;
|
||||||
|
|
||||||
let targetTop = (bodyHeight / 2) - (popoverHeight / 2);
|
// If ev was passed, use that for target element
|
||||||
let targetLeft = bodyWidth / 2;
|
let targetDim = ev && ev.target && ev.target.getBoundingClientRect();
|
||||||
let targetWidth = 0;
|
|
||||||
let targetHeight = 0;
|
let targetTop = targetDim && targetDim.top || (bodyHeight / 2) - (popoverHeight / 2);
|
||||||
|
let targetLeft = targetDim && targetDim.left || bodyWidth / 2 - (popoverWidth / 2);
|
||||||
|
let targetWidth = targetDim && targetDim.width || 0;
|
||||||
|
let targetHeight = targetDim && targetDim.height || 0;
|
||||||
|
|
||||||
|
let popoverCSS = {
|
||||||
|
top: targetTop,
|
||||||
|
left: targetLeft
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the popover left is less than the padding it is off screen
|
||||||
|
// to the left so adjust it, else if the width of the popover
|
||||||
|
// exceeds the body width it is off screen to the right so adjust
|
||||||
|
if (popoverCSS.left < POPOVER_MD_BODY_PADDING) {
|
||||||
|
popoverCSS.left = POPOVER_MD_BODY_PADDING;
|
||||||
|
} else if (popoverWidth + POPOVER_MD_BODY_PADDING + popoverCSS.left > bodyWidth) {
|
||||||
|
popoverCSS.left = bodyWidth - popoverWidth - POPOVER_MD_BODY_PADDING;
|
||||||
|
originX = 'right';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the popover when popped down stretches past bottom of screen,
|
||||||
|
// make it pop up if there's room above
|
||||||
|
if (targetTop + targetHeight + popoverHeight > bodyHeight && targetTop - popoverHeight > 0) {
|
||||||
|
popoverCSS.top = targetTop - popoverHeight;
|
||||||
|
nativeEle.className = nativeEle.className + ' popover-bottom';
|
||||||
|
originY = 'bottom';
|
||||||
|
// If there isn't room for it to pop up above the target cut it off
|
||||||
|
} else if (targetTop + targetHeight + popoverHeight > bodyHeight) {
|
||||||
|
popoverEle.style.bottom = POPOVER_MD_BODY_PADDING + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
popoverEle.style.top = popoverCSS.top + 'px';
|
||||||
|
popoverEle.style.left = popoverCSS.left + 'px';
|
||||||
|
|
||||||
|
popoverEle.style[CSS.transformOrigin] = originY + ' ' + originX;
|
||||||
|
|
||||||
|
// Since the transition starts before styling is done we
|
||||||
|
// want to wait for the styles to apply before showing the wrapper
|
||||||
|
popoverWrapperEle.style.opacity = '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
iosPositionView(nativeEle: HTMLElement, ev) {
|
||||||
|
let originY = 'top';
|
||||||
|
let originX = 'left';
|
||||||
|
|
||||||
|
let popoverWrapperEle = <HTMLElement>nativeEle.querySelector('.popover-wrapper');
|
||||||
|
|
||||||
|
// Popover content width and height
|
||||||
|
let popoverEle = <HTMLElement>nativeEle.querySelector('.popover-content');
|
||||||
|
let popoverDim = popoverEle.getBoundingClientRect();
|
||||||
|
let popoverWidth = popoverDim.width;
|
||||||
|
let popoverHeight = popoverDim.height;
|
||||||
|
|
||||||
|
// Window body width and height
|
||||||
|
let bodyWidth = window.innerWidth;
|
||||||
|
let bodyHeight = window.innerHeight;
|
||||||
|
|
||||||
// If ev was passed, use that for target element
|
// If ev was passed, use that for target element
|
||||||
if (ev && ev.target) {
|
let targetDim = ev && ev.target && ev.target.getBoundingClientRect();
|
||||||
let targetDim = ev.target.getBoundingClientRect();
|
|
||||||
targetTop = targetDim.top;
|
let targetTop = targetDim && targetDim.top || (bodyHeight / 2) - (popoverHeight / 2);
|
||||||
targetLeft = targetDim.left;
|
let targetLeft = targetDim && targetDim.left || bodyWidth / 2;
|
||||||
targetWidth = targetDim.width;
|
let targetWidth = targetDim && targetDim.width || 0;
|
||||||
targetHeight = targetDim.height;
|
let targetHeight = targetDim && targetDim.height || 0;
|
||||||
}
|
|
||||||
|
|
||||||
// The arrow that shows above the popover on iOS
|
// The arrow that shows above the popover on iOS
|
||||||
var arrowEle = <HTMLElement>nativeEle.querySelector('.popover-arrow');
|
var arrowEle = <HTMLElement>nativeEle.querySelector('.popover-arrow');
|
||||||
@ -290,10 +344,10 @@ class PopoverTransition extends Transition {
|
|||||||
// If the popover left is less than the padding it is off screen
|
// If the popover left is less than the padding it is off screen
|
||||||
// to the left so adjust it, else if the width of the popover
|
// to the left so adjust it, else if the width of the popover
|
||||||
// exceeds the body width it is off screen to the right so adjust
|
// exceeds the body width it is off screen to the right so adjust
|
||||||
if (popoverCSS.left < POPOVER_BODY_PADDING) {
|
if (popoverCSS.left < POPOVER_IOS_BODY_PADDING) {
|
||||||
popoverCSS.left = POPOVER_BODY_PADDING;
|
popoverCSS.left = POPOVER_IOS_BODY_PADDING;
|
||||||
} else if (popoverWidth + POPOVER_BODY_PADDING + popoverCSS.left > bodyWidth) {
|
} else if (popoverWidth + POPOVER_IOS_BODY_PADDING + popoverCSS.left > bodyWidth) {
|
||||||
popoverCSS.left = bodyWidth - popoverWidth - POPOVER_BODY_PADDING;
|
popoverCSS.left = bodyWidth - popoverWidth - POPOVER_IOS_BODY_PADDING;
|
||||||
originX = 'right';
|
originX = 'right';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +360,7 @@ class PopoverTransition extends Transition {
|
|||||||
originY = 'bottom';
|
originY = 'bottom';
|
||||||
// If there isn't room for it to pop up above the target cut it off
|
// If there isn't room for it to pop up above the target cut it off
|
||||||
} else if (targetTop + targetHeight + popoverHeight > bodyHeight) {
|
} else if (targetTop + targetHeight + popoverHeight > bodyHeight) {
|
||||||
popoverEle.style.bottom = POPOVER_BODY_PADDING + '%';
|
popoverEle.style.bottom = POPOVER_IOS_BODY_PADDING + '%';
|
||||||
}
|
}
|
||||||
|
|
||||||
arrowEle.style.top = arrowCSS.top + 'px';
|
arrowEle.style.top = arrowCSS.top + 'px';
|
||||||
@ -344,7 +398,7 @@ class PopoverPopIn extends PopoverTransition {
|
|||||||
|
|
||||||
play() {
|
play() {
|
||||||
nativeRaf(() => {
|
nativeRaf(() => {
|
||||||
this.positionView(this.enteringView.pageRef().nativeElement, this.opts.ev);
|
this.iosPositionView(this.enteringView.pageRef().nativeElement, this.opts.ev);
|
||||||
super.play();
|
super.play();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -394,7 +448,7 @@ class PopoverMdPopIn extends PopoverTransition {
|
|||||||
|
|
||||||
play() {
|
play() {
|
||||||
nativeRaf(() => {
|
nativeRaf(() => {
|
||||||
this.positionView(this.enteringView.pageRef().nativeElement, this.opts.ev);
|
this.mdPositionView(this.enteringView.pageRef().nativeElement, this.opts.ev);
|
||||||
super.play();
|
super.play();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import {App, Page, Popover, NavController, Content, NavParams, ViewController} f
|
|||||||
|
|
||||||
@Page({
|
@Page({
|
||||||
template: `
|
template: `
|
||||||
<ion-list radio-group [(ngModel)]="fontFamily" (change)="changeFontFamily()">
|
<ion-list radio-group [(ngModel)]="fontFamily" (ionChange)="changeFontFamily()">
|
||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<button (click)="changeFontSize('smaller')" ion-item detail-none class="text-button text-smaller">A</button>
|
<button (click)="changeFontSize('smaller')" ion-item detail-none class="text-button text-smaller">A</button>
|
||||||
|
@ -19,6 +19,11 @@
|
|||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
|
|
||||||
<ion-content #popoverContent padding>
|
<ion-content #popoverContent padding>
|
||||||
|
<ion-list>
|
||||||
|
<button ion-item (click)="presentListPopover($event)">
|
||||||
|
Present List Popover
|
||||||
|
</button>
|
||||||
|
</ion-list>
|
||||||
|
|
||||||
<button block (click)="presentListPopover($event)" class="e2eOpenListPopover">
|
<button block (click)="presentListPopover($event)" class="e2eOpenListPopover">
|
||||||
Present List Popover
|
Present List Popover
|
||||||
|
Reference in New Issue
Block a user