Skip to content

Commit 2cd1b51

Browse files
committed
feat(popover): position the popover on transition instead of create
references #5420
1 parent a96e36a commit 2cd1b51

File tree

4 files changed

+87
-67
lines changed

4 files changed

+87
-67
lines changed

src/components/popover/popover.ios.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ $popover-ios-background: #f3f3f3 !default;
3030
.popover-arrow {
3131
position: absolute;
3232
display: block;
33-
top: -20px;
3433
width: 20px;
3534
height: 10px;
3635
overflow: hidden;

src/components/popover/popover.ts

Lines changed: 76 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ class PopoverCmp {
8686
private _renderer: Renderer,
8787
private _config: Config,
8888
private _navParams: NavParams,
89-
private _viewCtrl: ViewController,
90-
private _platform: Platform
89+
private _viewCtrl: ViewController
9190
) {
9291
this.d = _navParams.data.opts;
9392
this.created = Date.now();
@@ -108,31 +107,55 @@ class PopoverCmp {
108107
});
109108
}
110109

111-
ngOnInit() {
112-
if (this.d.event) {
113-
this.positionView(this.d.event);
114-
}
115-
}
116-
117110
onPageDidEnter() {
118111
let activeElement: any = document.activeElement;
119112
if (document.activeElement) {
120113
activeElement.blur();
121114
}
122115
}
123116

