mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-06-22 10:24:18 +00:00
MODULE-TYPO
- Sass set-up - md-list - md-theming (install)
This commit is contained in:
+32
@@ -0,0 +1,32 @@
|
||||
<md-dialog aria-label="Mango (Fruit)">
|
||||
|
||||
<md-content>
|
||||
<md-subheader class="md-sticky-no-effect">Mango (Fruit)</md-subheader>
|
||||
<p>
|
||||
The mango is a juicy stone fruit belonging to the genus Mangifera, consisting of numerous tropical fruiting trees, cultivated mostly for edible fruit. The majority of these species are found in nature as wild mangoes. They all belong to the flowering plant family Anacardiaceae. The mango is native to South and Southeast Asia, from where it has been distributed worldwide to become one of the most cultivated fruits in the tropics.
|
||||
</p>
|
||||
|
||||
<img style="margin: auto; max-width: 100%;" src="img/mangues.jpg">
|
||||
|
||||
<p>
|
||||
The highest concentration of Mangifera genus is in the western part of Malesia (Sumatra, Java and Borneo) and in Burma and India. While other Mangifera species (e.g. horse mango, M. foetida) are also grown on a more localized basis, Mangifera indica—the "common mango" or "Indian mango"—is the only mango tree commonly cultivated in many tropical and subtropical regions.
|
||||
</p>
|
||||
<p>
|
||||
It originated in Indian subcontinent (present day India and Pakistan) and Burma. It is the national fruit of India, Pakistan, and the Philippines, and the national tree of Bangladesh. In several cultures, its fruit and leaves are ritually used as floral decorations at weddings, public celebrations, and religious ceremonies.
|
||||
</p>
|
||||
</md-content>
|
||||
|
||||
<div class="md-actions" layout="row">
|
||||
<md-button href="http://en.wikipedia.org/wiki/Mango" target="_blank" hide show-md>
|
||||
More on Wikipedia
|
||||
</md-button>
|
||||
<span flex></span>
|
||||
<md-button ng-click="answer('not useful')">
|
||||
Not Useful
|
||||
</md-button>
|
||||
<md-button ng-click="answer('useful')" class="md-primary">
|
||||
Useful
|
||||
</md-button>
|
||||
</div>
|
||||
|
||||
</md-dialog>
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
<div ng-controller="AppCtrl" class="full" layout="column" layout-margin>
|
||||
<p class="inset">
|
||||
Open a dialog over the app's content. Press escape or click outside to close the dialog.
|
||||
</p>
|
||||
|
||||
<div layout="column" layout-align="center" >
|
||||
<md-button class="md-primary" ng-click="showAlert($event)">
|
||||
Alert Dialog
|
||||
</md-button>
|
||||
<div class="gap"></div>
|
||||
<md-button class="md-primary" ng-click="showConfirm($event)">
|
||||
Confirm Dialog
|
||||
</md-button>
|
||||
<div class="gap"></div>
|
||||
<md-button class="md-primary" ng-click="showAdvanced($event)">
|
||||
Custom Dialog
|
||||
</md-button>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<b layout="row" layout-align="center center" layout-margin>
|
||||
{{alert}}
|
||||
</b>
|
||||
</div>
|
||||
Vendored
+59
@@ -0,0 +1,59 @@
|
||||
angular.module('dialogDemo1', ['ngMaterial'])
|
||||
|
||||
.controller('AppCtrl', function($scope, $mdDialog) {
|
||||
$scope.alert = '';
|
||||
|
||||
$scope.showAlert = function(ev) {
|
||||
$mdDialog.show(
|
||||
$mdDialog.alert()
|
||||
.title('This is an alert title')
|
||||
.content('You can specify some description text in here.')
|
||||
.ariaLabel('Password notification')
|
||||
.ok('Got it!')
|
||||
.targetEvent(ev)
|
||||
);
|
||||
};
|
||||
|
||||
$scope.showConfirm = function(ev) {
|
||||
var confirm = $mdDialog.confirm()
|
||||
.title('Would you like to delete your debt?')
|
||||
.content('All of the banks have agreed to forgive you your debts.')
|
||||
.ariaLabel('Lucky day')
|
||||
.ok('Please do it!')
|
||||
.cancel('Sounds like a scam')
|
||||
.targetEvent(ev);
|
||||
|
||||
$mdDialog.show(confirm).then(function() {
|
||||
$scope.alert = 'You decided to get rid of your debt.';
|
||||
}, function() {
|
||||
$scope.alert = 'You decided to keep your debt.';
|
||||
});
|
||||
};
|
||||
|
||||
$scope.showAdvanced = function(ev) {
|
||||
$mdDialog.show({
|
||||
controller: DialogController,
|
||||
templateUrl: 'dialog1.tmpl.html',
|
||||
targetEvent: ev,
|
||||
})
|
||||
.then(function(answer) {
|
||||
$scope.alert = 'You said the information was "' + answer + '".';
|
||||
}, function() {
|
||||
$scope.alert = 'You cancelled the dialog.';
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
function DialogController($scope, $mdDialog) {
|
||||
$scope.hide = function() {
|
||||
$mdDialog.hide();
|
||||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
$mdDialog.cancel();
|
||||
};
|
||||
|
||||
$scope.answer = function(answer) {
|
||||
$mdDialog.hide(answer);
|
||||
};
|
||||
}
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
.full {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.gap {
|
||||
width:50px;
|
||||
}
|
||||
|
||||
|
||||
.md-subheader {
|
||||
background-color: #dcedc8;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2.md-subheader {
|
||||
margin: 0px;
|
||||
margin-left: -24px;
|
||||
margin-right: -24px;
|
||||
margin-top: -24px;
|
||||
}
|
||||
|
||||
h2.md-subheader.md-sticky-clone {
|
||||
margin-right:0px;
|
||||
margin-top:0px;
|
||||
|
||||
box-shadow: 0px 2px 4px 0 rgba(0,0,0,0.16);
|
||||
}
|
||||
|
||||
h2 .md-subheader-content {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
$dialog-border-radius: 4px !default;
|
||||
|
||||
md-dialog.md-THEME_NAME-theme {
|
||||
border-radius: $dialog-border-radius;
|
||||
background-color: '{{background-hue-3}}';
|
||||
|
||||
&.md-content-overflow .md-actions {
|
||||
border-top-color: '{{foreground-4}}';
|
||||
}
|
||||
}
|
||||
|
||||
+485
@@ -0,0 +1,485 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc module
|
||||
* @name material.components.dialog
|
||||
*/
|
||||
angular.module('material.components.dialog', [
|
||||
'material.core',
|
||||
'material.components.backdrop'
|
||||
])
|
||||
.directive('mdDialog', MdDialogDirective)
|
||||
.provider('$mdDialog', MdDialogProvider);
|
||||
|
||||
function MdDialogDirective($$rAF, $mdTheming) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: function(scope, element, attr) {
|
||||
$mdTheming(element);
|
||||
$$rAF(function() {
|
||||
var content = element[0].querySelector('md-content');
|
||||
if (content && content.scrollHeight > content.clientHeight) {
|
||||
element.addClass('md-content-overflow');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $mdDialog
|
||||
* @module material.components.dialog
|
||||
*
|
||||
* @description
|
||||
* `$mdDialog` opens a dialog over the app and provides a simple promise API.
|
||||
*
|
||||
* ### Restrictions
|
||||
*
|
||||
* - The dialog is always given an isolate scope.
|
||||
* - The dialog's template must have an outer `<md-dialog>` element.
|
||||
* Inside, use an `<md-content>` element for the dialog's content, and use
|
||||
* an element with class `md-actions` for the dialog's actions.
|
||||
*
|
||||
* @usage
|
||||
* ##### HTML
|
||||
*
|
||||
* <hljs lang="html">
|
||||
* <div ng-app="demoApp" ng-controller="EmployeeController">
|
||||
* <md-button ng-click="showAlert()" class="md-raised md-warn">
|
||||
* Employee Alert!
|
||||
* </md-button>
|
||||
* <md-button ng-click="closeAlert()" ng-disabled="!hasAlert()" class="md-raised">
|
||||
* Close Alert
|
||||
* </md-button>
|
||||
* <md-button ng-click="showGreeting($event)" class="md-raised md-primary" >
|
||||
* Greet Employee
|
||||
* </md-button>
|
||||
* </div>
|
||||
* </hljs>
|
||||
*
|
||||
* ##### JavaScript
|
||||
*
|
||||
* <hljs lang="js">
|
||||
* (function(angular, undefined){
|
||||
* "use strict";
|
||||
*
|
||||
* angular
|
||||
* .module('demoApp', ['ngMaterial'])
|
||||
* .controller('EmployeeController', EmployeeEditor)
|
||||
* .controller('GreetingController', GreetingController);
|
||||
*
|
||||
* // Fictitious Employee Editor to show how to use simple and complex dialogs.
|
||||
*
|
||||
* function EmployeeEditor($scope, $mdDialog) {
|
||||
* var alert;
|
||||
*
|
||||
* $scope.showAlert = showAlert;
|
||||
* $scope.closeAlert = closeAlert;
|
||||
* $scope.showGreeting = showCustomGreeting;
|
||||
*
|
||||
* $scope.hasAlert = function() { return !!alert };
|
||||
* $scope.userName = $scope.userName || 'Bobby';
|
||||
*
|
||||
* // Dialog #1 - Show simple alert dialog and cache
|
||||
* // reference to dialog instance
|
||||
*
|
||||
* function showAlert() {
|
||||
* alert = $mdDialog.alert()
|
||||
* .title('Attention, ' + $scope.userName)
|
||||
* .content('This is an example of how easy dialogs can be!')
|
||||
* .ok('Close');
|
||||
*
|
||||
* $mdDialog
|
||||
* .show( alert )
|
||||
* .finally(function() {
|
||||
* alert = undefined;
|
||||
* });
|
||||
* }
|
||||
*
|
||||
* // Close the specified dialog instance and resolve with 'finished' flag
|
||||
* // Normally this is not needed, just use '$mdDialog.hide()' to close
|
||||
* // the most recent dialog popup.
|
||||
*
|
||||
* function closeAlert() {
|
||||
* $mdDialog.hide( alert, "finished" );
|
||||
* alert = undefined;
|
||||
* }
|
||||
*
|
||||
* // Dialog #2 - Demonstrate more complex dialogs construction and popup.
|
||||
*
|
||||
* function showCustomGreeting($event) {
|
||||
* $mdDialog.show({
|
||||
* targetEvent: $event,
|
||||
* template:
|
||||
* '<md-dialog>' +
|
||||
*
|
||||
* ' <md-content>Hello {{ employee }}!</md-content>' +
|
||||
*
|
||||
* ' <div class="md-actions">' +
|
||||
* ' <md-button ng-click="closeDialog()">' +
|
||||
* ' Close Greeting' +
|
||||
*
|
||||
* ' </md-button>' +
|
||||
* ' </div>' +
|
||||
* '</md-dialog>',
|
||||
* controller: 'GreetingController',
|
||||
* onComplete: afterShowAnimation,
|
||||
* locals: { employee: $scope.userName }
|
||||
* });
|
||||
*
|
||||
* // When the 'enter' animation finishes...
|
||||
*
|
||||
* function afterShowAnimation(scope, element, options) {
|
||||
* // post-show code here: DOM element focus, etc.
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Greeting controller used with the more complex 'showCustomGreeting()' custom dialog
|
||||
*
|
||||
* function GreetingController($scope, $mdDialog, employee) {
|
||||
* // Assigned from construction <code>locals</code> options...
|
||||
* $scope.employee = employee;
|
||||
*
|
||||
* $scope.closeDialog = function() {
|
||||
* // Easily hides most recent dialog shown...
|
||||
* // no specific instance reference is needed.
|
||||
* $mdDialog.hide();
|
||||
* };
|
||||
* }
|
||||
*
|
||||
* })(angular);
|
||||
* </hljs>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $mdDialog#alert
|
||||
*
|
||||
* @description
|
||||
* Builds a preconfigured dialog with the specified message.
|
||||
*
|
||||
* @returns {obj} an `$mdDialogPreset` with the chainable configuration methods:
|
||||
*
|
||||
* - $mdDialogPreset#title(string) - sets title to string
|
||||
* - $mdDialogPreset#content(string) - sets content / message to string
|
||||
* - $mdDialogPreset#ok(string) - sets okay button text to string
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $mdDialog#confirm
|
||||
*
|
||||
* @description
|
||||
* Builds a preconfigured dialog with the specified message. You can call show and the promise returned
|
||||
* will be resolved only if the user clicks the confirm action on the dialog.
|
||||
*
|
||||
* @returns {obj} an `$mdDialogPreset` with the chainable configuration methods:
|
||||
*
|
||||
* Additionally, it supports the following methods:
|
||||
*
|
||||
* - $mdDialogPreset#title(string) - sets title to string
|
||||
* - $mdDialogPreset#content(string) - sets content / message to string
|
||||
* - $mdDialogPreset#ok(string) - sets okay button text to string
|
||||
* - $mdDialogPreset#cancel(string) - sets cancel button text to string
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $mdDialog#show
|
||||
*
|
||||
* @description
|
||||
* Show a dialog with the specified options.
|
||||
*
|
||||
* @param {object} optionsOrPreset Either provide an `$mdDialogPreset` returned from `alert()`,
|
||||
* `confirm()` or an options object with the following properties:
|
||||
* - `templateUrl` - `{string=}`: The url of a template that will be used as the content
|
||||
* of the dialog.
|
||||
* - `template` - `{string=}`: Same as templateUrl, except this is an actual template string.
|
||||
* - `targetEvent` - `{DOMClickEvent=}`: A click's event object. When passed in as an option,
|
||||
* the location of the click will be used as the starting point for the opening animation
|
||||
* of the the dialog.
|
||||
* - `disableParentScroll` - `{boolean=}`: Whether to disable scrolling while the dialog is open.
|
||||
* Default true.
|
||||
* - `hasBackdrop` - `{boolean=}`: Whether there should be an opaque backdrop behind the dialog.
|
||||
* Default true.
|
||||
* - `clickOutsideToClose` - `{boolean=}`: Whether the user can click outside the dialog to
|
||||
* close it. Default true.
|
||||
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to close the dialog.
|
||||
* Default true.
|
||||
* - `controller` - `{string=}`: The controller to associate with the dialog. The controller
|
||||
* will be injected with the local `$hideDialog`, which is a function used to hide the dialog.
|
||||
* - `locals` - `{object=}`: An object containing key/value pairs. The keys will be used as names
|
||||
* of values to inject into the controller. For example, `locals: {three: 3}` would inject
|
||||
* `three` into the controller, with the value 3. If `bindToController` is true, they will be
|
||||
* copied to the controller instead.
|
||||
* - `bindToController` - `bool`: bind the locals to the controller, instead of passing them in
|
||||
* - `resolve` - `{object=}`: Similar to locals, except it takes promises as values, and the
|
||||
* dialog will not open until all of the promises resolve.
|
||||
* - `controllerAs` - `{string=}`: An alias to assign the controller to on the scope.
|
||||
* - `parent` - `{element=}`: The element to append the dialog to. Defaults to appending
|
||||
* to the root element of the application.
|
||||
* - `onComplete` `{function=}`: Callback function used to announce when the show() action is
|
||||
* finished.
|
||||
*
|
||||
* @returns {promise} A promise that can be resolved with `$mdDialog.hide()` or
|
||||
* rejected with `mdDialog.cancel()`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $mdDialog#hide
|
||||
*
|
||||
* @description
|
||||
* Hide an existing dialog and resolve the promise returned from `$mdDialog.show()`.
|
||||
*
|
||||
* @param {*=} response An argument for the resolved promise.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $mdDialog#cancel
|
||||
*
|
||||
* @description
|
||||
* Hide an existing dialog and reject the promise returned from `$mdDialog.show()`.
|
||||
*
|
||||
* @param {*=} response An argument for the rejected promise.
|
||||
*/
|
||||
|
||||
function MdDialogProvider($$interimElementProvider) {
|
||||
|
||||
var alertDialogMethods = ['title', 'content', 'ariaLabel', 'ok'];
|
||||
|
||||
return $$interimElementProvider('$mdDialog')
|
||||
.setDefaults({
|
||||
methods: ['disableParentScroll', 'hasBackdrop', 'clickOutsideToClose', 'escapeToClose', 'targetEvent'],
|
||||
options: dialogDefaultOptions
|
||||
})
|
||||
.addPreset('alert', {
|
||||
methods: ['title', 'content', 'ariaLabel', 'ok'],
|
||||
options: advancedDialogOptions
|
||||
})
|
||||
.addPreset('confirm', {
|
||||
methods: ['title', 'content', 'ariaLabel', 'ok', 'cancel'],
|
||||
options: advancedDialogOptions
|
||||
});
|
||||
|
||||
/* @ngInject */
|
||||
function advancedDialogOptions($mdDialog) {
|
||||
return {
|
||||
template: [
|
||||
'<md-dialog aria-label="{{ dialog.ariaLabel }}">',
|
||||
'<md-content>',
|
||||
'<h2>{{ dialog.title }}</h2>',
|
||||
'<p>{{ dialog.content }}</p>',
|
||||
'</md-content>',
|
||||
'<div class="md-actions">',
|
||||
'<md-button ng-if="dialog.$type == \'confirm\'" ng-click="dialog.abort()">',
|
||||
'{{ dialog.cancel }}',
|
||||
'</md-button>',
|
||||
'<md-button ng-click="dialog.hide()" class="md-primary">',
|
||||
'{{ dialog.ok }}',
|
||||
'</md-button>',
|
||||
'</div>',
|
||||
'</md-dialog>'
|
||||
].join(''),
|
||||
controller: function mdDialogCtrl() {
|
||||
this.hide = function() {
|
||||
$mdDialog.hide(true);
|
||||
};
|
||||
this.abort = function() {
|
||||
$mdDialog.cancel();
|
||||
};
|
||||
},
|
||||
controllerAs: 'dialog',
|
||||
bindToController: true
|
||||
};
|
||||
}
|
||||
|
||||
/* @ngInject */
|
||||
function dialogDefaultOptions($timeout, $rootElement, $compile, $animate, $mdAria, $document,
|
||||
$mdUtil, $mdConstant, $mdTheming, $$rAF, $q, $mdDialog) {
|
||||
return {
|
||||
hasBackdrop: true,
|
||||
isolateScope: true,
|
||||
onShow: onShow,
|
||||
onRemove: onRemove,
|
||||
clickOutsideToClose: true,
|
||||
escapeToClose: true,
|
||||
targetEvent: null,
|
||||
disableParentScroll: true,
|
||||
transformTemplate: function(template) {
|
||||
return '<div class="md-dialog-container">' + template + '</div>';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// On show method for dialogs
|
||||
function onShow(scope, element, options) {
|
||||
// Incase the user provides a raw dom element, always wrap it in jqLite
|
||||
options.parent = angular.element(options.parent);
|
||||
|
||||
options.popInTarget = angular.element((options.targetEvent || {}).target);
|
||||
var closeButton = findCloseButton();
|
||||
|
||||
configureAria(element.find('md-dialog'));
|
||||
|
||||
if (options.hasBackdrop) {
|
||||
options.backdrop = angular.element('<md-backdrop class="md-dialog-backdrop md-opaque">');
|
||||
$mdTheming.inherit(options.backdrop, options.parent);
|
||||
$animate.enter(options.backdrop, options.parent);
|
||||
}
|
||||
|
||||
if (options.disableParentScroll) {
|
||||
options.oldOverflowStyle = options.parent.css('overflow');
|
||||
options.parent.css('overflow', 'hidden');
|
||||
}
|
||||
|
||||
return dialogPopIn(
|
||||
element,
|
||||
options.parent,
|
||||
options.popInTarget && options.popInTarget.length && options.popInTarget
|
||||
)
|
||||
.then(function() {
|
||||
if (options.escapeToClose) {
|
||||
options.rootElementKeyupCallback = function(e) {
|
||||
if (e.keyCode === $mdConstant.KEY_CODE.ESCAPE) {
|
||||
$timeout($mdDialog.cancel);
|
||||
}
|
||||
};
|
||||
$rootElement.on('keyup', options.rootElementKeyupCallback);
|
||||
}
|
||||
|
||||
if (options.clickOutsideToClose) {
|
||||
options.dialogClickOutsideCallback = function(e) {
|
||||
// Only close if we click the flex container outside the backdrop
|
||||
if (e.target === element[0]) {
|
||||
$timeout($mdDialog.cancel);
|
||||
}
|
||||
};
|
||||
element.on('click', options.dialogClickOutsideCallback);
|
||||
}
|
||||
closeButton.focus();
|
||||
});
|
||||
|
||||
|
||||
function findCloseButton() {
|
||||
//If no element with class dialog-close, try to find the last
|
||||
//button child in md-actions and assume it is a close button
|
||||
var closeButton = element[0].querySelector('.dialog-close');
|
||||
if (!closeButton) {
|
||||
var actionButtons = element[0].querySelectorAll('.md-actions button');
|
||||
closeButton = actionButtons[ actionButtons.length - 1 ];
|
||||
}
|
||||
return angular.element(closeButton);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// On remove function for all dialogs
|
||||
function onRemove(scope, element, options) {
|
||||
|
||||
if (options.backdrop) {
|
||||
$animate.leave(options.backdrop);
|
||||
}
|
||||
if (options.disableParentScroll) {
|
||||
options.parent.css('overflow', options.oldOverflowStyle);
|
||||
$document[0].removeEventListener('scroll', options.captureScroll, true);
|
||||
}
|
||||
if (options.escapeToClose) {
|
||||
$rootElement.off('keyup', options.rootElementKeyupCallback);
|
||||
}
|
||||
if (options.clickOutsideToClose) {
|
||||
element.off('click', options.dialogClickOutsideCallback);
|
||||
}
|
||||
return dialogPopOut(
|
||||
element,
|
||||
options.parent,
|
||||
options.popInTarget && options.popInTarget.length && options.popInTarget
|
||||
).then(function() {
|
||||
options.scope.$destroy();
|
||||
element.remove();
|
||||
options.popInTarget && options.popInTarget.focus();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject ARIA-specific attributes appropriate for Dialogs
|
||||
*/
|
||||
function configureAria(element) {
|
||||
element.attr({
|
||||
'role': 'dialog'
|
||||
});
|
||||
|
||||
var dialogContent = element.find('md-content');
|
||||
if (dialogContent.length === 0){
|
||||
dialogContent = element;
|
||||
}
|
||||
$mdAria.expectAsync(element, 'aria-label', function() {
|
||||
var words = dialogContent.text().split(/\s+/);
|
||||
if (words.length > 3) words = words.slice(0,3).concat('...');
|
||||
return words.join(' ');
|
||||
});
|
||||
}
|
||||
|
||||
function dialogPopIn(container, parentElement, clickElement) {
|
||||
var dialogEl = container.find('md-dialog');
|
||||
|
||||
parentElement.append(container);
|
||||
transformToClickElement(dialogEl, clickElement);
|
||||
|
||||
$$rAF(function() {
|
||||
dialogEl.addClass('transition-in')
|
||||
.css($mdConstant.CSS.TRANSFORM, '');
|
||||
});
|
||||
|
||||
return dialogTransitionEnd(dialogEl);
|
||||
}
|
||||
|
||||
function dialogPopOut(container, parentElement, clickElement) {
|
||||
var dialogEl = container.find('md-dialog');
|
||||
|
||||
dialogEl.addClass('transition-out').removeClass('transition-in');
|
||||
transformToClickElement(dialogEl, clickElement);
|
||||
|
||||
return dialogTransitionEnd(dialogEl);
|
||||
}
|
||||
|
||||
function transformToClickElement(dialogEl, clickElement) {
|
||||
if (clickElement) {
|
||||
var clickRect = clickElement[0].getBoundingClientRect();
|
||||
var dialogRect = dialogEl[0].getBoundingClientRect();
|
||||
|
||||
var scaleX = Math.min(0.5, clickRect.width / dialogRect.width);
|
||||
var scaleY = Math.min(0.5, clickRect.height / dialogRect.height);
|
||||
|
||||
dialogEl.css($mdConstant.CSS.TRANSFORM, 'translate3d(' +
|
||||
(-dialogRect.left + clickRect.left + clickRect.width/2 - dialogRect.width/2) + 'px,' +
|
||||
(-dialogRect.top + clickRect.top + clickRect.height/2 - dialogRect.height/2) + 'px,' +
|
||||
'0) scale(' + scaleX + ',' + scaleY + ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function dialogTransitionEnd(dialogEl) {
|
||||
var deferred = $q.defer();
|
||||
dialogEl.on($mdConstant.CSS.TRANSITIONEND, finished);
|
||||
function finished(ev) {
|
||||
//Make sure this transitionend didn't bubble up from a child
|
||||
if (ev.target === dialogEl[0]) {
|
||||
dialogEl.off($mdConstant.CSS.TRANSITIONEND, finished);
|
||||
deferred.resolve();
|
||||
}
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
.md-dialog-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: $z-index-dialog;
|
||||
}
|
||||
|
||||
md-dialog {
|
||||
&.transition-in {
|
||||
opacity: 1;
|
||||
transition: $swift-ease-out;
|
||||
transform: translate3d(0,0,0) scale(1.0);
|
||||
}
|
||||
&.transition-out {
|
||||
transition: $swift-ease-out;
|
||||
transform: translate3d(0,100%,0) scale(0.2);
|
||||
}
|
||||
|
||||
opacity: 0;
|
||||
min-width: 240px;
|
||||
max-width: 80%;
|
||||
max-height: 80%;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
overflow: hidden; // stop content from leaking out of dialog parent
|
||||
|
||||
box-shadow: $whiteframe-shadow-z5;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
md-content {
|
||||
order: 1;
|
||||
padding: 24px;
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
*:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.md-actions {
|
||||
display: flex;
|
||||
order: 2;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 16px 16px;
|
||||
min-height: $baseline-grid * 5;
|
||||
|
||||
> * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
&.md-content-overflow .md-actions {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
}
|
||||
+479
@@ -0,0 +1,479 @@
|
||||
describe('$mdDialog', function() {
|
||||
|
||||
beforeEach(TestUtil.mockRaf);
|
||||
beforeEach(module('material.components.dialog', 'ngAnimateMock'));
|
||||
|
||||
beforeEach(inject(function spyOnMdEffects($$q, $animate) {
|
||||
spyOn($animate, 'leave').andCallFake(function(element) {
|
||||
element.remove();
|
||||
return $$q.when();
|
||||
});
|
||||
spyOn($animate, 'enter').andCallFake(function(element, parent) {
|
||||
parent.append(element);
|
||||
return $$q.when();
|
||||
});
|
||||
}));
|
||||
|
||||
describe('#alert()', function() {
|
||||
hasConfigurationMethods('alert', [
|
||||
'title', 'content', 'ariaLabel',
|
||||
'ok', 'targetEvent'
|
||||
]);
|
||||
|
||||
it('shows a basic alert dialog', inject(function($animate, $rootScope, $mdDialog, $mdConstant) {
|
||||
var parent = angular.element('<div>');
|
||||
var resolved = false;
|
||||
$mdDialog.show(
|
||||
$mdDialog.alert({
|
||||
parent: parent
|
||||
})
|
||||
.title('Title')
|
||||
.content('Hello world')
|
||||
.ok('Next')
|
||||
).then(function() {
|
||||
resolved = true;
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
container.triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
var title = angular.element(parent[0].querySelector('h2'));
|
||||
expect(title.text()).toBe('Title');
|
||||
var content = parent.find('p');
|
||||
expect(content.text()).toBe('Hello world');
|
||||
var buttons = parent.find('md-button');
|
||||
expect(buttons.length).toBe(1);
|
||||
expect(buttons.eq(0).text()).toBe('Next');
|
||||
buttons.eq(0).triggerHandler('click');
|
||||
$rootScope.$apply();
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
expect(parent.find('h2').length).toBe(0);
|
||||
expect(resolved).toBe(true);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('#confirm()', function() {
|
||||
hasConfigurationMethods('confirm', [
|
||||
'title', 'content', 'ariaLabel',
|
||||
'ok', 'cancel', 'targetEvent'
|
||||
]);
|
||||
|
||||
it('shows a basic confirm dialog', inject(function($rootScope, $mdDialog, $animate, $mdConstant) {
|
||||
var parent = angular.element('<div>');
|
||||
var rejected = false;
|
||||
$mdDialog.show(
|
||||
$mdDialog.confirm({
|
||||
parent: parent
|
||||
})
|
||||
.title('Title')
|
||||
.content('Hello world')
|
||||
.ok('Next')
|
||||
.cancel('Forget it')
|
||||
).catch(function() {
|
||||
rejected = true;
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
container.triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
var title = parent.find('h2');
|
||||
expect(title.text()).toBe('Title');
|
||||
var content = parent.find('p');
|
||||
expect(content.text()).toBe('Hello world');
|
||||
var buttons = parent.find('md-button');
|
||||
expect(buttons.length).toBe(2);
|
||||
expect(buttons.eq(0).text()).toBe('Next');
|
||||
expect(buttons.eq(1).text()).toBe('Forget it');
|
||||
buttons.eq(1).triggerHandler('click');
|
||||
$rootScope.$digest();
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
expect(parent.find('h2').length).toBe(0);
|
||||
expect(rejected).toBe(true);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('#build()', function() {
|
||||
it('should support onComplete callbacks within `show()`', inject(function($mdDialog, $rootScope, $timeout, $mdConstant) {
|
||||
|
||||
var template = '<md-dialog>Hello</md-dialog>';
|
||||
var parent = angular.element('<div>');
|
||||
var ready = false;
|
||||
|
||||
$mdDialog.show({
|
||||
template: template,
|
||||
parent: parent,
|
||||
onComplete: function(scope, element, options) {
|
||||
expect( arguments.length ).toEqual( 3 );
|
||||
ready = true;
|
||||
}
|
||||
});
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(ready).toBe( false );
|
||||
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
expect(container.length).toBe(1);
|
||||
expect(ready).toBe( true );
|
||||
}));
|
||||
|
||||
it('should append dialog with container', inject(function($mdDialog, $rootScope) {
|
||||
|
||||
var template = '<md-dialog>Hello</md-dialog>';
|
||||
var parent = angular.element('<div>');
|
||||
|
||||
$mdDialog.show({
|
||||
template: template,
|
||||
parent: parent
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
|
||||
var container = parent[0].querySelectorAll('.md-dialog-container');
|
||||
expect(container.length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should escapeToClose == true', inject(function($mdDialog, $rootScope, $rootElement, $timeout, $animate, $mdConstant) {
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog>',
|
||||
parent: parent,
|
||||
escapeToClose: true
|
||||
});
|
||||
$rootScope.$apply();
|
||||
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(parent.find('md-dialog').length).toBe(1);
|
||||
|
||||
$rootElement.triggerHandler({type: 'keyup',
|
||||
keyCode: $mdConstant.KEY_CODE.ESCAPE
|
||||
});
|
||||
|
||||
$timeout.flush();
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
expect(parent.find('md-dialog').length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should escapeToClose == false', inject(function($mdDialog, $rootScope, $rootElement, $timeout, $animate, $mdConstant) {
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog>',
|
||||
parent: parent,
|
||||
escapeToClose: false
|
||||
});
|
||||
$rootScope.$apply();
|
||||
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
container.triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(parent.find('md-dialog').length).toBe(1);
|
||||
|
||||
$rootElement.triggerHandler({ type: 'keyup', keyCode: $mdConstant.KEY_CODE.ESCAPE });
|
||||
|
||||
$timeout.flush();
|
||||
$animate.triggerCallbacks();
|
||||
expect(parent.find('md-dialog').length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should clickOutsideToClose == true', inject(function($mdDialog, $rootScope, $timeout, $animate, $mdConstant) {
|
||||
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog>',
|
||||
parent: parent,
|
||||
clickOutsideToClose: true
|
||||
});
|
||||
$rootScope.$apply();
|
||||
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(parent.find('md-dialog').length).toBe(1);
|
||||
|
||||
container.triggerHandler({
|
||||
type: 'click',
|
||||
target: container[0]
|
||||
});
|
||||
$timeout.flush();
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(parent.find('md-dialog').length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should clickOutsideToClose == false', inject(function($mdDialog, $rootScope, $timeout, $animate) {
|
||||
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog>',
|
||||
parent: parent,
|
||||
clickOutsideToClose: false
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
expect(parent.find('md-dialog').length).toBe(1);
|
||||
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
|
||||
container.triggerHandler('click');
|
||||
$timeout.flush();
|
||||
$animate.triggerCallbacks();
|
||||
|
||||
expect(parent[0].querySelectorAll('md-dialog').length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should disableParentScroll == true', inject(function($mdDialog, $animate, $rootScope) {
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog>',
|
||||
parent: parent,
|
||||
disableParentScroll: true
|
||||
});
|
||||
$rootScope.$apply();
|
||||
$animate.triggerCallbacks();
|
||||
$rootScope.$apply();
|
||||
expect(parent.css('overflow')).toBe('hidden');
|
||||
}));
|
||||
|
||||
it('should hasBackdrop == true', inject(function($mdDialog, $animate, $rootScope) {
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog>',
|
||||
parent: parent,
|
||||
hasBackdrop: true
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
$animate.triggerCallbacks();
|
||||
$rootScope.$apply();
|
||||
expect(parent.find('md-dialog').length).toBe(1);
|
||||
expect(parent.find('md-backdrop').length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should hasBackdrop == false', inject(function($mdDialog, $rootScope) {
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog>',
|
||||
parent: parent,
|
||||
hasBackdrop: false
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
expect(parent[0].querySelectorAll('md-dialog').length).toBe(1);
|
||||
expect(parent[0].querySelectorAll('md-backdrop').length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should focus `md-button.dialog-close` on open', inject(function($mdDialog, $rootScope, $document, $timeout, $mdConstant) {
|
||||
TestUtil.mockElementFocus(this);
|
||||
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template:
|
||||
'<md-dialog>' +
|
||||
'<div class="md-actions">' +
|
||||
'<button class="dialog-close">Close</button>' +
|
||||
'</div>' +
|
||||
'</md-dialog>',
|
||||
parent: parent
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
$timeout.flush();
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
container.triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
|
||||
expect($document.activeElement).toBe(parent[0].querySelector('.dialog-close'));
|
||||
}));
|
||||
|
||||
it('should focus the last `md-button` in md-actions open if no `.dialog-close`', inject(function($mdDialog, $rootScope, $document, $timeout, $mdConstant) {
|
||||
TestUtil.mockElementFocus(this);
|
||||
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template:
|
||||
'<md-dialog>' +
|
||||
'<div class="md-actions">' +
|
||||
'<button id="a">A</md-button>' +
|
||||
'<button id="focus-target">B</md-button>' +
|
||||
'</div>' +
|
||||
'</md-dialog>',
|
||||
parent: parent
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
$timeout.flush();
|
||||
|
||||
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
container.triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
expect($document.activeElement).toBe(parent[0].querySelector('#focus-target'));
|
||||
}));
|
||||
|
||||
it('should only allow one open at a time', inject(function($mdDialog, $rootScope) {
|
||||
var parent = angular.element('<div>');
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog class="one">',
|
||||
parent: parent
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
expect(parent[0].querySelectorAll('md-dialog.one').length).toBe(1);
|
||||
expect(parent[0].querySelectorAll('md-dialog.two').length).toBe(0);
|
||||
|
||||
$mdDialog.show({
|
||||
template: '<md-dialog class="two">',
|
||||
parent: parent
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
parent.find('md-dialog').triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
expect(parent[0].querySelectorAll('md-dialog.one').length).toBe(0);
|
||||
expect(parent[0].querySelectorAll('md-dialog.two').length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should have the dialog role', inject(function($mdDialog, $rootScope) {
|
||||
var template = '<md-dialog>Hello</md-dialog>';
|
||||
var parent = angular.element('<div>');
|
||||
|
||||
$mdDialog.show({
|
||||
template: template,
|
||||
parent: parent
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
|
||||
var dialog = angular.element(parent[0].querySelectorAll('md-dialog'));
|
||||
expect(dialog.attr('role')).toBe('dialog');
|
||||
}));
|
||||
|
||||
it('should create an ARIA label if one is missing', inject(function($mdDialog, $rootScope) {
|
||||
var template = '<md-dialog>Hello</md-dialog>';
|
||||
var parent = angular.element('<div>');
|
||||
|
||||
$mdDialog.show({
|
||||
template: template,
|
||||
parent: parent
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
angular.element(parent[0].querySelector('.md-dialog-container')).triggerHandler('transitionend');
|
||||
$rootScope.$apply();
|
||||
|
||||
var dialog = angular.element(parent[0].querySelector('md-dialog'));
|
||||
expect(dialog.attr('aria-label')).toEqual(dialog.text());
|
||||
}));
|
||||
|
||||
it('should not modify an existing ARIA label', inject(function($mdDialog, $rootScope){
|
||||
var template = '<md-dialog aria-label="Some Other Thing">Hello</md-dialog>';
|
||||
var parent = angular.element('<div>');
|
||||
|
||||
$mdDialog.show({
|
||||
template: template,
|
||||
parent: parent
|
||||
});
|
||||
|
||||
$rootScope.$apply();
|
||||
|
||||
var dialog = angular.element(parent[0].querySelector('md-dialog'));
|
||||
expect(dialog.attr('aria-label')).not.toEqual(dialog.text());
|
||||
expect(dialog.attr('aria-label')).toEqual('Some Other Thing');
|
||||
}));
|
||||
});
|
||||
|
||||
function hasConfigurationMethods(preset, methods) {
|
||||
angular.forEach(methods, function(method) {
|
||||
return it('supports config method #' + method, inject(function($mdDialog) {
|
||||
var dialog = $mdDialog[preset]();
|
||||
expect(typeof dialog[method]).toBe('function');
|
||||
expect(dialog[method]()).toEqual(dialog);
|
||||
}));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('$mdDialog with custom interpolation symbols', function() {
|
||||
beforeEach(TestUtil.mockRaf);
|
||||
beforeEach(module('material.components.dialog', 'ngAnimateMock'));
|
||||
|
||||
beforeEach(module(function($interpolateProvider) {
|
||||
$interpolateProvider.startSymbol('[[').endSymbol(']]');
|
||||
}));
|
||||
|
||||
it('displays #alert() correctly', inject(function($mdDialog, $rootScope) {
|
||||
var parent = angular.element('<div>');
|
||||
var dialog = $mdDialog.
|
||||
alert({parent: parent}).
|
||||
ariaLabel('test alert').
|
||||
title('Title').
|
||||
content('Hello, world !').
|
||||
ok('OK');
|
||||
|
||||
$mdDialog.show(dialog);
|
||||
$rootScope.$digest();
|
||||
|
||||
var mdContainer = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
var mdDialog = mdContainer.find('md-dialog');
|
||||
var mdContent = mdDialog.find('md-content');
|
||||
var title = mdContent.find('h2');
|
||||
var content = mdContent.find('p');
|
||||
var mdActions = angular.element(mdDialog[0].querySelector('.md-actions'));
|
||||
var buttons = mdActions.find('md-button');
|
||||
|
||||
expect(mdDialog.attr('aria-label')).toBe('test alert');
|
||||
expect(title.text()).toBe('Title');
|
||||
expect(content.text()).toBe('Hello, world !');
|
||||
expect(buttons.eq(0).text()).toBe('OK');
|
||||
}));
|
||||
|
||||
it('displays #confirm() correctly', inject(function($mdDialog, $rootScope) {
|
||||
var parent = angular.element('<div>');
|
||||
var dialog = $mdDialog.
|
||||
confirm({parent: parent}).
|
||||
ariaLabel('test alert').
|
||||
title('Title').
|
||||
content('Hello, world !').
|
||||
cancel('CANCEL').
|
||||
ok('OK');
|
||||
|
||||
$mdDialog.show(dialog);
|
||||
$rootScope.$digest();
|
||||
|
||||
var mdContainer = angular.element(parent[0].querySelector('.md-dialog-container'));
|
||||
var mdDialog = mdContainer.find('md-dialog');
|
||||
var mdContent = mdDialog.find('md-content');
|
||||
var title = mdContent.find('h2');
|
||||
var content = mdContent.find('p');
|
||||
var mdActions = angular.element(mdDialog[0].querySelector('.md-actions'));
|
||||
var buttons = mdActions.find('md-button');
|
||||
|
||||
expect(mdDialog.attr('aria-label')).toBe('test alert');
|
||||
expect(title.text()).toBe('Title');
|
||||
expect(content.text()).toBe('Hello, world !');
|
||||
expect(buttons.eq(0).text()).toBe('CANCEL');
|
||||
expect(buttons.eq(1).text()).toBe('OK');
|
||||
}));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user