Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

fix(backdrop, dialog, css): improve position and animations of backdrop #3841

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/build.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var fs = require('fs');
var versionFile = __dirname + '/../dist/commit';

module.exports = {
ngVersion: '1.3.15',
ngVersion: '1.4.3',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this sets the local testing and online docs to use 1.4.3.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I think that's good - as long as it's stable, we should be running against the latest version of Angular.

version: pkg.version,
repository: pkg.repository.url
.replace(/^git/,'https')
Expand Down
40 changes: 32 additions & 8 deletions src/components/backdrop/backdrop.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,35 @@
*
*/

angular.module('material.components.backdrop', [
'material.core'
])
.directive('mdBackdrop', BackdropDirective);

function BackdropDirective($mdTheming) {
return $mdTheming;
}
angular
.module('material.components.backdrop', ['material.core'])
.directive('mdBackdrop', function BackdropDirective($mdTheming, $animate, $rootElement, $window, $log, $$rAF) {

return {
restrict: 'E',
link: postLink
};

function postLink(scope, element, attrs) {
// backdrop may be outside the $rootElement, tell ngAnimate to animate regardless
if( $animate.pin ) $animate.pin(element,$rootElement);

$$rAF(function(){
// Often $animate.enter() is used to append the backDrop element
// so let's wait until $animate is done...

var parent = element.parent()[0];
if ( parent ) {
var position = $window.getComputedStyle(parent).getPropertyValue('position');
if (position == 'static') {
// backdrop uses position:absolute and will not work properly with parent position:static (default)
var positionError = "<md-backdrop> may not work properly in a scrolled, static-positioned parent container.";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps this should be var ERROR_CSS_POSITION ?

$log.warn( positionError );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
}

$mdTheming.inherit(element, element.parent());
});

};
});
25 changes: 14 additions & 11 deletions src/components/backdrop/backdrop.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ md-backdrop {
z-index: $z-index-sidenav - 1;
}

opacity: 1;
transition: opacity 600ms $swift-ease-in-timing-function;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit nit-picky, but this probably belongs inside the .ng-enter selector.


background-color: rgba(0,0,0,0);

position: absolute;
Expand All @@ -25,27 +28,27 @@ md-backdrop {
right: 0;

&.md-click-catcher {
top: 0;
position: fixed;
}

&.ng-enter {
animation: $swift-ease-out-timing-function mdBackdropFadeIn 0.5s both;
opacity: 0;
&.ng-enter-active {
opacity: 1;
}
}

&.ng-leave {
animation: $swift-ease-in-timing-function mdBackdropFadeOut 0.4s both;
opacity: 1;
transition: opacity 400ms linear;

&.ng-leave-active {
opacity: 0;
}
}

&.md-opaque {
background-color: rgba(0,0,0,0.42);
}
}

@keyframes mdBackdropFadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes mdBackdropFadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
4 changes: 2 additions & 2 deletions src/components/bottomSheet/bottomSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function MdBottomSheetProvider($$interimElementProvider) {
});

/* @ngInject */
function bottomSheetDefaults($animate, $mdConstant, $mdUtil, $compile, $mdTheming, $mdBottomSheet, $rootElement, $mdGesture) {
function bottomSheetDefaults($animate, $mdConstant, $mdUtil, $mdTheming, $mdBottomSheet, $rootElement, $mdGesture) {
var backdrop;

return {
Expand All @@ -143,7 +143,7 @@ function MdBottomSheetProvider($$interimElementProvider) {
element = $mdUtil.extractElementByName(element, 'md-bottom-sheet');

// Add a backdrop that will close on click
backdrop = $compile('<md-backdrop class="md-opaque md-bottom-sheet-backdrop">')(scope);
backdrop = $mdUtil.createBackdrop(scope, "md-bottom-sheet-backdrop md-opaque");
backdrop.on('click', function() {
$mdUtil.nextTick($mdBottomSheet.cancel,true);
});
Expand Down
4 changes: 2 additions & 2 deletions src/components/dialog/demoBasicUsage/index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<div ng-controller="AppCtrl" class="md-padding">
<div ng-controller="AppCtrl" class="md-padding" id="popupContainer">
<p class="inset">
Open a dialog over the app's content. Press escape or click outside to close the dialog and
send focus back to the triggering button.
</p>

<div class="dialog-demo-content" layout="row" layout-wrap>
<div class="dialog-demo-content" layout="row" layout-wrap >
<md-button class="md-primary md-raised" ng-click="showAlert($event)" flex flex-md="100">
Alert Dialog
</md-button>
Expand Down
3 changes: 1 addition & 2 deletions src/components/dialog/demoBasicUsage/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ angular.module('dialogDemo1', ['ngMaterial'])
// to prevent interaction outside of dialog
$mdDialog.show(
$mdDialog.alert()
.parent(angular.element(document.body))
.parent(angular.element(document.querySelector('#popupContainer')))
.clickOutsideToClose(true)
.title('This is an alert title')
.content('You can specify some description text in here.')
Expand All @@ -22,7 +22,6 @@ angular.module('dialogDemo1', ['ngMaterial'])
$scope.showConfirm = function(ev) {
// Appending dialog to document.body to cover sidenav in docs app
var confirm = $mdDialog.confirm()
.parent(angular.element(document.body))
.title('Would you like to delete your debt?')
.content('All of the banks have agreed to forgive you your debts.')
.ariaLabel('Lucky day')
Expand Down
3 changes: 3 additions & 0 deletions src/components/dialog/demoBasicUsage/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#popupContainer {
position:relative;
}
16 changes: 7 additions & 9 deletions src/components/dialog/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,7 @@ function MdDialogProvider($$interimElementProvider) {
}

/* @ngInject */
function dialogDefaultOptions($mdAria, $document, $mdUtil, $mdConstant, $mdTheming, $mdDialog, $animate, $q ) {

function dialogDefaultOptions($mdDialog, $mdAria, $mdUtil, $mdConstant, $animate, $document) {
return {
hasBackdrop: true,
isolateScope: true,
Expand All @@ -456,7 +455,7 @@ function MdDialogProvider($$interimElementProvider) {

captureSourceAndParent(element, options);
configureAria(element.find('md-dialog'), options);
showBackdrop(element, options);
showBackdrop(scope, element, options);

return dialogPopIn(element, options)
.then(function () {
Expand Down Expand Up @@ -492,10 +491,11 @@ function MdDialogProvider($$interimElementProvider) {
options.deactivateListeners();
options.unlockScreenReader();

options.hideBackdrop();

return dialogPopOut(element, options)
.finally(function () {
angular.element($document[0].body).removeClass('md-dialog-is-showing');
options.hideBackdrop();
element.remove();

options.origin.focus();
Expand All @@ -522,7 +522,7 @@ function MdDialogProvider($$interimElementProvider) {
options.parent = angular.element(options.parent);

if (options.disableParentScroll) {
options.restoreScroll = $mdUtil.disableScrollAround(element);
options.restoreScroll = $mdUtil.disableScrollAround(element,options.parent);
}
}

Expand Down Expand Up @@ -594,7 +594,7 @@ function MdDialogProvider($$interimElementProvider) {
/**
* Show modal backdrop element...
*/
function showBackdrop(element, options) {
function showBackdrop(scope, element, options) {

if (options.hasBackdrop) {
// Fix for IE 10
Expand All @@ -605,9 +605,7 @@ function MdDialogProvider($$interimElementProvider) {

element.css('top', parentOffset + 'px');

options.backdrop = angular.element('<md-backdrop class="md-dialog-backdrop md-opaque">');
options.backdrop.css('top', parentOffset + 'px');
$mdTheming.inherit(options.backdrop, options.parent);
options.backdrop = $mdUtil.createBackdrop(scope, "md-dialog-backdrop md-opaque");

$animate.enter(options.backdrop, options.parent);
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/dialog/dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ $dialog-padding: $baseline-grid * 3;
display: flex;
justify-content: center;
align-items: center;
position: fixed;
position: absolute;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to hear from @rschmukler on this one, just to confirm that this is safe and we aren't missing some edge case.

top: 0;
left: 0;
width: 100%;
Expand Down
1 change: 0 additions & 1 deletion src/components/menu/_menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ function MenuDirective($mdMenu) {
triggerElement = triggerElement.querySelector('[ng-click]');
}
triggerElement && triggerElement.setAttribute('aria-haspopup', 'true');
triggerElement.setAttribute('type', 'button');
if (templateElement.children().length != 2) {
throw Error('Invalid HTML for md-menu. Expected two children elements.');
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/menu/menu-interim-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function MenuProvider($$interimElementProvider) {
target: angular.element(opts.target), //make sure it's not a naked dom node
parent: angular.element(opts.parent),
menuContentEl: angular.element(element[0].querySelector('md-menu-content')),
backdrop: opts.hasBackdrop && angular.element('<md-backdrop class="md-menu-backdrop md-click-catcher">')
backdrop: opts.hasBackdrop && $mdUtil.createBackdrop(scope, "md-menu-backdrop md-click-catcher")
});
}

Expand Down
5 changes: 0 additions & 5 deletions src/components/menu/menu.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ describe('md-menu directive', function () {
expect(menu.firstElementChild.nodeName).toBe('BUTTON');
});

it('specifies button type', inject(function($compile, $rootScope) {
var menu = setup()[0];
expect(menu.firstElementChild.getAttribute('type')).toBe('button');
}));

it('opens on click', function () {
var menu = setup();
openMenu(menu);
Expand Down
6 changes: 2 additions & 4 deletions src/components/select/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ function SelectProvider($$interimElementProvider) {
});

/* @ngInject */
function selectDefaultOptions($mdSelect, $mdConstant, $$rAF, $mdUtil, $mdTheming, $window, $q, $log ) {
function selectDefaultOptions($mdSelect, $mdConstant, $$rAF, $mdUtil, $mdTheming, $window, $q, $compile ) {
var animator = $mdUtil.dom.animator;

return {
Expand All @@ -774,7 +774,7 @@ function SelectProvider($$interimElementProvider) {
parent: angular.element(opts.parent),
selectEl: element.find('md-select-menu'),
contentEl: element.find('md-content'),
backdrop: opts.hasBackdrop && angular.element('<md-backdrop class="md-select-backdrop md-click-catcher">')
backdrop: opts.hasBackdrop && $mdUtil.createBackdrop(scope, "md-select-backdrop md-click-catcher")
});

opts.resizeFn = function() {
Expand Down Expand Up @@ -847,8 +847,6 @@ function SelectProvider($$interimElementProvider) {
element.addClass('md-clickable');

opts.backdrop && opts.backdrop.on('click', function(e) {
$log.debug("backdrop click");

e.preventDefault();
e.stopPropagation();
opts.restoreFocus = false;
Expand Down
6 changes: 2 additions & 4 deletions src/components/sidenav/sidenav.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ function SidenavFocusDirective() {
* - `<md-sidenav md-is-locked-open="$mdMedia('min-width: 1000px')"></md-sidenav>`
* - `<md-sidenav md-is-locked-open="$mdMedia('sm')"></md-sidenav>` (locks open on small screens)
*/
function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $animate, $parse, $log, $compile, $q, $document) {
function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $animate, $compile, $parse, $log, $q, $document) {
return {
restrict: 'E',
scope: {
Expand Down Expand Up @@ -240,9 +240,7 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $animate,
$mdMedia: $mdMedia
});
};
var backdrop = $compile(
'<md-backdrop class="md-sidenav-backdrop md-opaque ng-enter">'
)(scope);
var backdrop = $mdUtil.createBackdrop(scope, "md-sidenav-backdrop md-opaque ng-enter");

element.on('$destroy', sidenavCtrl.destroy);
$mdTheming.inherit(backdrop, element);
Expand Down
3 changes: 2 additions & 1 deletion src/core/services/compiler/compiler.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
angular.module('material.core')
angular
.module('material.core')
.service('$mdCompiler', mdCompilerService);

function mdCompilerService($q, $http, $injector, $compile, $controller, $templateCache) {
Expand Down
7 changes: 5 additions & 2 deletions src/core/services/interimElement/interimElement.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ describe('$$interimElement service', function() {

beforeEach(module('material.core'));

var $rootScope, $animate, $timeout;
var $rootScope, $animate, $q, $timeout;
var $compilerSpy, $themingSpy;

describe('provider', function() {
Expand Down Expand Up @@ -250,7 +250,10 @@ describe('$$interimElement service', function() {

beforeEach(function() {
setup();
inject(function($$interimElement) {
inject(function($$interimElement, _$q_, _$timeout_) {
$q = _$q_;
$timeout = _$timeout_;

Service = $$interimElement();

Service.show = tailHook(Service.show, flush);
Expand Down
19 changes: 14 additions & 5 deletions src/core/util/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
var nextUniqueId = 0;

angular.module('material.core')
.factory('$mdUtil', function ($cacheFactory, $document, $timeout, $q, $window, $mdConstant, $$rAF, $rootScope, $$mdAnimate) {
.factory('$mdUtil', function ($cacheFactory, $document, $timeout, $q, $compile, $window, $mdConstant, $$rAF, $rootScope, $$mdAnimate) {
var $mdUtil = {
dom : { },
now: window.performance ?
Expand Down Expand Up @@ -47,14 +47,14 @@ angular.module('material.core')
},

// Disables scroll around the passed element.
disableScrollAround: function (element) {
disableScrollAround: function (element, parent) {
$mdUtil.disableScrollAround._count = $mdUtil.disableScrollAround._count || 0;
++$mdUtil.disableScrollAround._count;
if ($mdUtil.disableScrollAround._enableScrolling) return $mdUtil.disableScrollAround._enableScrolling;
element = angular.element(element);
var body = $document[0].body,
restoreBody = disableBodyScroll(),
restoreElement = disableElementScroll();
restoreElement = disableElementScroll(parent);

return $mdUtil.disableScrollAround._enableScrolling = function () {
if (!--$mdUtil.disableScrollAround._count) {
Expand All @@ -65,13 +65,14 @@ angular.module('material.core')
};

// Creates a virtual scrolling mask to absorb touchmove, keyboard, scrollbar clicking, and wheel events
function disableElementScroll() {
function disableElementScroll(element) {
element = angular.element(element || body)[0];
var zIndex = 50;
var scrollMask = angular.element(
'<div class="md-scroll-mask" style="z-index: ' + zIndex + '">' +
' <div class="md-scroll-mask-bar"></div>' +
'</div>');
body.appendChild(scrollMask[0]);
element.appendChild(scrollMask[0]);

scrollMask.on('wheel', preventDefault);
scrollMask.on('touchmove', preventDefault);
Expand Down Expand Up @@ -174,6 +175,14 @@ angular.module('material.core')
node.dispatchEvent(newEvent);
},

/**
* facade to build md-backdrop element with desired styles
* NOTE: Use $compile to trigger backdrop postLink function
*/
createBackdrop : function(scope, addClass){
return $compile( $mdUtil.supplant('<md-backdrop class="{0}">',[addClass]) )(scope);
},

/**
* supplant() method from Crockford's `Remedial Javascript`
* Equivalent to use of $interpolate; without dependency on
Expand Down