124-
positionView(ev) {
125-
let nativeEle = this._elementRef.nativeElement;
117+
dismiss(role): Promise<any> {
118+
return this._viewCtrl.dismiss(null, role);
119+
}
120+
121+
bdClick() {
122+
if (this.isEnabled() && this.d.enableBackdropDismiss) {
123+
this.dismiss('backdrop');
124+
}
125+
}
126126

127+
isEnabled() {
128+
let tm = this._config.getNumber('overlayCreatedDiff', 750);
129+
return (this.created + tm < Date.now());
130+
}
131+
}
132+
133+
export interface PopoverOptions {
134+
cssClass?: string;
135+
showBackdrop?: boolean;
136+
enableBackdropDismiss?: boolean;
137+
}
138+
139+
/**
140+
* Animations for popover
141+
*/
142+
class PopoverTransition extends Transition {
143+
constructor(opts: TransitionOptions) {
144+
super(opts);
145+
}
146+
147+
positionView(nativeEle: HTMLElement, ev) {
127148
// Popover wrapper width and height
128-
let popoverEle = nativeEle.querySelector('.popover-wrapper');
149+
let popoverEle = <HTMLElement>nativeEle.querySelector('.popover-wrapper');
129150
let popoverDim = popoverEle.getBoundingClientRect();
130151
let popoverWidth = popoverDim.width;
131152
let popoverHeight = popoverDim.height;
132153

133154
// Window body width and height
134-
let bodyWidth = this._platform.width();
135-
let bodyHeight = this._platform.height();
155+
// let bodyWidth = this._platform.width();
156+
// let bodyHeight = this._platform.height();
157+
let bodyWidth = window.innerWidth;
158+
let bodyHeight = window.innerHeight;
136159

137160
// Target element width and height
138161
let targetDim = ev.target.getBoundingClientRect();
@@ -142,7 +165,7 @@ class PopoverCmp {
142165
let targetHeight = targetDim.height;
143166

144167
// The arrow that shows above the popover on iOS
145-
var arrowEle = nativeEle.querySelector('.popover-arrow');
168+
var arrowEle = <HTMLElement>nativeEle.querySelector('.popover-arrow');
146169
let arrowDim = arrowEle.getBoundingClientRect();
147170
var arrowWidth = arrowDim.width;
148171
var arrowHeight = arrowDim.height;
@@ -171,166 +194,163 @@ class PopoverCmp {
171194
if (popoverCSS.top + POPOVER_BODY_PADDING + popoverHeight > bodyHeight && popoverCSS.top - popoverHeight > 0) {
172195
arrowCSS.top = targetTop - (arrowHeight + 1);
173196
popoverCSS.top = targetTop - popoverHeight - (arrowHeight - 1);
174-
this._renderer.setElementClass(this._elementRef.nativeElement, 'popover-bottom', true);
197+
nativeEle.className = nativeEle.className + ' popover-bottom';
175198
}
176199

177-
this._renderer.setElementStyle(arrowEle, 'top', arrowCSS.top + 'px');
178-
this._renderer.setElementStyle(arrowEle, 'left', arrowCSS.left + 'px');
179-
180-
this._renderer.setElementStyle(popoverEle, 'top', popoverCSS.top + 'px');
181-
this._renderer.setElementStyle(popoverEle, 'left', popoverCSS.left + 'px');
182-
}
183-
184-
dismiss(role): Promise<any> {
185-
return this._viewCtrl.dismiss(null, role);
186-
}
187-
188-
bdClick() {
189-
if (this.isEnabled() && this.d.enableBackdropDismiss) {
190-
this.dismiss('backdrop');
191-
}
192-
}
200+
arrowEle.style.top = arrowCSS.top + 'px';
201+
arrowEle.style.left = arrowCSS.left + 'px';
193202

194-
isEnabled() {
195-
let tm = this._config.getNumber('overlayCreatedDiff', 750);
196-
return (this.created + tm < Date.now());
203+
popoverEle.style.top = popoverCSS.top + 'px';
204+
popoverEle.style.left = popoverCSS.left + 'px';
197205
}
198206
}
199207

200-
export interface PopoverOptions {
201-
event?: any;
202-
cssClass?: string;
203-
showBackdrop?: boolean;
204-
enableBackdropDismiss?: boolean;
205-
}
206-
207-
/**
208-
* Animations for popover
209-
*/
210-
class PopoverPopIn extends Transition {
208+
class PopoverPopIn extends PopoverTransition {
211209
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
212210
super(opts);
213211

214-
console.log(opts);
215-
216212
let ele = enteringView.pageRef().nativeElement;
213+
this.positionView(ele, opts.ev);
214+
217215
let backdrop = new Animation(ele.querySelector('.backdrop'));
216+
let arrow = new Animation(ele.querySelector('.popover-arrow'));
218217
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
219218

219+
arrow.fromTo('opacity', '0.01', '1');
220220
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
221221
backdrop.fromTo('opacity', '0.01', '0.3');
222222

223223
this
224224
.easing('ease-in-out')
225225
.duration(200)
226226
.add(backdrop)
227+
.add(arrow)
227228
.add(wrapper);
228229
}
229230
}
230231
Transition.register('popover-pop-in', PopoverPopIn);
231232

232233

233-
class PopoverPopOut extends Transition {
234+
class PopoverPopOut extends PopoverTransition {
234235
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
235236
super(opts);
236237

237238
let ele = leavingView.pageRef().nativeElement;
238239
let backdrop = new Animation(ele.querySelector('.backdrop'));
240+
let arrow = new Animation(ele.querySelector('.popover-arrow'));
239241
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
240242

243+
arrow.fromTo('opacity', '1', '0');
241244
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
242245
backdrop.fromTo('opacity', '0.3', '0');
243246

244247
this
245248
.easing('ease-in-out')
246249
.duration(200)
247250
.add(backdrop)
251+
.add(arrow)
248252
.add(wrapper);
249253
}
250254
}
251255
Transition.register('popover-pop-out', PopoverPopOut);
252256

253257

254-
class PopoverMdPopIn extends Transition {
258+
class PopoverMdPopIn extends PopoverTransition {
255259
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
256260
super(opts);
257261

258262
let ele = enteringView.pageRef().nativeElement;
263+
this.positionView(ele, opts.ev);
264+
259265
let backdrop = new Animation(ele.querySelector('.backdrop'));
266+
let arrow = new Animation(ele.querySelector('.popover-arrow'));
260267
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
261268

269+
arrow.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
262270
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
263271
backdrop.fromTo('opacity', '0.01', '0.5');
264272

265273
this
266274
.easing('ease-in-out')
267275
.duration(200)
268276
.add(backdrop)
269-
.add(wrapper);
277+
.add(wrapper)
278+
.add(arrow);
270279
}
271280
}
272281
Transition.register('popover-md-pop-in', PopoverMdPopIn);
273282

274283

275-
class PopoverMdPopOut extends Transition {
284+
class PopoverMdPopOut extends PopoverTransition {
276285
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
277286
super(opts);
278287

279288
let ele = leavingView.pageRef().nativeElement;
280289
let backdrop = new Animation(ele.querySelector('.backdrop'));
290+
let arrow = new Animation(ele.querySelector('.popover-arrow'));
281291
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
282292

293+
arrow.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
283294
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
284295
backdrop.fromTo('opacity', '0.5', '0');
285296

286297
this
287298
.easing('ease-in-out')
288299
.duration(200)
289300
.add(backdrop)
290-
.add(wrapper);
301+
.add(wrapper)
302+
.add(arrow);
291303
}
292304
}
293305
Transition.register('popover-md-pop-out', PopoverMdPopOut);
294306

295307

296308

297-
class PopoverWpPopIn extends Transition {
309+
class PopoverWpPopIn extends PopoverTransition {
298310
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
299311
super(opts);
300312

301313
let ele = enteringView.pageRef().nativeElement;
314+
this.positionView(ele, opts.ev);
315+
302316
let backdrop = new Animation(ele.querySelector('.backdrop'));
317+
let arrow = new Animation(ele.querySelector('.popover-arrow'));
303318
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
304319

320+
arrow.fromTo('opacity', '0.01', '1').fromTo('scale', '1.3', '1');
305321
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.3', '1');
306322
backdrop.fromTo('opacity', '0.01', '0.5');
307323

308324
this
309325
.easing('cubic-bezier(0,0 0.05,1)')
310326
.duration(200)
311327
.add(backdrop)
312-
.add(wrapper);
328+
.add(wrapper)
329+
.add(arrow);
313330
}
314331
}
315332
Transition.register('popover-wp-pop-in', PopoverWpPopIn);
316333

317334

318-
class PopoverWpPopOut extends Transition {
335+
class PopoverWpPopOut extends PopoverTransition {
319336
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
320337
super(opts);
321338

322339
let ele = leavingView.pageRef().nativeElement;
323340
let backdrop = new Animation(ele.querySelector('.backdrop'));
341+
let arrow = new Animation(ele.querySelector('.popover-arrow'));
324342
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
325343

344+
arrow.fromTo('opacity', '1', '0').fromTo('scale', '1', '1.3');
326345
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '1.3');
327346
backdrop.fromTo('opacity', '0.5', '0');
328347

329348
this
330349
.easing('ease-out')
331350
.duration(150)
332351
.add(backdrop)
333-
.add(wrapper);
352+
.add(wrapper)
353+
.add(arrow);
334354
}
335355
}
336356
Transition.register('popover-wp-pop-out', PopoverWpPopOut);

src/components/popover/test/basic/index.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@ class PopoverPage {
2222
templateUrl: 'main.html'
2323
})
2424
class E2EPage {
25-
constructor(private nav: NavController) {}
25+
popover: any;
2626

27-
presentPopover(ev) {
28-
let popover = Popover.create(PopoverPage, {}, {
29-
event: ev
30-
});
27+
constructor(private nav: NavController) {}
3128

32-
this.nav.present(popover);
29+
createPopover() {
30+
this.popover = Popover.create(PopoverPage);
31+
}
3332

34-
this.nav.present(popover, {
33+
presentPopover(ev) {
34+
this.createPopover();
35+
this.nav.present(this.popover, {
3536
ev: ev
3637
});
3738
}

src/components/popover/test/basic/main.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<ion-navbar *navbar primary>
2-
<ion-buttons start>
2+
<ion-buttons left>
33
<button (click)="presentPopover($event)">
4-
<ion-icon name="options"></ion-icon>
4+
<ion-icon name="person"></ion-icon>
55
</button>
66
<button (click)="presentPopover($event)">
7-
<ion-icon name="more"></ion-icon>
7+
<ion-icon name="search"></ion-icon>
88
</button>
99
</ion-buttons>
1010
<ion-title>Popover</ion-title>

0 commit comments

Comments
 (0)