Skip to content

Commit a1a582b

Browse files
committed
fix(ion-backdrop): new ion-backdrop can prevent background scrolling
closes #6656
1 parent c42bf97 commit a1a582b

File tree

21 files changed

+153
-115
lines changed

21 files changed

+153
-115
lines changed

src/components.core.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
// Core Components
1616
@import
17+
"components/backdrop/backdrop",
1718
"components/grid/grid",
1819
"components/icon/icon",
1920
"components/img/img",

src/components/action-sheet/action-sheet.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ export class ActionSheet extends ViewController {
215215
@Component({
216216
selector: 'ion-action-sheet',
217217
template:
218-
'<div (click)="bdClick()" tappable disable-activated class="backdrop" role="presentation"></div>' +
218+
'<ion-backdrop (click)="bdClick()"></ion-backdrop>' +
219219
'<div class="action-sheet-wrapper">' +
220220
'<div class="action-sheet-container">' +
221221
'<div class="action-sheet-group">' +
@@ -384,7 +384,7 @@ class ActionSheetSlideIn extends Transition {
384384
super(opts);
385385

386386
let ele = enteringView.pageRef().nativeElement;
387-
let backdrop = new Animation(ele.querySelector('.backdrop'));
387+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
388388
let wrapper = new Animation(ele.querySelector('.action-sheet-wrapper'));
389389

390390
backdrop.fromTo('opacity', 0.01, 0.4);
@@ -401,7 +401,7 @@ class ActionSheetSlideOut extends Transition {
401401
super(opts);
402402

403403
let ele = leavingView.pageRef().nativeElement;
404-
let backdrop = new Animation(ele.querySelector('.backdrop'));
404+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
405405
let wrapper = new Animation(ele.querySelector('.action-sheet-wrapper'));
406406

407407
backdrop.fromTo('opacity', 0.4, 0);
@@ -418,7 +418,7 @@ class ActionSheetMdSlideIn extends Transition {
418418
super(opts);
419419

420420
let ele = enteringView.pageRef().nativeElement;
421-
let backdrop = new Animation(ele.querySelector('.backdrop'));
421+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
422422
let wrapper = new Animation(ele.querySelector('.action-sheet-wrapper'));
423423

424424
backdrop.fromTo('opacity', 0.01, 0.26);
@@ -435,7 +435,7 @@ class ActionSheetMdSlideOut extends Transition {
435435
super(opts);
436436

437437
let ele = leavingView.pageRef().nativeElement;
438-
let backdrop = new Animation(ele.querySelector('.backdrop'));
438+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
439439
let wrapper = new Animation(ele.querySelector('.action-sheet-wrapper'));
440440

441441
backdrop.fromTo('opacity', 0.26, 0);
@@ -451,7 +451,7 @@ class ActionSheetWpSlideIn extends Transition {
451451
super(opts);
452452

453453
let ele = enteringView.pageRef().nativeElement;
454-
let backdrop = new Animation(ele.querySelector('.backdrop'));
454+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
455455
let wrapper = new Animation(ele.querySelector('.action-sheet-wrapper'));
456456

457457
backdrop.fromTo('opacity', 0.01, 0.16);
@@ -468,7 +468,7 @@ class ActionSheetWpSlideOut extends Transition {
468468
super(opts);
469469

470470
let ele = leavingView.pageRef().nativeElement;
471-
let backdrop = new Animation(ele.querySelector('.backdrop'));
471+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
472472
let wrapper = new Animation(ele.querySelector('.action-sheet-wrapper'));
473473

474474
backdrop.fromTo('opacity', 0.1, 0);

src/components/action-sheet/test/basic/e2e.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ it('should open action sheet', function() {
44
});
55

66
it('should close with backdrop click', function() {
7-
element(by.css('.backdrop')).click();
7+
element(by.css('ion-backdrop')).click();
88
});

src/components/alert/alert.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ export class Alert extends ViewController {
311311
@Component({
312312
selector: 'ion-alert',
313313
template:
314-
'<div (click)="bdClick()" tappable disable-activated class="backdrop" role="presentation"></div>' +
314+
'<ion-backdrop (click)="bdClick()"></ion-backdrop>' +
315315
'<div class="alert-wrapper">' +
316316
'<div class="alert-head">' +
317317
'<h2 id="{{hdrId}}" class="alert-title" *ngIf="d.title" [innerHTML]="d.title"></h2>' +
@@ -612,7 +612,7 @@ class AlertPopIn extends Transition {
612612
super(opts);
613613

614614
let ele = enteringView.pageRef().nativeElement;
615-
let backdrop = new Animation(ele.querySelector('.backdrop'));
615+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
616616
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
617617

618618
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
@@ -633,7 +633,7 @@ class AlertPopOut extends Transition {
633633
super(opts);
634634

635635
let ele = leavingView.pageRef().nativeElement;
636-
let backdrop = new Animation(ele.querySelector('.backdrop'));
636+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
637637
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
638638

639639
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
@@ -654,7 +654,7 @@ class AlertMdPopIn extends Transition {
654654
super(opts);
655655

656656
let ele = enteringView.pageRef().nativeElement;
657-
let backdrop = new Animation(ele.querySelector('.backdrop'));
657+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
658658
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
659659

660660
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
@@ -675,7 +675,7 @@ class AlertMdPopOut extends Transition {
675675
super(opts);
676676

677677
let ele = leavingView.pageRef().nativeElement;
678-
let backdrop = new Animation(ele.querySelector('.backdrop'));
678+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
679679
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
680680

681681
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
@@ -697,7 +697,7 @@ class AlertWpPopIn extends Transition {
697697
super(opts);
698698

699699
let ele = enteringView.pageRef().nativeElement;
700-
let backdrop = new Animation(ele.querySelector('.backdrop'));
700+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
701701
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
702702

703703
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.3', '1');
@@ -718,7 +718,7 @@ class AlertWpPopOut extends Transition {
718718
super(opts);
719719

720720
let ele = leavingView.pageRef().nativeElement;
721-
let backdrop = new Animation(ele.querySelector('.backdrop'));
721+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
722722
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
723723

724724
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '1.3');

src/components/alert/alert.wp.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ $alert-wp-checkbox-icon-transform: rotate(45deg) !default;
100100

101101

102102
ion-alert {
103-
.backdrop {
103+
ion-backdrop {
104104
background: $alert-wp-backdrop-background;
105105
}
106106
}

src/components/backdrop/backdrop.scss

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@import "../../globals.core";
2+
3+
// Backdrop
4+
// --------------------------------------------------
5+
6+
$backdrop-color: #000 !default;
7+
8+
ion-backdrop {
9+
position: absolute;
10+
top: 0;
11+
left: 0;
12+
z-index: $z-index-backdrop;
13+
display: block;
14+
15+
width: 100%;
16+
height: 100%;
17+
18+
background-color: $backdrop-color;
19+
opacity: 0.01;
20+
transform: translateZ(0);
21+
}
22+
23+
ion-backdrop.hide-backdrop {
24+
display: none;
25+
}

src/components/backdrop/backdrop.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import {Directive, ViewEncapsulation, HostListener, ElementRef, Input} from '@angular/core';
2+
import {isTrueProperty} from '../../util/util';
3+
4+
const DISABLE_SCROLL = 'disable-scroll';
5+
6+
/**
7+
* @private
8+
*/
9+
@Directive({
10+
selector: 'ion-backdrop',
11+
host: {
12+
'role': 'presentation',
13+
'tappable': '',
14+
'disable-activated': ''
15+
},
16+
})
17+
export class Backdrop {
18+
private static nuBackDrops: number = 0;
19+
20+
private static push() {
21+
if (this.nuBackDrops === 0) {
22+
console.debug('adding .disable-scroll to body');
23+
document.body.classList.add(DISABLE_SCROLL);
24+
} else {
25+
console.warn('several backdrops on screen? probably a bug');
26+
}
27+
this.nuBackDrops++;
28+
}
29+
30+
private static pop() {
31+
if (this.nuBackDrops === 0) {
32+
console.error('pop requires a push');
33+
return;
34+
}
35+
this.nuBackDrops--;
36+
if (this.nuBackDrops === 0) {
37+
console.debug('removing .disable-scroll from body');
38+
document.body.classList.remove(DISABLE_SCROLL);
39+
}
40+
}
41+
42+
private pushed: boolean = false;
43+
@Input() disableScroll = true;
44+
45+
constructor(public elementRef: ElementRef) {}
46+
47+
ngOnInit() {
48+
if (isTrueProperty(this.disableScroll)) {
49+
Backdrop.push();
50+
this.pushed = true;
51+
}
52+
}
53+
54+
ngOnDestroy() {
55+
if (this.pushed) {
56+
Backdrop.pop();
57+
this.pushed = false;
58+
}
59+
}
60+
61+
}

src/components/loading/loading.scss

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// Loading Indicator
44
// --------------------------------------------------
55

6-
76
ion-loading {
87
position: absolute;
98
top: 0;
@@ -26,10 +25,3 @@ ion-loading {
2625

2726
opacity: 0;
2827
}
29-
30-
// Loading Backdrop
31-
// -----------------------------------------
32-
33-
.hide-backdrop {
34-
display: none;
35-
}

src/components/loading/loading.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export class Loading extends ViewController {
156156
@Component({
157157
selector: 'ion-loading',
158158
template:
159-
'<div disable-activated class="backdrop" [class.hide-backdrop]="!d.showBackdrop" role="presentation"></div>' +
159+
'<ion-backdrop [class.hide-backdrop]="!d.showBackdrop"></ion-backdrop>' +
160160
'<div class="loading-wrapper">' +
161161
'<div *ngIf="showSpinner" class="loading-spinner">' +
162162
'<ion-spinner [name]="d.spinner"></ion-spinner>' +
@@ -240,7 +240,7 @@ export interface LoadingOptions {
240240
super(opts);
241241

242242
let ele = enteringView.pageRef().nativeElement;
243-
let backdrop = new Animation(ele.querySelector('.backdrop'));
243+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
244244
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
245245

246246
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
@@ -261,7 +261,7 @@ export interface LoadingOptions {
261261
super(opts);
262262

263263
let ele = leavingView.pageRef().nativeElement;
264-
let backdrop = new Animation(ele.querySelector('.backdrop'));
264+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
265265
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
266266

267267
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
@@ -282,7 +282,7 @@ export interface LoadingOptions {
282282
super(opts);
283283

284284
let ele = enteringView.pageRef().nativeElement;
285-
let backdrop = new Animation(ele.querySelector('.backdrop'));
285+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
286286
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
287287

288288
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
@@ -303,7 +303,7 @@ export interface LoadingOptions {
303303
super(opts);
304304

305305
let ele = leavingView.pageRef().nativeElement;
306-
let backdrop = new Animation(ele.querySelector('.backdrop'));
306+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
307307
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
308308

309309
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
@@ -324,7 +324,7 @@ export interface LoadingOptions {
324324
super(opts);
325325

326326
let ele = enteringView.pageRef().nativeElement;
327-
let backdrop = new Animation(ele.querySelector('.backdrop'));
327+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
328328
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
329329

330330
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.3', '1');
@@ -345,7 +345,7 @@ export interface LoadingOptions {
345345
super(opts);
346346

347347
let ele = leavingView.pageRef().nativeElement;
348-
let backdrop = new Animation(ele.querySelector('.backdrop'));
348+
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
349349
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
350350

351351
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '1.3');

src/components/menu/menu.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ ion-menu[side=right] {
2828
left: auto;
2929
}
3030

31-
ion-menu .backdrop {
31+
ion-menu ion-backdrop {
3232
z-index: -1;
3333
display: none;
3434
}
@@ -74,13 +74,13 @@ ion-menu[type=overlay] {
7474
left: -8px; // make up for the box-shadow hanging over on the left
7575
z-index: $z-index-menu-overlay;
7676

77-
.backdrop {
77+
ion-backdrop {
7878
left: -3000px;
7979
display: block;
8080

8181
width: 6000px;
8282

83-
opacity: .01;
83+
opacity: 0.01;
8484
transform: translate3d(-9999px, 0, 0);
8585

8686
&.show-backdrop {

0 commit comments

Comments
 (0)