fix(popover): position MD popover on top of element clicked

fixes #6683
This commit is contained in:
Brandy Carney
2016-05-31 13:40:36 -04:00
parent c897c344cc
commit 6bd91f02a3
4 changed files with 82 additions and 23 deletions

View File

@ -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>

View File

@ -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();
});
}

View File

@ -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>

View File

@ -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