mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +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({
|
||||
template: `
|
||||
<ion-list radio-group [(ngModel)]="fontFamily" (change)="changeFontFamily()">
|
||||
<ion-list radio-group [(ngModel)]="fontFamily" (ionChange)="changeFontFamily()">
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<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 {ViewController} from '../nav/view-controller';
|
||||
|
||||
const POPOVER_BODY_PADDING = 2;
|
||||
const POPOVER_IOS_BODY_PADDING = 2;
|
||||
const POPOVER_MD_BODY_PADDING = 12;
|
||||
|
||||
/**
|
||||
* @name Popover
|
||||
@ -240,8 +241,7 @@ class PopoverTransition extends Transition {
|
||||
super(opts);
|
||||
}
|
||||
|
||||
|
||||
positionView(nativeEle: HTMLElement, ev) {
|
||||
mdPositionView(nativeEle: HTMLElement, ev) {
|
||||
let originY = 'top';
|
||||
let originX = 'left';
|
||||
|
||||
@ -257,19 +257,73 @@ class PopoverTransition extends Transition {
|
||||
let bodyWidth = window.innerWidth;
|
||||
let bodyHeight = window.innerHeight;
|
||||
|
||||
let targetTop = (bodyHeight / 2) - (popoverHeight / 2);
|
||||
let targetLeft = bodyWidth / 2;
|
||||
let targetWidth = 0;
|
||||
let targetHeight = 0;
|
||||
// If ev was passed, use that for target element
|
||||
let targetDim = ev && ev.target && ev.target.getBoundingClientRect();
|
||||
|
||||
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 && ev.target) {
|
||||
let targetDim = ev.target.getBoundingClientRect();
|
||||
targetTop = targetDim.top;
|
||||
targetLeft = targetDim.left;
|
||||
targetWidth = targetDim.width;
|
||||
targetHeight = targetDim.height;
|
||||
}
|
||||
let targetDim = ev && ev.target && ev.target.getBoundingClientRect();
|
||||
|
||||
let targetTop = targetDim && targetDim.top || (bodyHeight / 2) - (popoverHeight / 2);
|
||||
let targetLeft = targetDim && targetDim.left || bodyWidth / 2;
|
||||
let targetWidth = targetDim && targetDim.width || 0;
|
||||
let targetHeight = targetDim && targetDim.height || 0;
|
||||
|
||||
// The arrow that shows above the popover on iOS
|
||||
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
|
||||
// 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_BODY_PADDING) {
|
||||
popoverCSS.left = POPOVER_BODY_PADDING;
|
||||
} else if (popoverWidth + POPOVER_BODY_PADDING + popoverCSS.left > bodyWidth) {
|
||||
popoverCSS.left = bodyWidth - popoverWidth - POPOVER_BODY_PADDING;
|
||||
if (popoverCSS.left < POPOVER_IOS_BODY_PADDING) {
|
||||
popoverCSS.left = POPOVER_IOS_BODY_PADDING;
|
||||
} else if (popoverWidth + POPOVER_IOS_BODY_PADDING + popoverCSS.left > bodyWidth) {
|
||||
popoverCSS.left = bodyWidth - popoverWidth - POPOVER_IOS_BODY_PADDING;
|
||||
originX = 'right';
|
||||
}
|
||||
|
||||
@ -306,7 +360,7 @@ class PopoverTransition extends Transition {
|
||||
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_BODY_PADDING + '%';
|
||||
popoverEle.style.bottom = POPOVER_IOS_BODY_PADDING + '%';
|
||||
}
|
||||
|
||||
arrowEle.style.top = arrowCSS.top + 'px';
|
||||
@ -344,7 +398,7 @@ class PopoverPopIn extends PopoverTransition {
|
||||
|
||||
play() {
|
||||
nativeRaf(() => {
|
||||
this.positionView(this.enteringView.pageRef().nativeElement, this.opts.ev);
|
||||
this.iosPositionView(this.enteringView.pageRef().nativeElement, this.opts.ev);
|
||||
super.play();
|
||||
});
|
||||
}
|
||||
@ -394,7 +448,7 @@ class PopoverMdPopIn extends PopoverTransition {
|
||||
|
||||
play() {
|
||||
nativeRaf(() => {
|
||||
this.positionView(this.enteringView.pageRef().nativeElement, this.opts.ev);
|
||||
this.mdPositionView(this.enteringView.pageRef().nativeElement, this.opts.ev);
|
||||
super.play();
|
||||
});
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import {App, Page, Popover, NavController, Content, NavParams, ViewController} f
|
||||
|
||||
@Page({
|
||||
template: `
|
||||
<ion-list radio-group [(ngModel)]="fontFamily" (change)="changeFontFamily()">
|
||||
<ion-list radio-group [(ngModel)]="fontFamily" (ionChange)="changeFontFamily()">
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<button (click)="changeFontSize('smaller')" ion-item detail-none class="text-button text-smaller">A</button>
|
||||
|
@ -19,6 +19,11 @@
|
||||
</ion-navbar>
|
||||
|
||||
<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">
|
||||
Present List Popover
|
||||
|
Reference in New Issue
Block a user