MODULE-TYPO

- Sass set-up
- md-list
- md-theming (install)
This commit is contained in:
iRouge
2015-01-16 07:52:29 -05:00
parent ec1b4b9b0c
commit f1d2b8cb75
312 changed files with 26839 additions and 1309 deletions
@@ -0,0 +1,34 @@
<div ng-controller="AppCtrl" layout-fill layout="column" class="inset">
<p>Toast can be dismissed with a swipe, a timer, or a button.</p>
<div layout="row" layout-sm="column" layout-align="space-around">
<div style="width:50px"></div>
<md-button ng-click="showCustomToast()">
Show Custom
</md-button>
<md-button ng-click="showSimpleToast()">
Show Simple
</md-button>
<md-button class="md-raised" ng-click="showActionToast()">
Show With Action
</md-button>
<div style="width:50px"></div>
</div>
<div>
<br/>
<b>Toast Position: "{{getToastPosition()}}"</b>
<br/>
<md-checkbox ng-repeat="(name, isSelected) in toastPosition"
aria-label="{{name}}"
ng-model="toastPosition[name]">
{{name}}
</md-checkbox>
<md-button class="md-primary md-fab md-fab-bottom-right">
FAB
</md-button>
<md-button class="md-primary md-fab md-fab-top-right" md-theme="green">
FAB
</md-button>
</div>
</div>
@@ -0,0 +1,55 @@
angular.module('toastDemo1', ['ngMaterial'])
.controller('AppCtrl', function($scope, $mdToast, $animate) {
$scope.toastPosition = {
bottom: false,
top: true,
left: false,
right: true
};
$scope.getToastPosition = function() {
return Object.keys($scope.toastPosition)
.filter(function(pos) { return $scope.toastPosition[pos]; })
.join(' ');
};
$scope.showCustomToast = function() {
$mdToast.show({
controller: 'ToastCtrl',
templateUrl: 'toast-template.html',
hideDelay: 6000,
position: $scope.getToastPosition()
});
};
$scope.showSimpleToast = function() {
$mdToast.show(
$mdToast.simple()
.content('Simple Toast!')
.position($scope.getToastPosition())
.hideDelay(0)
);
};
$scope.showActionToast = function() {
var toast = $mdToast.simple()
.content('Action Toast!')
.action('OK')
.highlightAction(false)
.position($scope.getToastPosition());
$mdToast.show(toast).then(function() {
alert('You clicked \'OK\'.');
});
};
})
.controller('ToastCtrl', function($scope, $mdToast) {
$scope.closeToast = function() {
$mdToast.hide();
};
});
@@ -0,0 +1,6 @@
<md-toast>
<span flex>Custom toast!</span>
<md-button ng-click="closeToast()">
Close
</md-button>
</md-toast>
@@ -0,0 +1,18 @@
md-toast.md-THEME_NAME-theme {
background-color: '{{foreground-1}}';
color: '{{background-50}}';
.md-button {
color: '{{background-50}}';
}
.md-action {
color: '{{primary-A200}}';
&.md-accent {
color: '{{accent-A200}}';
}
&.md-warn {
color: '{{warn-A200}}';
}
}
}
@@ -0,0 +1,227 @@
(function() {
'use strict';
/**
* @ngdoc module
* @name material.components.toast
* @description
* Toast
*/
angular.module('material.components.toast', [
'material.core',
'material.components.swipe',
'material.components.button'
])
.directive('mdToast', MdToastDirective)
.provider('$mdToast', MdToastProvider);
function MdToastDirective() {
return {
restrict: 'E'
};
}
/**
* @ngdoc service
* @name $mdToast
* @module material.components.toast
*
* @description
* `$mdToast` is a service to build a toast nofication on any position
* on the screen with an optional duration, and provides a simple promise API.
*
*
* ### Restrictions on custom toasts
* - The toast's template must have an outer `<md-toast>` element.
* - For a toast action, use element with class `md-action`.
* - Add the class `md-capsule` for curved corners.
*
* @usage
* <hljs lang="html">
* <div ng-controller="MyController">
* <md-button ng-click="openToast()">
* Open a Toast!
* </md-button>
* </div>
* </hljs>
*
* <hljs lang="js">
* var app = angular.module('app', ['ngMaterial']);
* app.controller('MyController', function($scope, $mdToast) {
* $scope.openToast = function($event) {
* $mdToast.show($mdToast.simple().content('Hello!'));
* // Could also do $mdtoast.showSimple('Hello');
* };
* });
* </hljs>
*/
/**
* @ngdoc method
* @name $mdToast#showSimple
*
* @description
* Convenience method which builds and shows a simple toast.
*
* @returns {promise} A promise that can be resolved with `$mdToast.hide()` or
* rejected with `$mdToast.cancel()`.
*
*/
/**
* @ngdoc method
* @name $mdToast#simple
*
* @description
* Builds a preconfigured toast.
*
* @returns {obj} a `$mdToastPreset` with the chainable configuration methods:
*
* - $mdToastPreset#content(string) - sets toast content to string
* - $mdToastPreset#action(string) - adds an action button, which resolves the promise returned from `show()` if clicked.
* - $mdToastPreset#highlightAction(boolean) - sets action button to be highlighted
* - $mdToastPreset#capsule(boolean) - adds 'md-capsule' class to the toast (curved corners)
*/
/**
* @ngdoc method
* @name $mdToast#build
*
* @description
* Creates a custom `$mdToastPreset` that you can configure.
*
* @returns {obj} a `$mdToastPreset` with the chainable configuration methods for shows' options (see below).
*/
/**
* @ngdoc method
* @name $mdToast#show
*
* @description Shows the toast.
*
* @param {object} optionsOrPreset Either provide an `$mdToastPreset` returned from `simple()`
* and `build()`, or an options object with the following properties:
*
* - `templateUrl` - `{string=}`: The url of an html template file that will
* be used as the content of the toast. Restrictions: the template must
* have an outer `md-toast` element.
* - `template` - `{string=}`: Same as templateUrl, except this is an actual
* template string.
* - `hideDelay` - `{number=}`: How many milliseconds the toast should stay
* active before automatically closing. Set to 0 or false to have the toast stay open until
* closed manually. Default: 3000.
* - `position` - `{string=}`: Where to place the toast. Available: any combination
* of 'bottom', 'left', 'top', 'right', 'fit'. Default: 'bottom left'.
* - `controller` - `{string=}`: The controller to associate with this toast.
* The controller will be injected the local `$hideToast`, which is a function
* used to hide the toast.
* - `locals` - `{string=}`: 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
* of 3.
* - `resolve` - `{object=}`: Similar to locals, except it takes promises as values
* and the toast will not open until the promises resolve.
* - `controllerAs` - `{string=}`: An alias to assign the controller to on the scope.
* - `parent` - `{element=}`: The element to append the toast to. Defaults to appending
* to the root element of the application.
*
* @returns {promise} A promise that can be resolved with `$mdToast.hide()` or
* rejected with `$mdToast.cancel()`.
*/
/**
* @ngdoc method
* @name $mdToast#hide
*
* @description
* Hide an existing toast and resolve the promise returned from `$mdToast.show()`.
*
* @param {*=} response An argument for the resolved promise.
*
*/
/**
* @ngdoc method
* @name $mdToast#cancel
*
* @description
* Hide the existing toast and reject the promise returned from
* `$mdToast.show()`.
*
* @param {*=} response An argument for the rejected promise.
*
*/
function MdToastProvider($$interimElementProvider) {
return $$interimElementProvider('$mdToast')
.setDefaults({
methods: ['position', 'hideDelay', 'capsule'],
options: toastDefaultOptions
})
.addPreset('simple', {
argOption: 'content',
methods: ['content', 'action', 'highlightAction'],
options: /* @ngInject */ function($mdToast) {
return {
template: [
'<md-toast ng-class="{\'md-capsule\': toast.capsule}">',
'<span flex>{{ toast.content }}</span>',
'<md-button ng-if="toast.action" ng-click="toast.resolve()" ng-class="{\'md-action\': toast.highlightAction}">',
'{{ toast.action }}',
'</md-button>',
'</md-toast>'
].join(''),
controller: function mdToastCtrl() {
this.resolve = function() {
$mdToast.hide();
};
},
controllerAs: 'toast',
bindToController: true
};
}
});
/* @ngInject */
function toastDefaultOptions($timeout, $animate, $mdSwipe, $mdTheming, $mdToast) {
return {
onShow: onShow,
onRemove: onRemove,
position: 'bottom left',
themable: true,
hideDelay: 3000
};
function onShow(scope, element, options) {
// 'top left' -> 'md-top md-left'
element.addClass(options.position.split(' ').map(function(pos) {
return 'md-' + pos;
}).join(' '));
options.parent.addClass(toastOpenClass(options.position));
var configureSwipe = $mdSwipe(scope, 'swipeleft swiperight');
options.detachSwipe = configureSwipe(element, function(ev) {
//Add swipeleft/swiperight class to element so it can animate correctly
element.addClass('md-' + ev.type);
$timeout($mdToast.cancel);
});
return $animate.enter(element, options.parent);
}
function onRemove(scope, element, options) {
options.detachSwipe();
options.parent.removeClass(toastOpenClass(options.position));
return $animate.leave(element);
}
function toastOpenClass(position) {
return 'md-toast-open-' +
(position.indexOf('top') > -1 ? 'top' : 'bottom');
}
}
}
})();
@@ -0,0 +1,130 @@
// See height set globally, depended on by buttons
md-toast {
display: flex;
position:absolute;
box-sizing: border-box;
align-items: center;
min-height: 48px;
padding-left: 24px;
padding-right: 24px;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
border-radius: 2px;
font-size: 14px;
cursor: default;
max-width: 879px;
max-height: 40px;
height: $toast-height;
z-index: $z-index-toast;
&.md-capsule {
border-radius: 24px;
}
opacity: 1;
transform: translate3d(0,0,0) rotateZ(0deg);
transition: $swift-ease-out;
&.ng-leave-active {
transition: $swift-ease-in;
}
/* Transition differently when swiping */
&.md-swipeleft,
&.md-swiperight,
&.md-swipeup,
&.md-swipedown {
transition: $swift-ease-out;
}
&.ng-enter {
transform: translate3d(0, 100%, 0);
&.md-top {
transform: translate3d(0, -100%, 0);
}
opacity: 0;
&.ng-enter-active {
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
&.ng-leave.ng-leave-active {
opacity: 0;
transform: translate3d(0, 100%, 0);
&.md-top {
transform: translate3d(0, -100%, 0);
}
&.md-swipeleft {
transform: translate3d(-100%, 0%, 0);
}
&.md-swiperight {
transform: translate3d(100%, 0%, 0);
}
}
.md-action {
line-height: 19px;
padding-left: 24px;
cursor: pointer;
text-transform: uppercase;
float: right;
}
}
@media (max-width: $layout-breakpoint-sm) {
md-toast {
left: 0;
right: 0;
width: 100%;
max-width: 100%;
min-width: 0;
border-radius: 0;
bottom: 0;
&.md-top {
bottom: auto;
top: 0;
}
}
}
@media (min-width: $layout-breakpoint-sm) {
md-toast {
min-width: 288px;
&.md-bottom {
bottom: $toast-margin;
}
&.md-left {
left: $toast-margin;
}
&.md-right {
right: $toast-margin;
}
&.md-top {
top: $toast-margin;
}
/*
* When the toast doesn't take up the whole screen,
* make it rotate when the user swipes it away
*/
&.ng-leave.ng-leave-active {
&.md-swipeleft {
transform: translate3d(-100%, 25%, 0) rotateZ(-15deg);
}
&.md-swiperight {
transform: translate3d(100%, 25%, 0) rotateZ(15deg);
}
&.md-top {
&.md-swipeleft {
transform: translate3d(-100%, 0, 0) rotateZ(-15deg);
}
&.md-swiperight {
transform: translate3d(100%, 0, 0) rotateZ(15deg);
}
}
}
}
}
@@ -0,0 +1,201 @@
describe('$mdToast service', function() {
beforeEach(module('material.components.toast', 'ngAnimateMock', function($provide) {
}));
function setup(options) {
inject(function($mdToast, $rootScope, $animate) {
options = options || {};
$mdToast.show(options);
$rootScope.$apply();
$animate.triggerCallbacks();
});
}
describe('simple()', function() {
hasConfigMethods(['content', 'action', 'capsule', 'highlightAction']);
it('supports a basic toast', inject(function($mdToast, $rootScope, $timeout, $animate) {
var rejected = false;
var parent = angular.element('<div>');
$mdToast.show(
$mdToast.simple({
parent: parent,
content: 'Do something',
capsule: true
})
).catch(function() {
rejected = true;
});
$rootScope.$digest();
expect(parent.find('span').text()).toBe('Do something');
expect(parent.find('md-toast')).toHaveClass('md-capsule');
$animate.triggerCallbacks();
$timeout.flush();
$animate.triggerCallbacks();
expect(rejected).toBe(true);
}));
it('supports an action toast', inject(function($mdToast, $rootScope, $animate) {
var resolved = false;
var parent = angular.element('<div>');
$mdToast.show(
$mdToast.simple({
content: 'Do something',
parent: parent
})
.action('Click me')
.highlightAction(true)
).then(function() {
resolved = true;
});
$rootScope.$digest();
$animate.triggerCallbacks();
var button = parent.find('button');
expect(button.text()).toBe('Click me');
button.triggerHandler('click');
$rootScope.$digest();
$animate.triggerCallbacks();
expect(resolved).toBe(true);
}));
describe('when using custom interpolation symbols', function() {
beforeEach(module(function($interpolateProvider) {
$interpolateProvider.startSymbol('[[').endSymbol(']]');
}));
it('displays correctly', inject(function($mdToast, $rootScope) {
var parent = angular.element('<div>');
var toast = $mdToast.simple({
content: 'Do something',
parent: parent
}).action('Click me');
$mdToast.show(toast);
$rootScope.$digest();
var content = parent.find('span').eq(0);
var button = parent.find('button');
expect(content.text()).toBe('Do something');
expect(button.text()).toBe('Click me');
}));
});
function hasConfigMethods(methods) {
angular.forEach(methods, function(method) {
return it('supports config method #' + method, inject(function($mdToast) {
var basic = $mdToast.simple();
expect(typeof basic[method]).toBe('function');
expect(basic[method]()).toBe(basic);
}));
});
}
});
describe('build()', function() {
describe('options', function() {
it('should hide current toast when showing new one', inject(function($rootElement) {
setup({
template: '<md-toast class="one">'
});
expect($rootElement[0].querySelector('md-toast.one')).toBeTruthy();
expect($rootElement[0].querySelector('md-toast.two')).toBeFalsy();
expect($rootElement[0].querySelector('md-toast.three')).toBeFalsy();
setup({
template: '<md-toast class="two">'
});
expect($rootElement[0].querySelector('md-toast.one')).toBeFalsy();
expect($rootElement[0].querySelector('md-toast.two')).toBeTruthy();
expect($rootElement[0].querySelector('md-toast.three')).toBeFalsy();
setup({
template: '<md-toast class="three">'
});
expect($rootElement[0].querySelector('md-toast.one')).toBeFalsy();
expect($rootElement[0].querySelector('md-toast.two')).toBeFalsy();
expect($rootElement[0].querySelector('md-toast.three')).toBeTruthy();
}));
it('should hide after duration', inject(function($timeout, $animate, $rootElement) {
var parent = angular.element('<div>');
setup({
template: '<md-toast />',
hideTimeout: 1234
});
expect($rootElement.find('md-toast').length).toBe(1);
$timeout.flush();
expect($rootElement.find('md-toast').length).toBe(0);
}));
it('should have template', inject(function($timeout, $rootScope, $rootElement) {
var parent = angular.element('<div>');
setup({
template: '<md-toast>{{1}}234</md-toast>',
appendTo: parent
});
var toast = $rootElement.find('md-toast');
$timeout.flush();
expect(toast.text()).toBe('1234');
}));
it('should have templateUrl', inject(function($timeout, $rootScope, $templateCache, $rootElement) {
$templateCache.put('template.html', '<md-toast>hello, {{1}}</md-toast>');
setup({
templateUrl: 'template.html',
});
var toast = $rootElement.find('md-toast');
expect(toast.text()).toBe('hello, 1');
}));
it('should add position class to tast', inject(function($rootElement, $timeout) {
setup({
template: '<md-toast>',
position: 'top left'
});
var toast = $rootElement.find('md-toast');
$timeout.flush();
expect(toast.hasClass('md-top')).toBe(true);
expect(toast.hasClass('md-left')).toBe(true);
}));
});
describe('lifecycle', function() {
it('should hide current toast when showing new one', inject(function($rootElement) {
setup({
template: '<md-toast class="one">'
});
expect($rootElement[0].querySelector('md-toast.one')).toBeTruthy();
expect($rootElement[0].querySelector('md-toast.two')).toBeFalsy();
expect($rootElement[0].querySelector('md-toast.three')).toBeFalsy();
setup({
template: '<md-toast class="two">'
});
expect($rootElement[0].querySelector('md-toast.one')).toBeFalsy();
expect($rootElement[0].querySelector('md-toast.two')).toBeTruthy();
expect($rootElement[0].querySelector('md-toast.three')).toBeFalsy();
setup({
template: '<md-toast class="three">'
});
expect($rootElement[0].querySelector('md-toast.one')).toBeFalsy();
expect($rootElement[0].querySelector('md-toast.two')).toBeFalsy();
expect($rootElement[0].querySelector('md-toast.three')).toBeTruthy();
}));
it('should add class to toastParent', inject(function($rootElement) {
setup({
template: '<md-toast>'
});
expect($rootElement.hasClass('md-toast-open-bottom')).toBe(true);
setup({
template: '<md-toast>',
position: 'top'
});
expect($rootElement.hasClass('md-toast-open-top')).toBe(true);
}));
});
});
});