Supplement other js/css files

Keep consistency with npm bower package v1.1.5,
with all minified files removed.
https://github.com/angular/bower-material/releases/tag/v1.1.5

Change-Id: I28f8b7f40452945f8ce322169d3f9acc99acb79a
This commit is contained in:
Xinni Ge 2018-04-10 18:52:26 +09:00
parent 9f6499b081
commit 8f7db83c5c
294 changed files with 212300 additions and 16702 deletions

View File

@ -0,0 +1,186 @@
/**
*
* AngularJS-Material-Mocks
*
* Developers interested in running their own custom unit tests WITH angular-material.js loaded...
* must also include this *mocks* file. Similar to `angular-mocks.js`, `angular-material-mocks.js`
* will override and disable specific AngularJS Material performance settings:
*
* - Disabled Theme CSS rule generations
* - Forces $mdAria.expectWithText() to be synchronous
* - Mocks $$rAF.throttle()
* - Captures flush exceptions from $$rAF
*
*/
(function(window, angular, undefined) {
'use strict';
// Allow our code to know when they are running inside of a test so they can expose extra services
// that should NOT be exposed to the public but that should be tested.
//
// As an example, see input.js which exposes some animation-related methods.
window._mdMocksIncluded = true;
/**
* @ngdoc module
* @name ngMaterial-mock
* @packageName angular-material-mocks
*
* @description
*
* The `ngMaterial-mock` module provides support
*
*/
angular.module('ngMaterial-mock', [
'ngMock',
'ngAnimateMock',
'material.core'
])
.config(['$provide', function($provide) {
$provide.factory('$material', ['$animate', '$timeout', function($animate, $timeout) {
return {
flushOutstandingAnimations: function() {
// this code is placed in a try-catch statement
// since 1.3 and 1.4 handle their animations differently
// and there may be situations where follow-up animations
// are run in one version and not the other
try { $animate.flush(); } catch(e) {}
},
flushInterimElement: function() {
this.flushOutstandingAnimations();
$timeout.flush();
this.flushOutstandingAnimations();
$timeout.flush();
this.flushOutstandingAnimations();
$timeout.flush();
}
};
}]);
/**
* AngularJS Material dynamically generates Style tags
* based on themes and palletes; for each ng-app.
*
* For testing, we want to disable generation and
* <style> DOM injections. So we clear the huge THEME
* styles while testing...
*/
$provide.constant('$MD_THEME_CSS', '/**/');
/**
* Add throttle() and wrap .flush() to catch `no callbacks present`
* errors
*/
$provide.decorator('$$rAF', function throttleInjector($delegate){
$delegate.throttle = function(cb) {
return function() {
cb.apply(this, arguments);
};
};
var ngFlush = $delegate.flush;
$delegate.flush = function() {
try { ngFlush(); }
catch(e) { ; }
};
return $delegate;
});
/**
* Capture $timeout.flush() errors: "No deferred tasks to be flushed"
* errors
*/
$provide.decorator('$timeout', function throttleInjector($delegate){
var ngFlush = $delegate.flush;
$delegate.flush = function() {
var args = Array.prototype.slice.call(arguments);
try { ngFlush.apply($delegate, args); }
catch(e) { }
};
return $delegate;
});
}]);
/**
* Stylesheet Mocks used by `animateCss.spec.js`
*/
window.createMockStyleSheet = function createMockStyleSheet(doc, wind) {
doc = doc ? doc[0] : window.document;
wind = wind || window;
var node = doc.createElement('style');
var head = doc.getElementsByTagName('head')[0];
head.appendChild(node);
var ss = doc.styleSheets[doc.styleSheets.length - 1];
return {
addRule: function(selector, styles) {
styles = addVendorPrefix(styles);
try {
ss.insertRule(selector + '{ ' + styles + '}', 0);
}
catch (e) {
try {
ss.addRule(selector, styles);
}
catch (e2) {}
}
},
destroy: function() {
head.removeChild(node);
}
};
/**
* Decompose styles, attached specific vendor prefixes
* and recompose...
* e.g.
* 'transition:0.5s linear all; font-size:100px;'
* becomes
* '-webkit-transition:0.5s linear all; transition:0.5s linear all; font-size:100px;'
*/
function addVendorPrefix(styles) {
var cache = { };
// Decompose into cache registry
styles
.match(/([\-A-Za-z]*)\w\:\w*([A-Za-z0-9\.\-\s]*)/gi)
.forEach(function(style){
var pair = style.split(":");
var key = pair[0];
switch(key) {
case 'transition':
case 'transform':
case 'animation':
case 'transition-duration':
case 'animation-duration':
cache[key] = cache['-webkit-' + key] = pair[1];
break;
default:
cache[key] = pair[1];
}
});
// Recompose full style object (as string)
styles = "";
angular.forEach(cache, function(value, key) {
styles = styles + key + ":" + value + "; ";
});
return styles;
}
};
})(window, window.angular);

File diff suppressed because it is too large Load Diff

22701
xstatic/pkg/angular_material/data/angular-material.scss Normal file → Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,992 @@
$font-family: Roboto, 'Helvetica Neue', sans-serif !default;
$font-size: 10px !default;
$display-4-font-size-base: rem(11.20) !default;
$display-3-font-size-base: rem(5.600) !default;
$display-2-font-size-base: rem(4.500) !default;
$display-1-font-size-base: rem(3.400) !default;
$headline-font-size-base: rem(2.400) !default;
$title-font-size-base: rem(2.000) !default;
$subhead-font-size-base: rem(1.600) !default;
$body-font-size-base: rem(1.400) !default;
$caption-font-size-base: rem(1.200) !default;
$baseline-grid: 8px !default;
$layout-gutter-width: ($baseline-grid * 2) !default;
$layout-breakpoint-xs: 600px !default;
$layout-breakpoint-sm: 960px !default;
$layout-breakpoint-md: 1280px !default;
$layout-breakpoint-lg: 1920px !default;
$button-left-right-padding: rem(0.600) !default;
$icon-size: rem(2.400) !default;
$app-bar-height: 64px !default;
$toast-height: $baseline-grid * 3 !default;
$toast-margin: $baseline-grid * 1 !default;
$shadow-key-umbra-opacity: 0.2 !default;
$shadow-key-penumbra-opacity: 0.14 !default;
$shadow-ambient-shadow-opacity: 0.12 !default;
$whiteframe-shadow-1dp: 0px 1px 3px 0px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 1px 1px 0px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 2px 1px -1px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-2dp: 0px 1px 5px 0px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 2px 2px 0px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 3px 1px -2px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-3dp: 0px 1px 8px 0px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 3px 4px 0px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 3px 3px -2px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-4dp: 0px 2px 4px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 4px 5px 0px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 1px 10px 0px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-5dp: 0px 3px 5px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 5px 8px 0px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 1px 14px 0px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-6dp: 0px 3px 5px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 6px 10px 0px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 1px 18px 0px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-7dp: 0px 4px 5px -2px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 7px 10px 1px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 2px 16px 1px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-8dp: 0px 5px 5px -3px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 8px 10px 1px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 3px 14px 2px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-9dp: 0px 5px 6px -3px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 9px 12px 1px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 3px 16px 2px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-10dp: 0px 6px 6px -3px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 10px 14px 1px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 4px 18px 3px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-11dp: 0px 6px 7px -4px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 11px 15px 1px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 4px 20px 3px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-12dp: 0px 7px 8px -4px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 12px 17px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 5px 22px 4px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-13dp: 0px 7px 8px -4px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 13px 19px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 5px 24px 4px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-14dp: 0px 7px 9px -4px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 14px 21px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 5px 26px 4px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-15dp: 0px 8px 9px -5px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 15px 22px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 6px 28px 5px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-16dp: 0px 8px 10px -5px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 16px 24px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 6px 30px 5px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-17dp: 0px 8px 11px -5px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 17px 26px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 6px 32px 5px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-18dp: 0px 9px 11px -5px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 18px 28px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 7px 34px 6px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-19dp: 0px 9px 12px -6px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 19px 29px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 7px 36px 6px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-20dp: 0px 10px 13px -6px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 20px 31px 3px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 8px 38px 7px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-21dp: 0px 10px 13px -6px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 21px 33px 3px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 8px 40px 7px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-22dp: 0px 10px 14px -6px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 22px 35px 3px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 8px 42px 7px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-23dp: 0px 11px 14px -7px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 23px 36px 3px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 9px 44px 8px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$whiteframe-shadow-24dp: 0px 11px 15px -7px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0px 24px 38px 3px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0px 9px 46px 8px rgba(0, 0, 0, $shadow-ambient-shadow-opacity) !default;
$z-index-toast: 105 !default;
$z-index-tooltip: 100 !default;
$z-index-menu: 100 !default;
$z-index-calendar-pane: 100 !default;
$z-index-select: 90 !default;
$z-index-dialog: 80 !default;
$z-index-bottom-sheet: 70 !default;
$z-index-scroll-mask: 50 !default;
$z-index-scroll-mask-bar: 65 !default;
$z-index-sidenav: 60 !default;
$z-index-backdrop: 50 !default;
$z-index-fab: 20 !default;
$z-index-progress-circular: 2 !default; // Used to fix animation bug in Chrome
$swift-ease-out-duration: 0.4s !default;
$swift-ease-out-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !default;
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-timing-function !default;
$swift-ease-in-duration: 0.3s !default;
$swift-ease-in-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2) !default;
$swift-ease-in: all $swift-ease-in-duration $swift-ease-in-timing-function !default;
$swift-ease-in-out-duration: 0.5s !default;
$swift-ease-in-out-timing-function: cubic-bezier(0.35, 0, 0.25, 1) !default;
$swift-ease-in-out: all $swift-ease-in-out-duration $swift-ease-in-out-timing-function !default;
$swift-linear-duration: 0.08s !default;
$swift-linear-timing-function: linear !default;
$swift-linear: all $swift-linear-duration $swift-linear-timing-function !default;
$material-enter-duration: 0.3s;
$material-enter-timing-function: cubic-bezier(0.0, 0.0, 0.2, 1);
$material-enter: all $material-enter-duration $material-enter-timing-function;
$material-leave-duration: 0.3s;
$material-leave-timing-function: cubic-bezier(0.4, 0.0, 1, 1);
$material-leave: all $material-leave-duration $material-leave-timing-function;
$button-fab-width: rem(5.600) !default;
$button-fab-height: rem(5.600) !default;
$button-fab-padding: rem(1.60) !default;
$checkbox-width: 20px !default;
$checkbox-height: $checkbox-width !default;
$checkbox-border-radius: 2px !default;
$checkbox-border-width: 2px !default;
$baseline-grid: 8px !default;
$layout-gutter-width: ($baseline-grid * 2) !default;
$layout-breakpoint-xs: 600px !default;
$layout-breakpoint-sm: 960px !default;
$layout-breakpoint-md: 1280px !default;
$layout-breakpoint-lg: 1920px !default;
// Typography
// ------------------------------
//-- Must be defined before $font-size.
@function rem($multiplier) {
@return $multiplier * $font-size;
}
// Layout
// ------------------------------
// Button
// Icon
// App bar variables
// Whiteframes
// NOTE(shyndman): gulp-sass seems to be failing if I split the shadow defs across
// multiple lines. Ugly. Sorry.
// Z-indexes
//--------------------------------------------
// Easing Curves
//--------------------------------------------
// Fab Buttons (shared between buttons.scss and fab*.scss)
// -------------------------------------------
// Shared Checkbox variables
@mixin margin-selectors($before:1em, $after:1em, $start:0px, $end:0px) {
-webkit-margin-before: $before;
-webkit-margin-after: $after;
-webkit-margin-start: $start;
-webkit-margin-end: $end;
}
@mixin not-selectable($value:none) {
-webkit-touch-callout: $value;
-webkit-user-select: $value;
-khtml-user-select: $value;
-moz-user-select: $value;
-ms-user-select: $value;
user-select: $value;
}
@mixin input-placeholder-color($color) {
$pseudos: '::-webkit-input-placeholder', ':-moz-placeholder', '::-moz-placeholder',
':-ms-input-placeholder', '::-webkit-input-placeholder';
// It is important to export every pseudo within its own block, because otherwise the placeholder
// won't be set on the most browsers.
@each $pseudo in $pseudos {
&#{$pseudo} {
color: unquote($color);
}
}
}
@mixin pie-clearfix {
&:after {
content: '';
display: table;
clear: both;
}
}
@mixin md-shadow-bottom-z-1() {
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
}
@mixin md-shadow-bottom-z-2() {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4);
}
// Mixin for a "flat" input that can be used for components that contain an input
// (datepicker, autocomplete).
@mixin md-flat-input() {
font-size: 14px;
box-sizing: border-box;
border: none;
box-shadow: none;
outline: none;
background: transparent;
// The "clear X" that IE adds to input[type="search"]
&::-ms-clear {
display: none;
}
}
// Typography mixins
@mixin md-title() {
font-size: $title-font-size-base;
font-weight: 500;
letter-spacing: 0.005em;
}
@mixin md-body-1() {
font-size: $body-font-size-base;
font-weight: 400;
letter-spacing: 0.010em;
line-height: rem(2);
}
@mixin md-body-2() {
font-size: $body-font-size-base;
font-weight: 500;
letter-spacing: 0.010em;
line-height: rem(2.4);
}
@mixin md-subhead() {
font-size: $subhead-font-size-base;
font-weight: 400;
letter-spacing: 0.010em;
line-height: rem(2.4);
}
@function map-to-string($map) {
$map-str: '{';
$keys: map-keys($map);
$len: length($keys);
@for $i from 1 through $len {
$key: nth($keys, $i);
$value: map-get($map, $key);
$map-str: $map-str + '_' + $key + '_: _' + map-get($map, $key) + '_';
@if $i != $len {
$map-str: $map-str + ',';
}
}
@return $map-str + '}';
}
// This is a mixin, which fixes IE11's vertical alignment issue, when using `min-height`.
// See https://connect.microsoft.com/IE/feedback/details/816293/
@mixin ie11-min-height-flexbug($min-height) {
&::before {
content: '';
min-height: $min-height;
visibility: hidden;
display: inline-block;
}
}
// mixin definition ; sets LTR and RTL within the same style call
// @see https://css-tricks.com/almanac/properties/d/direction/
@mixin rtl($prop, $ltr-value, $rtl-value) {
#{$prop}: $ltr-value;
[dir=rtl] & {
#{$prop}: $rtl-value;
}
}
@mixin rtl-prop($ltr-prop, $rtl-prop, $value, $reset-value) {
#{$ltr-prop}: $value;
[dir=rtl] & {
#{$ltr-prop}: $reset-value;
#{$rtl-prop}: $value;
}
}
// To reverse padding (top left bottom right) -> (top right bottom left)
@function rtl-value($list) {
@if length($list) == 4 {
@return nth($list, 1) nth($list, 4) nth($list, 3) nth($list, 2)
}
@if length($list) == 5 {
@return nth($list, 1) nth($list, 4) nth($list, 3) nth($list, 2) nth($list, 5)
}
@return $list;
}
// Position a FAB button.
@mixin fab-position($spot, $top: auto, $right: auto, $bottom: auto, $left: auto) {
&.md-fab-#{$spot} {
top: $top;
right: $right;
bottom: $bottom;
left: $left;
position: absolute;
}
}
@mixin fab-all-positions() {
@include fab-position(bottom-right, auto, ($button-fab-width - $button-fab-padding)/2, ($button-fab-height - $button-fab-padding)/2, auto);
@include fab-position(bottom-left, auto, auto, ($button-fab-height - $button-fab-padding)/2, ($button-fab-width - $button-fab-padding)/2);
@include fab-position(top-right, ($button-fab-height - $button-fab-padding)/2, ($button-fab-width - $button-fab-padding)/2, auto, auto);
@include fab-position(top-left, ($button-fab-height - $button-fab-padding)/2, auto, auto, ($button-fab-width - $button-fab-padding)/2);
}
// This mixin allows a user to use the md-checkbox css outside of the
// md-checkbox directive.
// See src/components/select/select.scss for an example.
@mixin checkbox-container(
$checkedSelector: '.md-checked',
$width: $checkbox-width,
$height: $checkbox-height,
$border-width: $checkbox-border-width,
$border-radius: $checkbox-border-radius) {
.md-container {
position: absolute;
top: 50%;
transform: translateY(-50%);
box-sizing: border-box;
display: inline-block;
width: $width;
height: $height;
@include rtl(left, 0, auto);
@include rtl(right, auto, 0);
&:before {
box-sizing: border-box;
background-color: transparent;
border-radius: 50%;
content: '';
position: absolute;
display: block;
height: auto;
left: 0;
top: 0;
right: 0;
bottom: 0;
transition: all 0.5s;
width: auto;
}
&:after {
box-sizing: border-box;
content: '';
position: absolute;
top: -10px;
right: -10px;
bottom: -10px;
left: -10px;
}
.md-ripple-container {
position: absolute;
display: block;
width: auto;
height: auto;
left: -15px;
top: -15px;
right: -15px;
bottom: -15px;
}
}
// unchecked
.md-icon {
box-sizing: border-box;
transition: 240ms;
position: absolute;
top: 0;
left: 0;
width: $width;
height: $height;
border-width: $border-width;
border-style: solid;
border-radius: $border-radius;
}
&#{$checkedSelector} .md-icon {
border-color: transparent;
&:after {
box-sizing: border-box;
transform: rotate(45deg);
position: absolute;
left: $width / 3 - $border-width;
top: $width / 9 - $border-width;
display: table;
width: $width / 3;
height: $width * 2 / 3;
border-width: $border-width;
border-style: solid;
border-top: 0;
border-left: 0;
content: '';
}
}
// disabled
&[disabled] {
cursor: default;
}
&.md-indeterminate .md-icon {
&:after {
box-sizing: border-box;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: table;
width: $width * 0.6;
height: $border-width;
border-width: $border-width;
border-style: solid;
border-top: 0;
border-left: 0;
content: '';
}
}
}
// Mixin to create a primary checkbox.
// Used by the checkbox and select component.
@mixin checkbox-primary($checkedSelector: '.md-checked') {
.md-ripple {
color: '{{primary-600}}';
}
&#{$checkedSelector} .md-ripple {
color: '{{background-600}}';
}
.md-ink-ripple {
color: '{{foreground-2}}';
}
&#{$checkedSelector} .md-ink-ripple {
color: '{{primary-color-0.87}}';
}
&:not(.md-checked) .md-icon {
border-color: '{{foreground-2}}';
}
&#{$checkedSelector} .md-icon {
background-color: '{{primary-color-0.87}}';
}
&#{$checkedSelector}.md-focused .md-container:before {
background-color: '{{primary-color-0.26}}';
}
&#{$checkedSelector} .md-icon:after {
border-color: '{{primary-contrast-0.87}}';
}
& .md-indeterminate[disabled] {
.md-container {
color: '{{foreground-3}}';
}
}
}
@mixin dense($prop, $normal, $dense) {
#{$prop}: $normal;
.md-dense > &:not(.md-dense-disabled),
.md-dense :not(.md-dense-disabled) &:not(.md-dense-disabled) {
#{$prop}: $dense;
}
}
@mixin dense-rtl($prop, $ltr-normal, $rtl-normal, $ltr-dense, $rtl-dense) {
@include rtl($prop, $ltr-normal, $rtl-normal);
.md-dense > &:not(.md-dense-disabled),
.md-dense :not(.md-dense-disabled) &:not(.md-dense-disabled) {
@include rtl($prop, $ltr-dense, $rtl-dense);
}
}
/*
*
* Responsive attributes
*
* References:
* 1) https://scotch.io/tutorials/a-visual-guide-to-css3-flexbox-properties#flex
* 2) https://css-tricks.com/almanac/properties/f/flex/
* 3) https://css-tricks.com/snippets/css/a-guide-to-flexbox/
* 4) https://github.com/philipwalton/flexbugs#3-min-height-on-a-flex-container-wont-apply-to-its-flex-items
* 5) http://godban.com.ua/projects/flexgrid
*
*/
// Layout
// ------------------------------
@-moz-document url-prefix() {
[layout-fill] {
margin: 0;
width: 100%;
min-height: 100%;
height: 100%;
}
}
@mixin flex-order-for-name($sizes:null) {
@if $sizes == null {
$sizes : '';
[flex-order] {
order : 0;
}
}
@for $i from -20 through 20 {
$order : '';
$suffix : '';
@each $s in $sizes {
@if $s != '' { $suffix : '-#{$s}="#{$i}"'; }
@else { $suffix : '="#{$i}"'; }
$order : '[flex-order#{$suffix}]';
}
#{$order} {
order: #{$i};
}
}
}
@mixin offset-for-name($sizes:null) {
@if $sizes == null { $sizes : ''; }
@for $i from 0 through 19 {
$offsets : '';
$suffix : '';
@each $s in $sizes {
@if $s != '' { $suffix : '-#{$s}="#{$i * 5}"'; }
@else { $suffix : '="#{$i * 5}"'; }
$offsets : $offsets + '[flex-offset#{$suffix}], ';
}
#{$offsets} {
margin-left: #{$i * 5 + '%'};
}
}
@each $i in 33 {
$offsets : '';
$suffix : '';
@each $s in $sizes {
@if $s != '' { $suffix : '-#{$s}="#{$i}"'; }
@else { $suffix : '="#{$i}"'; }
$offsets : '[flex-offset#{$suffix}], ';
}
#{$offsets} {
margin-left: calc(100% / 3);
}
}
@each $i in 66 {
$offsets : '';
$suffix : '';
@each $s in $sizes {
@if $s != '' { $suffix : '-#{$s}="#{$i}"'; }
@else { $suffix : '="#{$i}"'; }
$offsets : '[flex-offset#{$suffix}]';
}
#{$offsets} {
margin-left: calc(200% / 3);
}
}
}
@mixin layout-for-name($name: null) {
@if $name == null { $name : ''; }
@if $name != '' { $name : '-#{$name}'; }
[layout#{$name}], [layout#{$name}="column"], [layout#{$name}="row"] {
box-sizing: border-box;
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
}
[layout#{$name}="column"] { flex-direction: column; }
[layout#{$name}="row"] { flex-direction: row; }
}
@mixin flex-properties-for-name($name: null) {
$flexName: 'flex';
@if $name != null {
$flexName: 'flex-#{$name}';
$name : '-#{$name}';
} @else {
$name : '';
}
[#{$flexName}] { flex: 1; box-sizing: border-box; } // === flex: 1 1 0%;
[#{$flexName}-grow] { flex: 1 1 100%; box-sizing: border-box; }
[#{$flexName}-initial] { flex: 0 1 auto; box-sizing: border-box; }
[#{$flexName}-auto] { flex: 1 1 auto; box-sizing: border-box; }
[#{$flexName}-none] { flex: 0 0 auto; box-sizing: border-box; }
// (1-20) * 5 = 0-100%
@for $i from 0 through 20 {
$value : #{$i * 5 + '%'};
[#{$flexName}="#{$i * 5}"] {
flex: 1 1 #{$value};
max-width: #{$value};
max-height: 100%;
box-sizing: border-box;
}
[layout="row"] > [#{$flexName}="#{$i * 5}"] {
flex: 1 1 #{$value};
max-width: #{$value};
max-height: 100%;
box-sizing: border-box;
}
[layout="column"] > [#{$flexName}="#{$i * 5}"] {
flex: 1 1 #{$value};
max-width: 100%;
max-height: #{$value};
box-sizing: border-box;
}
[layout="row"] {
> [#{$flexName}="33"] , > [#{$flexName}="33"] { flex: 1 1 33.33%; max-width: 33.33%; max-height: 100%; box-sizing: border-box; }
> [#{$flexName}="66"] , > [#{$flexName}="66"] { flex: 1 1 66.66%; max-width: 66.66%; max-height: 100%; box-sizing: border-box; }
}
[layout="column"] {
> [#{$flexName}="33"] , > [#{$flexName}="33"] { flex: 1 1 33.33%; max-width: 100%; max-height: 33.33%; box-sizing: border-box; }
> [#{$flexName}="66"] , > [#{$flexName}="66"] { flex: 1 1 66.66%; max-width: 100%; max-height: 66.66%; box-sizing: border-box; }
}
[layout#{$name}="row"] > [#{$flexName}="#{$i * 5}"] {
flex: 1 1 #{$value};
max-width: #{$value};
max-height: 100%;
box-sizing: border-box;
}
[layout#{$name}="column"] > [#{$flexName}="#{$i * 5}"] {
flex: 1 1 #{$value};
max-width: 100%;
max-height: #{$value};
box-sizing: border-box;
}
}
[layout#{$name}="row"] {
> [#{$flexName}="33"] , > [#{$flexName}="33"] { flex: 1 1 33.33%; max-width: 33.33%; max-height: 100%; box-sizing: border-box; }
> [#{$flexName}="66"] , > [#{$flexName}="66"] { flex: 1 1 66.66%; max-width: 66.66%; max-height: 100%; box-sizing: border-box; }
}
[layout#{$name}="column"] {
> [#{$flexName}="33"] , > [#{$flexName}="33"] { flex: 1 1 33.33%; max-width: 100%; max-height: 33.33%; box-sizing: border-box; }
> [#{$flexName}="66"] , > [#{$flexName}="66"] { flex: 1 1 66.66%; max-width: 100%; max-height: 66.66%; box-sizing: border-box; }
}
}
@mixin layout-align-for-name($suffix: null) {
// Alignment attributes for layout containers' children
// Arrange on the Main Axis
// center, start, end, space-between, space-around
// flex-start is the default for justify-content
// ------------------------------
$name: 'layout-align';
@if $suffix != null {
$name: 'layout-align-#{$suffix}';
}
[#{$name}],
[#{$name}="start stretch"] // defaults
{
justify-content :flex-start;
align-content : stretch;
align-items: stretch;
}
// Main Axis Center
[#{$name}="start"],
[#{$name}="start start"],
[#{$name}="start center"],
[#{$name}="start end"],
[#{$name}="start stretch"]
{
justify-content: flex-start;
}
// Main Axis Center
[#{$name}="center"],
[#{$name}="center start"],
[#{$name}="center center"],
[#{$name}="center end"],
[#{$name}="center stretch"]
{
justify-content: center;
}
// Main Axis End
[#{$name}="end"], //stretch
[#{$name}="end center"],
[#{$name}="end start"],
[#{$name}="end end"],
[#{$name}="end stretch"]
{
justify-content: flex-end;
}
// Main Axis Space Around
[#{$name}="space-around"], //stretch
[#{$name}="space-around center"],
[#{$name}="space-around start"],
[#{$name}="space-around end"],
[#{$name}="space-around stretch"]
{
justify-content: space-around;
}
// Main Axis Space Between
[#{$name}="space-between"], //stretch
[#{$name}="space-between center"],
[#{$name}="space-between start"],
[#{$name}="space-between end"],
[#{$name}="space-between stretch"]
{
justify-content: space-between;
}
// Arrange on the Cross Axis
// center, start, end
// stretch is the default for align-items
// ------------------------------
// Cross Axis Start
[#{$name}="start start"],
[#{$name}="center start"],
[#{$name}="end start"],
[#{$name}="space-between start"],
[#{$name}="space-around start"]
{
align-items: flex-start;
align-content: flex-start;
}
// Cross Axis Center
[#{$name}="start center"],
[#{$name}="center center"],
[#{$name}="end center"],
[#{$name}="space-between center"],
[#{$name}="space-around center"]
{
align-items: center;
align-content: center;
max-width: 100%;
}
// Cross Axis Center IE overflow fix
[#{$name}="start center"] > *,
[#{$name}="center center"] > *,
[#{$name}="end center"] > *,
[#{$name}="space-between center"] > *,
[#{$name}="space-around center"] > *
{
max-width: 100%;
box-sizing: border-box;
}
// Cross Axis End
[#{$name}="start end"],
[#{$name}="center end"],
[#{$name}="end end"],
[#{$name}="space-between end"],
[#{$name}="space-around end"]
{
align-items: flex-end;
align-content: flex-end;
}
// Cross Axis stretch
[#{$name}="start stretch"],
[#{$name}="center stretch"],
[#{$name}="end stretch"],
[#{$name}="space-between stretch"],
[#{$name}="space-around stretch"]
{
align-items: stretch;
align-content: stretch;
}
}
@mixin layout-padding-margin() {
[layout-padding] > [flex-sm], [layout-padding] > [flex-lt-md] {
padding: $layout-gutter-width / 4;
}
[layout-padding],
[layout-padding] > [flex],
[layout-padding] > [flex-gt-sm],
[layout-padding] > [flex-md],
[layout-padding] > [flex-lt-lg]
{
padding: $layout-gutter-width / 2;
}
[layout-padding] > [flex-gt-md],
[layout-padding] > [flex-lg]
{
padding: $layout-gutter-width / 1;
}
[layout-margin] > [flex-sm],
[layout-margin] > [flex-lt-md]
{
margin: $layout-gutter-width / 4;
}
[layout-margin],
[layout-margin] > [flex],
[layout-margin] > [flex-gt-sm],
[layout-margin] > [flex-md],
[layout-margin] > [flex-lt-lg]
{
margin: $layout-gutter-width / 2;
}
[layout-margin] > [flex-gt-md],
[layout-margin] > [flex-lg]
{
margin: $layout-gutter-width / 1;
}
[layout-wrap] {
flex-wrap: wrap;
}
[layout-nowrap] {
flex-wrap: nowrap;
}
[layout-fill] {
margin: 0;
width: 100%;
min-height: 100%;
height: 100%;
}
}
@mixin layouts_for_breakpoint($name:null) {
@include flex-order-for-name($name);
@include offset-for-name($name);
@include layout-align-for-name($name);
@include flex-properties-for-name($name);
@include layout-for-name($name);
}
/*
* Apply Mixins to create Layout/Flexbox styles
*
*/
@include layouts_for_breakpoint();
@include layout-padding-margin();
/**
* `hide-gt-sm show-gt-lg` should hide from 600px to 1200px
* `show-md hide-gt-sm` should show from 0px to 960px and hide at >960px
* `hide-gt-md show-gt-sm` should show everywhere (show overrides hide)`
*
* hide means hide everywhere
* Sizes:
* $layout-breakpoint-xs: 600px !default;
* $layout-breakpoint-sm: 960px !default;
* $layout-breakpoint-md: 1280px !default;
* $layout-breakpoint-lg: 1920px !default;
*/
@media (max-width: $layout-breakpoint-xs - 1) {
// Xtra-SMALL SCREEN
[hide-xs], [hide] {
&:not([show-xs]):not([show]) {
display: none;
}
}
@include layouts_for_breakpoint(xs);
}
@media (min-width: $layout-breakpoint-xs) {
// BIGGER THAN Xtra-SMALL SCREEN
@include layouts_for_breakpoint(gt-xs);
}
@media (min-width: $layout-breakpoint-xs) and (max-width: $layout-breakpoint-sm - 1) {
// SMALL SCREEN
[hide], [hide-gt-xs] {
&:not([show-gt-xs]):not([show-sm]):not([show]) {
display: none;
}
}
[hide-sm]:not([show-gt-xs]):not([show-sm]):not([show]) {
display: none;
}
@include layouts_for_breakpoint(sm);
}
@media (min-width: $layout-breakpoint-sm) {
// BIGGER THAN SMALL SCREEN
@include layouts_for_breakpoint(gt-sm);
}
@media (min-width: $layout-breakpoint-sm) and (max-width: $layout-breakpoint-md - 1) {
// MEDIUM SCREEN
[hide], [hide-gt-xs], [hide-gt-sm] {
&:not([show-gt-xs]):not([show-gt-sm]):not([show-md]):not([show]) {
display: none;
}
}
[hide-md]:not([show-md]):not([show]) {
display: none;
}
@include layouts_for_breakpoint(md);
}
@media (min-width: $layout-breakpoint-md) {
// BIGGER THAN MEDIUM SCREEN
@include layouts_for_breakpoint(gt-md);
}
@media (min-width: $layout-breakpoint-md) and (max-width: $layout-breakpoint-lg - 1) {
// LARGE SCREEN
[hide],[hide-gt-xs], [hide-gt-sm], [hide-gt-md] {
&:not([show-gt-xs]):not([show-gt-sm]):not([show-gt-md]):not([show-lg]):not([show]) {
display: none;
}
}
[hide-lg]:not([show-lg]):not([show]) {
display: none;
}
@include layouts_for_breakpoint(lg);
}
@media (min-width: $layout-breakpoint-lg) {
// BIGGER THAN LARGE SCREEN
@include layouts_for_breakpoint(gt-lg);
@include layouts_for_breakpoint(xl);
// BIGGER THAN LARGE SCREEN
[hide], [hide-gt-xs], [hide-gt-sm], [hide-gt-md], [hide-gt-lg] {
&:not([show-gt-xs]):not([show-gt-sm]):not([show-gt-md]):not([show-gt-lg]):not([show-xl]):not([show]) {
display: none;
}
}
[hide-xl]:not([show-xl]):not([show-gt-lg]):not([show]) {
display: none;
}
}
@media print {
// PRINT
@include layouts_for_breakpoint(print);
[hide-print]:not([show-print]):not([show]) {
display: none;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,104 @@
/* IE mediaQuery hack for 8,9,10 to set the flex-basis properly for 'flex' values */
/* Details: */
/* Do not use unitless flex-basis values in the flex shorthand because IE 10-11 will error. */
/* Also use 0% instead of 0px since minifiers will often convert 0px to 0 (which is unitless and will have the same problem). */
/* Safari, however, fails with flex-basis : 0% and requires flex-basis : 0px */
@media screen\0 {
.flex {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0 {
.flex {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (max-width: 599px) {
.flex-xs {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (min-width: 600px) {
.flex-gt-xs {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (min-width: 600px) and (max-width: 959px) {
.flex-sm {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (min-width: 960px) {
.flex-gt-sm {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (min-width: 960px) and (max-width: 1279px) {
.flex-md {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (min-width: 1280px) {
.flex-gt-md {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (min-width: 1280px) and (max-width: 1919px) {
.flex-lg {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (min-width: 1920px) {
.flex-gt-lg {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}
@media screen\0
and (min-width: 1920px) {
.flex-xl {
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-autocomplete.md-THEME_NAME-theme {
background: '{{background-A100}}'; }
md-autocomplete.md-THEME_NAME-theme[disabled]:not([md-floating-label]) {
background: '{{background-100}}'; }
md-autocomplete.md-THEME_NAME-theme button md-icon path {
fill: '{{background-600}}'; }
md-autocomplete.md-THEME_NAME-theme button:after {
background: '{{background-600-0.3}}'; }
.md-autocomplete-suggestions-container.md-THEME_NAME-theme {
background: '{{background-A100}}'; }
.md-autocomplete-suggestions-container.md-THEME_NAME-theme li {
color: '{{background-900}}'; }
.md-autocomplete-suggestions-container.md-THEME_NAME-theme li .highlight {
color: '{{background-600}}'; }
.md-autocomplete-suggestions-container.md-THEME_NAME-theme li:hover, .md-autocomplete-suggestions-container.md-THEME_NAME-theme li.selected {
background: '{{background-200}}'; }

View File

@ -0,0 +1,196 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-autocomplete {
border-radius: 2px;
display: block;
height: 40px;
position: relative;
overflow: visible;
min-width: 190px; }
md-autocomplete[disabled] input {
cursor: default; }
md-autocomplete[md-floating-label] {
border-radius: 0;
background: transparent;
height: auto; }
md-autocomplete[md-floating-label] md-input-container {
padding-bottom: 0; }
md-autocomplete[md-floating-label] md-autocomplete-wrap {
height: auto; }
md-autocomplete[md-floating-label] .md-show-clear-button button {
display: block;
position: absolute;
right: 0;
top: 20px;
width: 30px;
height: 30px; }
md-autocomplete[md-floating-label] .md-show-clear-button input {
padding-right: 30px; }
[dir=rtl] md-autocomplete[md-floating-label] .md-show-clear-button input {
padding-right: 0;
padding-left: 30px; }
md-autocomplete md-autocomplete-wrap {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
box-sizing: border-box;
position: relative;
overflow: visible;
height: 40px; }
md-autocomplete md-autocomplete-wrap.md-menu-showing {
z-index: 51; }
md-autocomplete md-autocomplete-wrap md-input-container, md-autocomplete md-autocomplete-wrap input {
-webkit-box-flex: 1;
-webkit-flex: 1 1 0%;
flex: 1 1 0%;
box-sizing: border-box;
min-width: 0; }
md-autocomplete md-autocomplete-wrap md-progress-linear {
position: absolute;
bottom: -2px;
left: 0; }
md-autocomplete md-autocomplete-wrap md-progress-linear.md-inline {
bottom: 40px;
right: 2px;
left: 2px;
width: auto; }
md-autocomplete md-autocomplete-wrap md-progress-linear .md-mode-indeterminate {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 3px;
-webkit-transition: none;
transition: none; }
md-autocomplete md-autocomplete-wrap md-progress-linear .md-mode-indeterminate .md-container {
-webkit-transition: none;
transition: none;
height: 3px; }
md-autocomplete md-autocomplete-wrap md-progress-linear .md-mode-indeterminate.ng-enter {
-webkit-transition: opacity 0.15s linear;
transition: opacity 0.15s linear; }
md-autocomplete md-autocomplete-wrap md-progress-linear .md-mode-indeterminate.ng-enter.ng-enter-active {
opacity: 1; }
md-autocomplete md-autocomplete-wrap md-progress-linear .md-mode-indeterminate.ng-leave {
-webkit-transition: opacity 0.15s linear;
transition: opacity 0.15s linear; }
md-autocomplete md-autocomplete-wrap md-progress-linear .md-mode-indeterminate.ng-leave.ng-leave-active {
opacity: 0; }
md-autocomplete input:not(.md-input) {
font-size: 14px;
box-sizing: border-box;
border: none;
box-shadow: none;
outline: none;
background: transparent;
width: 100%;
padding: 0 15px;
line-height: 40px;
height: 40px; }
md-autocomplete input:not(.md-input)::-ms-clear {
display: none; }
md-autocomplete .md-show-clear-button button {
position: relative;
line-height: 20px;
text-align: center;
width: 30px;
height: 30px;
cursor: pointer;
border: none;
border-radius: 50%;
padding: 0;
font-size: 12px;
background: transparent;
margin: auto 5px; }
md-autocomplete .md-show-clear-button button:after {
content: '';
position: absolute;
top: -6px;
right: -6px;
bottom: -6px;
left: -6px;
border-radius: 50%;
-webkit-transform: scale(0);
transform: scale(0);
opacity: 0;
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); }
md-autocomplete .md-show-clear-button button:focus {
outline: none; }
md-autocomplete .md-show-clear-button button:focus:after {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1; }
md-autocomplete .md-show-clear-button button md-icon {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate3d(-50%, -50%, 0) scale(0.9);
transform: translate3d(-50%, -50%, 0) scale(0.9); }
md-autocomplete .md-show-clear-button button md-icon path {
stroke-width: 0; }
md-autocomplete .md-show-clear-button button.ng-enter {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transition: -webkit-transform 0.15s ease-out;
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out;
transition: transform 0.15s ease-out, -webkit-transform 0.15s ease-out; }
md-autocomplete .md-show-clear-button button.ng-enter.ng-enter-active {
-webkit-transform: scale(1);
transform: scale(1); }
md-autocomplete .md-show-clear-button button.ng-leave {
-webkit-transition: -webkit-transform 0.15s ease-out;
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out;
transition: transform 0.15s ease-out, -webkit-transform 0.15s ease-out; }
md-autocomplete .md-show-clear-button button.ng-leave.ng-leave-active {
-webkit-transform: scale(0);
transform: scale(0); }
@media screen and (-ms-high-contrast: active) {
md-autocomplete input {
border: 1px solid #fff; }
md-autocomplete li:focus {
color: #fff; } }
.md-virtual-repeat-container.md-autocomplete-suggestions-container {
position: absolute;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25);
z-index: 100;
height: 100%; }
.md-virtual-repeat-container.md-not-found {
height: 48px; }
.md-autocomplete-suggestions {
margin: 0;
list-style: none;
padding: 0; }
.md-autocomplete-suggestions li {
font-size: 14px;
overflow: hidden;
padding: 0 15px;
line-height: 48px;
height: 48px;
-webkit-transition: background 0.15s linear;
transition: background 0.15s linear;
margin: 0;
white-space: nowrap;
text-overflow: ellipsis; }
.md-autocomplete-suggestions li:focus {
outline: none; }
.md-autocomplete-suggestions li:not(.md-not-found-wrapper) {
cursor: pointer; }
@media screen and (-ms-high-contrast: active) {
md-autocomplete,
.md-autocomplete-suggestions {
border: 1px solid #fff; } }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-backdrop {
background-color: '{{background-900-0.0}}'; }
md-backdrop.md-opaque.md-THEME_NAME-theme {
background-color: '{{background-900-1.0}}'; }

View File

@ -0,0 +1,42 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-backdrop {
-webkit-transition: opacity 450ms;
transition: opacity 450ms;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 50; }
md-backdrop.md-menu-backdrop {
position: fixed !important;
z-index: 99; }
md-backdrop.md-select-backdrop {
z-index: 81;
-webkit-transition-duration: 0;
transition-duration: 0; }
md-backdrop.md-dialog-backdrop {
z-index: 79; }
md-backdrop.md-bottom-sheet-backdrop {
z-index: 69; }
md-backdrop.md-sidenav-backdrop {
z-index: 59; }
md-backdrop.md-click-catcher {
position: absolute; }
md-backdrop.md-opaque {
opacity: .48; }
md-backdrop.md-opaque.ng-enter {
opacity: 0; }
md-backdrop.md-opaque.ng-enter.md-opaque.ng-enter-active {
opacity: .48; }
md-backdrop.md-opaque.ng-leave {
opacity: .48;
-webkit-transition: opacity 400ms;
transition: opacity 400ms; }
md-backdrop.md-opaque.ng-leave.md-opaque.ng-leave-active {
opacity: 0; }

View File

@ -0,0 +1,93 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.backdrop');
goog.require('ngmaterial.core');
/*
* @ngdoc module
* @name material.components.backdrop
* @description Backdrop
*/
/**
* @ngdoc directive
* @name mdBackdrop
* @module material.components.backdrop
*
* @restrict E
*
* @description
* `<md-backdrop>` is a backdrop element used by other components, such as dialog and bottom sheet.
* Apply class `opaque` to make the backdrop use the theme backdrop color.
*
*/
angular
.module('material.components.backdrop', ['material.core'])
.directive('mdBackdrop', ["$mdTheming", "$mdUtil", "$animate", "$rootElement", "$window", "$log", "$$rAF", "$document", function BackdropDirective($mdTheming, $mdUtil, $animate, $rootElement, $window, $log, $$rAF, $document) {
var ERROR_CSS_POSITION = '<md-backdrop> may not work properly in a scrolled, static-positioned parent container.';
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);
var bodyStyles;
$$rAF(function() {
// If body scrolling has been disabled using mdUtil.disableBodyScroll(),
// adjust the 'backdrop' height to account for the fixed 'body' top offset.
// Note that this can be pretty expensive and is better done inside the $$rAF.
bodyStyles = $window.getComputedStyle($document[0].body);
if (bodyStyles.position === 'fixed') {
var resizeHandler = $mdUtil.debounce(function(){
bodyStyles = $window.getComputedStyle($document[0].body);
resize();
}, 60, null, false);
resize();
angular.element($window).on('resize', resizeHandler);
scope.$on('$destroy', function() {
angular.element($window).off('resize', resizeHandler);
});
}
// Often $animate.enter() is used to append the backDrop element
// so let's wait until $animate is done...
var parent = element.parent();
if (parent.length) {
if (parent[0].nodeName === 'BODY') {
element.css('position', 'fixed');
}
var styles = $window.getComputedStyle(parent[0]);
if (styles.position === 'static') {
// backdrop uses position:absolute and will not work properly with parent position:static (default)
$log.warn(ERROR_CSS_POSITION);
}
// Only inherit the parent if the backdrop has a parent.
$mdTheming.inherit(element, parent);
}
});
function resize() {
var viewportHeight = parseInt(bodyStyles.height, 10) + Math.abs(parseInt(bodyStyles.top, 10));
element.css('height', viewportHeight + 'px');
}
}
}]);
ngmaterial.components.backdrop = angular.module("material.components.backdrop");

View File

@ -0,0 +1,15 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-bottom-sheet.md-THEME_NAME-theme {
background-color: '{{background-50}}';
border-top-color: '{{background-300}}'; }
md-bottom-sheet.md-THEME_NAME-theme.md-list md-list-item {
color: '{{foreground-1}}'; }
md-bottom-sheet.md-THEME_NAME-theme .md-subheader {
background-color: '{{background-50}}'; }
md-bottom-sheet.md-THEME_NAME-theme .md-subheader {
color: '{{foreground-1}}'; }

View File

@ -0,0 +1,170 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-bottom-sheet {
position: absolute;
left: 0;
right: 0;
bottom: 0;
padding: 8px 16px 88px 16px;
z-index: 70;
border-top-width: 1px;
border-top-style: solid;
-webkit-transform: translate3d(0, 80px, 0);
transform: translate3d(0, 80px, 0);
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transition-property: -webkit-transform;
transition-property: -webkit-transform;
transition-property: transform;
transition-property: transform, -webkit-transform; }
md-bottom-sheet.md-has-header {
padding-top: 0; }
md-bottom-sheet.ng-enter {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0); }
md-bottom-sheet.ng-enter-active {
opacity: 1;
display: block;
-webkit-transform: translate3d(0, 80px, 0) !important;
transform: translate3d(0, 80px, 0) !important; }
md-bottom-sheet.ng-leave-active {
-webkit-transform: translate3d(0, 100%, 0) !important;
transform: translate3d(0, 100%, 0) !important;
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-bottom-sheet .md-subheader {
background-color: transparent;
font-family: Roboto, "Helvetica Neue", sans-serif;
line-height: 56px;
padding: 0;
white-space: nowrap; }
md-bottom-sheet md-inline-icon {
display: inline-block;
height: 24px;
width: 24px;
fill: #444; }
md-bottom-sheet md-list-item {
display: -webkit-box;
display: -webkit-flex;
display: flex;
outline: none; }
md-bottom-sheet md-list-item:hover {
cursor: pointer; }
md-bottom-sheet.md-list md-list-item {
padding: 0;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
height: 48px; }
md-bottom-sheet.md-grid {
padding-left: 24px;
padding-right: 24px;
padding-top: 0; }
md-bottom-sheet.md-grid md-list {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-transition: all 0.5s;
transition: all 0.5s;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center; }
md-bottom-sheet.md-grid md-list-item {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-transition: all 0.5s;
transition: all 0.5s;
height: 96px;
margin-top: 8px;
margin-bottom: 8px;
/* Mixin for how many grid items to show per row */ }
@media (max-width: 960px) {
md-bottom-sheet.md-grid md-list-item {
-webkit-box-flex: 1;
-webkit-flex: 1 1 33.33333%;
flex: 1 1 33.33333%;
max-width: 33.33333%; }
md-bottom-sheet.md-grid md-list-item:nth-of-type(3n + 1) {
-webkit-box-align: start;
-webkit-align-items: flex-start;
align-items: flex-start; }
md-bottom-sheet.md-grid md-list-item:nth-of-type(3n) {
-webkit-box-align: end;
-webkit-align-items: flex-end;
align-items: flex-end; } }
@media (min-width: 960px) and (max-width: 1279px) {
md-bottom-sheet.md-grid md-list-item {
-webkit-box-flex: 1;
-webkit-flex: 1 1 25%;
flex: 1 1 25%;
max-width: 25%; } }
@media (min-width: 1280px) and (max-width: 1919px) {
md-bottom-sheet.md-grid md-list-item {
-webkit-box-flex: 1;
-webkit-flex: 1 1 16.66667%;
flex: 1 1 16.66667%;
max-width: 16.66667%; } }
@media (min-width: 1920px) {
md-bottom-sheet.md-grid md-list-item {
-webkit-box-flex: 1;
-webkit-flex: 1 1 14.28571%;
flex: 1 1 14.28571%;
max-width: 14.28571%; } }
md-bottom-sheet.md-grid md-list-item::before {
display: none; }
md-bottom-sheet.md-grid md-list-item .md-list-item-content {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
width: 48px;
padding-bottom: 16px; }
md-bottom-sheet.md-grid md-list-item .md-grid-item-content {
border: 1px solid transparent;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
width: 80px; }
md-bottom-sheet.md-grid md-list-item .md-grid-text {
font-weight: 400;
line-height: 16px;
font-size: 13px;
margin: 0;
white-space: nowrap;
width: 64px;
text-align: center;
text-transform: none;
padding-top: 8px; }
@media screen and (-ms-high-contrast: active) {
md-bottom-sheet {
border: 1px solid #fff; } }

View File

@ -0,0 +1,332 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.bottomSheet');
goog.require('ngmaterial.components.backdrop');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.bottomSheet
* @description
* BottomSheet
*/
MdBottomSheetDirective['$inject'] = ["$mdBottomSheet"];
MdBottomSheetProvider['$inject'] = ["$$interimElementProvider"];
angular
.module('material.components.bottomSheet', [
'material.core',
'material.components.backdrop'
])
.directive('mdBottomSheet', MdBottomSheetDirective)
.provider('$mdBottomSheet', MdBottomSheetProvider);
/* ngInject */
function MdBottomSheetDirective($mdBottomSheet) {
return {
restrict: 'E',
link : function postLink(scope, element) {
element.addClass('_md'); // private md component indicator for styling
// When navigation force destroys an interimElement, then
// listen and $destroy() that interim instance...
scope.$on('$destroy', function() {
$mdBottomSheet.destroy();
});
}
};
}
/**
* @ngdoc service
* @name $mdBottomSheet
* @module material.components.bottomSheet
*
* @description
* `$mdBottomSheet` opens a bottom sheet over the app and provides a simple promise API.
*
* ## Restrictions
*
* - The bottom sheet's template must have an outer `<md-bottom-sheet>` element.
* - Add the `md-grid` class to the bottom sheet for a grid layout.
* - Add the `md-list` class to the bottom sheet for a list layout.
*
* @usage
* <hljs lang="html">
* <div ng-controller="MyController">
* <md-button ng-click="openBottomSheet()">
* Open a Bottom Sheet!
* </md-button>
* </div>
* </hljs>
* <hljs lang="js">
* var app = angular.module('app', ['ngMaterial']);
* app.controller('MyController', function($scope, $mdBottomSheet) {
* $scope.openBottomSheet = function() {
* $mdBottomSheet.show({
* template: '<md-bottom-sheet>' +
* 'Hello! <md-button ng-click="closeBottomSheet()">Close</md-button>' +
* '</md-bottom-sheet>'
* })
*
* // Fires when the hide() method is used
* .then(function() {
* console.log('You clicked the button to close the bottom sheet!');
* })
*
* // Fires when the cancel() method is used
* .catch(function() {
* console.log('You hit escape or clicked the backdrop to close.');
* });
* };
*
* $scope.closeBottomSheet = function($scope, $mdBottomSheet) {
* $mdBottomSheet.hide();
* }
*
* });
* </hljs>
*/
/**
* @ngdoc method
* @name $mdBottomSheet#show
*
* @description
* Show a bottom sheet with the specified options.
*
* <em><b>Note:</b> You should <b>always</b> provide a `.catch()` method in case the user hits the
* `esc` key or clicks the background to close. In this case, the `cancel()` method will
* automatically be called on the bottom sheet which will `reject()` the promise. See the @usage
* section above for an example.
*
* Newer versions of Angular will throw a `Possibly unhandled rejection` exception if you forget
* this.</em>
*
* @param {object} options 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 bottom sheet. Restrictions: the template must
* have an outer `md-bottom-sheet` element.
* - `template` - `{string=}`: Same as templateUrl, except this is an actual
* template string.
* - `scope` - `{object=}`: the scope to link the template / controller to. If none is specified, it will create a new child scope.
* This scope will be destroyed when the bottom sheet is removed unless `preserveScope` is set to true.
* - `preserveScope` - `{boolean=}`: whether to preserve the scope when the element is removed. Default is false
* - `controller` - `{string=}`: The controller to associate with this bottom sheet.
* - `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.
* - `clickOutsideToClose` - `{boolean=}`: Whether the user can click outside the bottom sheet to
* close it. Default true.
* - `bindToController` - `{boolean=}`: When set to true, the locals will be bound to the controller instance.
* - `disableBackdrop` - `{boolean=}`: When set to true, the bottomsheet will not show a backdrop.
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to close the bottom sheet.
* Default true.
* - `resolve` - `{object=}`: Similar to locals, except it takes promises as values
* and the bottom sheet 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 bottom sheet to. The `parent` may be a `function`, `string`,
* `object`, or null. Defaults to appending to the body of the root element (or the root element) of the application.
* e.g. angular.element(document.getElementById('content')) or "#content"
* - `disableParentScroll` - `{boolean=}`: Whether to disable scrolling while the bottom sheet is open.
* Default true.
*
* @returns {promise} A promise that can be resolved with `$mdBottomSheet.hide()` or
* rejected with `$mdBottomSheet.cancel()`.
*/
/**
* @ngdoc method
* @name $mdBottomSheet#hide
*
* @description
* Hide the existing bottom sheet and resolve the promise returned from
* `$mdBottomSheet.show()`. This call will close the most recently opened/current bottomsheet (if
* any).
*
* <em><b>Note:</b> Use a `.then()` on your `.show()` to handle this callback.</em>
*
* @param {*=} response An argument for the resolved promise.
*
*/
/**
* @ngdoc method
* @name $mdBottomSheet#cancel
*
* @description
* Hide the existing bottom sheet and reject the promise returned from
* `$mdBottomSheet.show()`.
*
* <em><b>Note:</b> Use a `.catch()` on your `.show()` to handle this callback.</em>
*
* @param {*=} response An argument for the rejected promise.
*
*/
function MdBottomSheetProvider($$interimElementProvider) {
// how fast we need to flick down to close the sheet, pixels/ms
bottomSheetDefaults['$inject'] = ["$animate", "$mdConstant", "$mdUtil", "$mdTheming", "$mdBottomSheet", "$rootElement", "$mdGesture", "$log"];
var CLOSING_VELOCITY = 0.5;
var PADDING = 80; // same as css
return $$interimElementProvider('$mdBottomSheet')
.setDefaults({
methods: ['disableParentScroll', 'escapeToClose', 'clickOutsideToClose'],
options: bottomSheetDefaults
});
/* ngInject */
function bottomSheetDefaults($animate, $mdConstant, $mdUtil, $mdTheming, $mdBottomSheet, $rootElement,
$mdGesture, $log) {
var backdrop;
return {
themable: true,
onShow: onShow,
onRemove: onRemove,
disableBackdrop: false,
escapeToClose: true,
clickOutsideToClose: true,
disableParentScroll: true
};
function onShow(scope, element, options, controller) {
element = $mdUtil.extractElementByName(element, 'md-bottom-sheet');
// prevent tab focus or click focus on the bottom-sheet container
element.attr('tabindex',"-1");
// Once the md-bottom-sheet has `ng-cloak` applied on his template the opening animation will not work properly.
// This is a very common problem, so we have to notify the developer about this.
if (element.hasClass('ng-cloak')) {
var message = '$mdBottomSheet: using `<md-bottom-sheet ng-cloak >` will affect the bottom-sheet opening animations.';
$log.warn( message, element[0] );
}
if (!options.disableBackdrop) {
// Add a backdrop that will close on click
backdrop = $mdUtil.createBackdrop(scope, "md-bottom-sheet-backdrop md-opaque");
// Prevent mouse focus on backdrop; ONLY programatic focus allowed.
// This allows clicks on backdrop to propogate to the $rootElement and
// ESC key events to be detected properly.
backdrop[0].tabIndex = -1;
if (options.clickOutsideToClose) {
backdrop.on('click', function() {
$mdUtil.nextTick($mdBottomSheet.cancel,true);
});
}
$mdTheming.inherit(backdrop, options.parent);
$animate.enter(backdrop, options.parent, null);
}
var bottomSheet = new BottomSheet(element, options.parent);
options.bottomSheet = bottomSheet;
$mdTheming.inherit(bottomSheet.element, options.parent);
if (options.disableParentScroll) {
options.restoreScroll = $mdUtil.disableScrollAround(bottomSheet.element, options.parent);
}
return $animate.enter(bottomSheet.element, options.parent, backdrop)
.then(function() {
var focusable = $mdUtil.findFocusTarget(element) || angular.element(
element[0].querySelector('button') ||
element[0].querySelector('a') ||
element[0].querySelector($mdUtil.prefixer('ng-click', true))
) || backdrop;
if (options.escapeToClose) {
options.rootElementKeyupCallback = function(e) {
if (e.keyCode === $mdConstant.KEY_CODE.ESCAPE) {
$mdUtil.nextTick($mdBottomSheet.cancel,true);
}
};
$rootElement.on('keyup', options.rootElementKeyupCallback);
focusable && focusable.focus();
}
});
}
function onRemove(scope, element, options) {
var bottomSheet = options.bottomSheet;
if (!options.disableBackdrop) $animate.leave(backdrop);
return $animate.leave(bottomSheet.element).then(function() {
if (options.disableParentScroll) {
options.restoreScroll();
delete options.restoreScroll;
}
bottomSheet.cleanup();
});
}
/**
* BottomSheet class to apply bottom-sheet behavior to an element
*/
function BottomSheet(element, parent) {
var deregister = $mdGesture.register(parent, 'drag', { horizontal: false });
parent.on('$md.dragstart', onDragStart)
.on('$md.drag', onDrag)
.on('$md.dragend', onDragEnd);
return {
element: element,
cleanup: function cleanup() {
deregister();
parent.off('$md.dragstart', onDragStart);
parent.off('$md.drag', onDrag);
parent.off('$md.dragend', onDragEnd);
}
};
function onDragStart(ev) {
// Disable transitions on transform so that it feels fast
element.css($mdConstant.CSS.TRANSITION_DURATION, '0ms');
}
function onDrag(ev) {
var transform = ev.pointer.distanceY;
if (transform < 5) {
// Slow down drag when trying to drag up, and stop after PADDING
transform = Math.max(-PADDING, transform / 2);
}
element.css($mdConstant.CSS.TRANSFORM, 'translate3d(0,' + (PADDING + transform) + 'px,0)');
}
function onDragEnd(ev) {
if (ev.pointer.distanceY > 0 &&
(ev.pointer.distanceY > 20 || Math.abs(ev.pointer.velocityY) > CLOSING_VELOCITY)) {
var distanceRemaining = element.prop('offsetHeight') - ev.pointer.distanceY;
var transitionDuration = Math.min(distanceRemaining / ev.pointer.velocityY * 0.75, 500);
element.css($mdConstant.CSS.TRANSITION_DURATION, transitionDuration + 'ms');
$mdUtil.nextTick($mdBottomSheet.cancel,true);
} else {
element.css($mdConstant.CSS.TRANSITION_DURATION, '');
element.css($mdConstant.CSS.TRANSFORM, '');
}
}
}
}
}
ngmaterial.components.bottomSheet = angular.module("material.components.bottomSheet");

View File

@ -0,0 +1,113 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
.md-button.md-THEME_NAME-theme:not([disabled]):hover {
background-color: '{{background-500-0.2}}'; }
.md-button.md-THEME_NAME-theme:not([disabled]).md-focused {
background-color: '{{background-500-0.2}}'; }
.md-button.md-THEME_NAME-theme:not([disabled]).md-icon-button:hover {
background-color: transparent; }
.md-button.md-THEME_NAME-theme.md-fab {
background-color: '{{accent-color}}';
color: '{{accent-contrast}}'; }
.md-button.md-THEME_NAME-theme.md-fab md-icon {
color: '{{accent-contrast}}'; }
.md-button.md-THEME_NAME-theme.md-fab:not([disabled]):hover {
background-color: '{{accent-A700}}'; }
.md-button.md-THEME_NAME-theme.md-fab:not([disabled]).md-focused {
background-color: '{{accent-A700}}'; }
.md-button.md-THEME_NAME-theme.md-primary {
color: '{{primary-color}}'; }
.md-button.md-THEME_NAME-theme.md-primary.md-raised, .md-button.md-THEME_NAME-theme.md-primary.md-fab {
color: '{{primary-contrast}}';
background-color: '{{primary-color}}'; }
.md-button.md-THEME_NAME-theme.md-primary.md-raised:not([disabled]) md-icon, .md-button.md-THEME_NAME-theme.md-primary.md-fab:not([disabled]) md-icon {
color: '{{primary-contrast}}'; }
.md-button.md-THEME_NAME-theme.md-primary.md-raised:not([disabled]):hover, .md-button.md-THEME_NAME-theme.md-primary.md-fab:not([disabled]):hover {
background-color: '{{primary-600}}'; }
.md-button.md-THEME_NAME-theme.md-primary.md-raised:not([disabled]).md-focused, .md-button.md-THEME_NAME-theme.md-primary.md-fab:not([disabled]).md-focused {
background-color: '{{primary-600}}'; }
.md-button.md-THEME_NAME-theme.md-primary:not([disabled]) md-icon {
color: '{{primary-color}}'; }
.md-button.md-THEME_NAME-theme.md-fab {
background-color: '{{accent-color}}';
color: '{{accent-contrast}}'; }
.md-button.md-THEME_NAME-theme.md-fab:not([disabled]) .md-icon {
color: '{{accent-contrast}}'; }
.md-button.md-THEME_NAME-theme.md-fab:not([disabled]):hover {
background-color: '{{accent-A700}}'; }
.md-button.md-THEME_NAME-theme.md-fab:not([disabled]).md-focused {
background-color: '{{accent-A700}}'; }
.md-button.md-THEME_NAME-theme.md-raised {
color: '{{background-900}}';
background-color: '{{background-50}}'; }
.md-button.md-THEME_NAME-theme.md-raised:not([disabled]) md-icon {
color: '{{background-900}}'; }
.md-button.md-THEME_NAME-theme.md-raised:not([disabled]):hover {
background-color: '{{background-50}}'; }
.md-button.md-THEME_NAME-theme.md-raised:not([disabled]).md-focused {
background-color: '{{background-200}}'; }
.md-button.md-THEME_NAME-theme.md-warn {
color: '{{warn-color}}'; }
.md-button.md-THEME_NAME-theme.md-warn.md-raised, .md-button.md-THEME_NAME-theme.md-warn.md-fab {
color: '{{warn-contrast}}';
background-color: '{{warn-color}}'; }
.md-button.md-THEME_NAME-theme.md-warn.md-raised:not([disabled]) md-icon, .md-button.md-THEME_NAME-theme.md-warn.md-fab:not([disabled]) md-icon {
color: '{{warn-contrast}}'; }
.md-button.md-THEME_NAME-theme.md-warn.md-raised:not([disabled]):hover, .md-button.md-THEME_NAME-theme.md-warn.md-fab:not([disabled]):hover {
background-color: '{{warn-600}}'; }
.md-button.md-THEME_NAME-theme.md-warn.md-raised:not([disabled]).md-focused, .md-button.md-THEME_NAME-theme.md-warn.md-fab:not([disabled]).md-focused {
background-color: '{{warn-600}}'; }
.md-button.md-THEME_NAME-theme.md-warn:not([disabled]) md-icon {
color: '{{warn-color}}'; }
.md-button.md-THEME_NAME-theme.md-accent {
color: '{{accent-color}}'; }
.md-button.md-THEME_NAME-theme.md-accent.md-raised, .md-button.md-THEME_NAME-theme.md-accent.md-fab {
color: '{{accent-contrast}}';
background-color: '{{accent-color}}'; }
.md-button.md-THEME_NAME-theme.md-accent.md-raised:not([disabled]) md-icon, .md-button.md-THEME_NAME-theme.md-accent.md-fab:not([disabled]) md-icon {
color: '{{accent-contrast}}'; }
.md-button.md-THEME_NAME-theme.md-accent.md-raised:not([disabled]):hover, .md-button.md-THEME_NAME-theme.md-accent.md-fab:not([disabled]):hover {
background-color: '{{accent-A700}}'; }
.md-button.md-THEME_NAME-theme.md-accent.md-raised:not([disabled]).md-focused, .md-button.md-THEME_NAME-theme.md-accent.md-fab:not([disabled]).md-focused {
background-color: '{{accent-A700}}'; }
.md-button.md-THEME_NAME-theme.md-accent:not([disabled]) md-icon {
color: '{{accent-color}}'; }
.md-button.md-THEME_NAME-theme[disabled], .md-button.md-THEME_NAME-theme.md-raised[disabled], .md-button.md-THEME_NAME-theme.md-fab[disabled], .md-button.md-THEME_NAME-theme.md-accent[disabled], .md-button.md-THEME_NAME-theme.md-warn[disabled] {
color: '{{foreground-3}}';
cursor: default; }
.md-button.md-THEME_NAME-theme[disabled] md-icon, .md-button.md-THEME_NAME-theme.md-raised[disabled] md-icon, .md-button.md-THEME_NAME-theme.md-fab[disabled] md-icon, .md-button.md-THEME_NAME-theme.md-accent[disabled] md-icon, .md-button.md-THEME_NAME-theme.md-warn[disabled] md-icon {
color: '{{foreground-3}}'; }
.md-button.md-THEME_NAME-theme.md-raised[disabled], .md-button.md-THEME_NAME-theme.md-fab[disabled] {
background-color: '{{foreground-4}}'; }
.md-button.md-THEME_NAME-theme[disabled] {
background-color: transparent; }
._md a.md-THEME_NAME-theme:not(.md-button).md-primary {
color: '{{primary-color}}'; }
._md a.md-THEME_NAME-theme:not(.md-button).md-primary:hover {
color: '{{primary-700}}'; }
._md a.md-THEME_NAME-theme:not(.md-button).md-accent {
color: '{{accent-color}}'; }
._md a.md-THEME_NAME-theme:not(.md-button).md-accent:hover {
color: '{{accent-A700}}'; }
._md a.md-THEME_NAME-theme:not(.md-button).md-warn {
color: '{{warn-color}}'; }
._md a.md-THEME_NAME-theme:not(.md-button).md-warn:hover {
color: '{{warn-700}}'; }

View File

@ -0,0 +1,205 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
button.md-button::-moz-focus-inner {
border: 0; }
.md-button {
display: inline-block;
position: relative;
cursor: pointer;
/** Alignment adjustments */
min-height: 36px;
min-width: 88px;
line-height: 36px;
vertical-align: middle;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
text-align: center;
border-radius: 2px;
box-sizing: border-box;
/* Reset default button appearance */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
outline: none;
border: 0;
/** Custom styling for button */
padding: 0 6px;
margin: 6px 8px;
background: transparent;
color: currentColor;
white-space: nowrap;
/* Uppercase text content */
text-transform: uppercase;
font-weight: 500;
font-size: 14px;
font-style: inherit;
font-variant: inherit;
font-family: inherit;
text-decoration: none;
overflow: hidden;
-webkit-transition: box-shadow 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), background-color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: box-shadow 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), background-color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); }
.md-dense > .md-button:not(.md-dense-disabled),
.md-dense :not(.md-dense-disabled) .md-button:not(.md-dense-disabled) {
min-height: 32px; }
.md-dense > .md-button:not(.md-dense-disabled),
.md-dense :not(.md-dense-disabled) .md-button:not(.md-dense-disabled) {
line-height: 32px; }
.md-dense > .md-button:not(.md-dense-disabled),
.md-dense :not(.md-dense-disabled) .md-button:not(.md-dense-disabled) {
font-size: 13px; }
.md-button:focus {
outline: none; }
.md-button:hover, .md-button:focus {
text-decoration: none; }
.md-button.ng-hide, .md-button.ng-leave {
-webkit-transition: none;
transition: none; }
.md-button.md-cornered {
border-radius: 0; }
.md-button.md-icon {
padding: 0;
background: none; }
.md-button.md-raised:not([disabled]) {
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); }
.md-button.md-icon-button {
margin: 0 6px;
height: 40px;
min-width: 0;
line-height: 24px;
padding: 8px;
width: 40px;
border-radius: 50%; }
.md-button.md-icon-button .md-ripple-container {
border-radius: 50%;
background-clip: padding-box;
overflow: hidden;
-webkit-mask-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC"); }
.md-button.md-fab {
z-index: 20;
line-height: 56px;
min-width: 0;
width: 56px;
height: 56px;
vertical-align: middle;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
border-radius: 50%;
background-clip: padding-box;
overflow: hidden;
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
-webkit-transition-property: background-color, box-shadow, -webkit-transform;
transition-property: background-color, box-shadow, -webkit-transform;
transition-property: background-color, box-shadow, transform;
transition-property: background-color, box-shadow, transform, -webkit-transform; }
.md-button.md-fab.md-fab-bottom-right {
top: auto;
right: 20px;
bottom: 20px;
left: auto;
position: absolute; }
.md-button.md-fab.md-fab-bottom-left {
top: auto;
right: auto;
bottom: 20px;
left: 20px;
position: absolute; }
.md-button.md-fab.md-fab-top-right {
top: 20px;
right: 20px;
bottom: auto;
left: auto;
position: absolute; }
.md-button.md-fab.md-fab-top-left {
top: 20px;
right: auto;
bottom: auto;
left: 20px;
position: absolute; }
.md-button.md-fab .md-ripple-container {
border-radius: 50%;
background-clip: padding-box;
overflow: hidden;
-webkit-mask-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC"); }
.md-button.md-fab.md-mini {
line-height: 40px;
width: 40px;
height: 40px; }
.md-button.md-fab.ng-hide, .md-button.md-fab.ng-leave {
-webkit-transition: none;
transition: none; }
.md-button:not([disabled]).md-raised.md-focused, .md-button:not([disabled]).md-fab.md-focused {
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); }
.md-button:not([disabled]).md-raised:active, .md-button:not([disabled]).md-fab:active {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4); }
.md-button .md-ripple-container {
border-radius: 2px;
background-clip: padding-box;
overflow: hidden;
-webkit-mask-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC"); }
.md-button.md-icon-button md-icon,
button.md-button.md-fab md-icon {
display: block; }
.md-toast-open-top .md-button.md-fab-top-left,
.md-toast-open-top .md-button.md-fab-top-right {
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transform: translate3d(0, 42px, 0);
transform: translate3d(0, 42px, 0); }
.md-toast-open-top .md-button.md-fab-top-left:not([disabled]).md-focused, .md-toast-open-top .md-button.md-fab-top-left:not([disabled]):hover,
.md-toast-open-top .md-button.md-fab-top-right:not([disabled]).md-focused,
.md-toast-open-top .md-button.md-fab-top-right:not([disabled]):hover {
-webkit-transform: translate3d(0, 41px, 0);
transform: translate3d(0, 41px, 0); }
.md-toast-open-bottom .md-button.md-fab-bottom-left,
.md-toast-open-bottom .md-button.md-fab-bottom-right {
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transform: translate3d(0, -42px, 0);
transform: translate3d(0, -42px, 0); }
.md-toast-open-bottom .md-button.md-fab-bottom-left:not([disabled]).md-focused, .md-toast-open-bottom .md-button.md-fab-bottom-left:not([disabled]):hover,
.md-toast-open-bottom .md-button.md-fab-bottom-right:not([disabled]).md-focused,
.md-toast-open-bottom .md-button.md-fab-bottom-right:not([disabled]):hover {
-webkit-transform: translate3d(0, -43px, 0);
transform: translate3d(0, -43px, 0); }
.md-button-group {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
width: 100%; }
.md-button-group > .md-button {
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
display: block;
overflow: hidden;
width: 0;
border-width: 1px 0px 1px 1px;
border-radius: 0;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap; }
.md-button-group > .md-button:first-child {
border-radius: 2px 0px 0px 2px; }
.md-button-group > .md-button:last-child {
border-right-width: 1px;
border-radius: 0px 2px 2px 0px; }
@media screen and (-ms-high-contrast: active) {
.md-button.md-raised,
.md-button.md-fab {
border: 1px solid #fff; } }

View File

@ -0,0 +1,194 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.button');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.button
* @description
*
* Button
*/
MdButtonDirective['$inject'] = ["$mdButtonInkRipple", "$mdTheming", "$mdAria", "$mdInteraction"];
MdAnchorDirective['$inject'] = ["$mdTheming"];
angular
.module('material.components.button', [ 'material.core' ])
.directive('mdButton', MdButtonDirective)
.directive('a', MdAnchorDirective);
/**
* @private
* @restrict E
*
* @description
* `a` is an anchor directive used to inherit theme colors for md-primary, md-accent, etc.
*
* @usage
*
* <hljs lang="html">
* <md-content md-theme="myTheme">
* <a href="#chapter1" class="md-accent"></a>
* </md-content>
* </hljs>
*/
function MdAnchorDirective($mdTheming) {
return {
restrict : 'E',
link : function postLink(scope, element) {
// Make sure to inherit theme so stand-alone anchors
// support theme colors for md-primary, md-accent, etc.
$mdTheming(element);
}
};
}
/**
* @ngdoc directive
* @name mdButton
* @module material.components.button
*
* @restrict E
*
* @description
* `<md-button>` is a button directive with optional ink ripples (default enabled).
*
* If you supply a `href` or `ng-href` attribute, it will become an `<a>` element. Otherwise, it
* will become a `<button>` element. As per the
* [Material Design specifications](https://material.google.com/style/color.html#color-color-palette)
* the FAB button background is filled with the accent color [by default]. The primary color palette
* may be used with the `md-primary` class.
*
* Developers can also change the color palette of the button, by using the following classes
* - `md-primary`
* - `md-accent`
* - `md-warn`
*
* See for example
*
* <hljs lang="html">
* <md-button class="md-primary">Primary Button</md-button>
* </hljs>
*
* Button can be also raised, which means that they will use the current color palette to fill the button.
*
* <hljs lang="html">
* <md-button class="md-accent md-raised">Raised and Accent Button</md-button>
* </hljs>
*
* It is also possible to disable the focus effect on the button, by using the following markup.
*
* <hljs lang="html">
* <md-button class="md-no-focus">No Focus Style</md-button>
* </hljs>
*
* @param {boolean=} md-no-ink If present, disable ripple ink effects.
* @param {expression=} ng-disabled En/Disable based on the expression
* @param {string=} md-ripple-size Overrides the default ripple size logic. Options: `full`, `partial`, `auto`
* @param {string=} aria-label Adds alternative text to button for accessibility, useful for icon buttons.
* If no default text is found, a warning will be logged.
*
* @usage
*
* Regular buttons:
*
* <hljs lang="html">
* <md-button> Flat Button </md-button>
* <md-button href="http://google.com"> Flat link </md-button>
* <md-button class="md-raised"> Raised Button </md-button>
* <md-button ng-disabled="true"> Disabled Button </md-button>
* <md-button>
* <md-icon md-svg-src="your/icon.svg"></md-icon>
* Register Now
* </md-button>
* </hljs>
*
* FAB buttons:
*
* <hljs lang="html">
* <md-button class="md-fab" aria-label="FAB">
* <md-icon md-svg-src="your/icon.svg"></md-icon>
* </md-button>
* <!-- mini-FAB -->
* <md-button class="md-fab md-mini" aria-label="Mini FAB">
* <md-icon md-svg-src="your/icon.svg"></md-icon>
* </md-button>
* <!-- Button with SVG Icon -->
* <md-button class="md-icon-button" aria-label="Custom Icon Button">
* <md-icon md-svg-icon="path/to/your.svg"></md-icon>
* </md-button>
* </hljs>
*/
function MdButtonDirective($mdButtonInkRipple, $mdTheming, $mdAria, $mdInteraction) {
return {
restrict: 'EA',
replace: true,
transclude: true,
template: getTemplate,
link: postLink
};
function isAnchor(attr) {
return angular.isDefined(attr.href) || angular.isDefined(attr.ngHref) || angular.isDefined(attr.ngLink) || angular.isDefined(attr.uiSref);
}
function getTemplate(element, attr) {
if (isAnchor(attr)) {
return '<a class="md-button" ng-transclude></a>';
} else {
//If buttons don't have type="button", they will submit forms automatically.
var btnType = (typeof attr.type === 'undefined') ? 'button' : attr.type;
return '<button class="md-button" type="' + btnType + '" ng-transclude></button>';
}
}
function postLink(scope, element, attr) {
$mdTheming(element);
$mdButtonInkRipple.attach(scope, element);
// Use async expect to support possible bindings in the button label
$mdAria.expectWithoutText(element, 'aria-label');
// For anchor elements, we have to set tabindex manually when the
// element is disabled
if (isAnchor(attr) && angular.isDefined(attr.ngDisabled) ) {
scope.$watch(attr.ngDisabled, function(isDisabled) {
element.attr('tabindex', isDisabled ? -1 : 0);
});
}
// disabling click event when disabled is true
element.on('click', function(e){
if (attr.disabled === true) {
e.preventDefault();
e.stopImmediatePropagation();
}
});
if (!element.hasClass('md-no-focus')) {
element.on('focus', function() {
// Only show the focus effect when being focused through keyboard interaction or programmatically
if (!$mdInteraction.isUserInvoked() || $mdInteraction.getLastInteractionType() === 'keyboard') {
element.addClass('md-focused');
}
});
element.on('blur', function() {
element.removeClass('md-focused');
});
}
}
}
ngmaterial.components.button = angular.module("material.components.button");

View File

@ -0,0 +1,19 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-card.md-THEME_NAME-theme {
color: '{{foreground-1}}';
background-color: '{{background-hue-1}}';
border-radius: 2px; }
md-card.md-THEME_NAME-theme .md-card-image {
border-radius: 2px 2px 0 0; }
md-card.md-THEME_NAME-theme md-card-header md-card-avatar md-icon {
color: '{{background-color}}';
background-color: '{{foreground-3}}'; }
md-card.md-THEME_NAME-theme md-card-header md-card-header-text .md-subhead {
color: '{{foreground-2}}'; }
md-card.md-THEME_NAME-theme md-card-title md-card-title-text:not(:only-child) .md-subhead {
color: '{{foreground-2}}'; }

View File

@ -0,0 +1,202 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-card {
box-sizing: border-box;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
margin: 8px;
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 2px 1px -1px rgba(0, 0, 0, 0.12); }
md-card md-card-header {
padding: 16px;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
md-card md-card-header:first-child md-card-avatar {
margin-right: 12px; }
[dir=rtl] md-card md-card-header:first-child md-card-avatar {
margin-right: auto;
margin-left: 12px; }
md-card md-card-header:last-child md-card-avatar {
margin-left: 12px; }
[dir=rtl] md-card md-card-header:last-child md-card-avatar {
margin-left: auto;
margin-right: 12px; }
md-card md-card-header md-card-avatar {
width: 40px;
height: 40px; }
md-card md-card-header md-card-avatar .md-user-avatar,
md-card md-card-header md-card-avatar md-icon {
border-radius: 50%; }
md-card md-card-header md-card-avatar md-icon {
padding: 8px; }
md-card md-card-header md-card-avatar md-icon > svg {
height: inherit;
width: inherit; }
md-card md-card-header md-card-avatar + md-card-header-text {
max-height: 40px; }
md-card md-card-header md-card-avatar + md-card-header-text .md-title {
font-size: 14px; }
md-card md-card-header md-card-header-text {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column; }
md-card md-card-header md-card-header-text .md-subhead {
font-size: 14px; }
md-card > img,
md-card > md-card-header img,
md-card md-card-title-media img {
box-sizing: border-box;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-flex: 0;
-webkit-flex: 0 0 auto;
flex: 0 0 auto;
width: 100%;
height: auto; }
md-card md-card-title {
padding: 24px 16px 16px;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
md-card md-card-title + md-card-content {
padding-top: 0; }
md-card md-card-title md-card-title-text {
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
display: -webkit-box;
display: -webkit-flex;
display: flex; }
md-card md-card-title md-card-title-text .md-subhead {
padding-top: 0;
font-size: 14px; }
md-card md-card-title md-card-title-text:only-child .md-subhead {
padding-top: 12px; }
md-card md-card-title md-card-title-media {
margin-top: -8px; }
md-card md-card-title md-card-title-media .md-media-sm {
height: 80px;
width: 80px; }
md-card md-card-title md-card-title-media .md-media-md {
height: 112px;
width: 112px; }
md-card md-card-title md-card-title-media .md-media-lg {
height: 152px;
width: 152px; }
md-card md-card-content {
display: block;
padding: 16px; }
md-card md-card-content > p:first-child {
margin-top: 0; }
md-card md-card-content > p:last-child {
margin-bottom: 0; }
md-card md-card-content .md-media-xl {
height: 240px;
width: 240px; }
md-card .md-actions, md-card md-card-actions {
margin: 8px; }
md-card .md-actions.layout-column .md-button:not(.md-icon-button), md-card md-card-actions.layout-column .md-button:not(.md-icon-button) {
margin: 2px 0; }
md-card .md-actions.layout-column .md-button:not(.md-icon-button):first-of-type, md-card md-card-actions.layout-column .md-button:not(.md-icon-button):first-of-type {
margin-top: 0; }
md-card .md-actions.layout-column .md-button:not(.md-icon-button):last-of-type, md-card md-card-actions.layout-column .md-button:not(.md-icon-button):last-of-type {
margin-bottom: 0; }
md-card .md-actions.layout-column .md-button.md-icon-button, md-card md-card-actions.layout-column .md-button.md-icon-button {
margin-top: 6px;
margin-bottom: 6px; }
md-card .md-actions md-card-icon-actions, md-card md-card-actions md-card-icon-actions {
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
md-card .md-actions:not(.layout-column) .md-button:not(.md-icon-button), md-card md-card-actions:not(.layout-column) .md-button:not(.md-icon-button) {
margin: 0 4px; }
md-card .md-actions:not(.layout-column) .md-button:not(.md-icon-button):first-of-type, md-card md-card-actions:not(.layout-column) .md-button:not(.md-icon-button):first-of-type {
margin-left: 0; }
[dir=rtl] md-card .md-actions:not(.layout-column) .md-button:not(.md-icon-button):first-of-type, [dir=rtl] md-card md-card-actions:not(.layout-column) .md-button:not(.md-icon-button):first-of-type {
margin-left: auto;
margin-right: 0; }
md-card .md-actions:not(.layout-column) .md-button:not(.md-icon-button):last-of-type, md-card md-card-actions:not(.layout-column) .md-button:not(.md-icon-button):last-of-type {
margin-right: 0; }
[dir=rtl] md-card .md-actions:not(.layout-column) .md-button:not(.md-icon-button):last-of-type, [dir=rtl] md-card md-card-actions:not(.layout-column) .md-button:not(.md-icon-button):last-of-type {
margin-right: auto;
margin-left: 0; }
md-card .md-actions:not(.layout-column) .md-button.md-icon-button, md-card md-card-actions:not(.layout-column) .md-button.md-icon-button {
margin-left: 6px;
margin-right: 6px; }
md-card .md-actions:not(.layout-column) .md-button.md-icon-button:first-of-type, md-card md-card-actions:not(.layout-column) .md-button.md-icon-button:first-of-type {
margin-left: 12px; }
[dir=rtl] md-card .md-actions:not(.layout-column) .md-button.md-icon-button:first-of-type, [dir=rtl] md-card md-card-actions:not(.layout-column) .md-button.md-icon-button:first-of-type {
margin-left: auto;
margin-right: 12px; }
md-card .md-actions:not(.layout-column) .md-button.md-icon-button:last-of-type, md-card md-card-actions:not(.layout-column) .md-button.md-icon-button:last-of-type {
margin-right: 12px; }
[dir=rtl] md-card .md-actions:not(.layout-column) .md-button.md-icon-button:last-of-type, [dir=rtl] md-card md-card-actions:not(.layout-column) .md-button.md-icon-button:last-of-type {
margin-right: auto;
margin-left: 12px; }
md-card .md-actions:not(.layout-column) .md-button + md-card-icon-actions, md-card md-card-actions:not(.layout-column) .md-button + md-card-icon-actions {
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
-webkit-box-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
md-card md-card-footer {
margin-top: auto;
padding: 16px; }
@media screen and (-ms-high-contrast: active) {
md-card {
border: 1px solid #fff; } }
.md-image-no-fill > img {
width: auto;
height: auto; }

View File

@ -0,0 +1,142 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.card');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.card
*
* @description
* Card components.
*/
mdCardDirective['$inject'] = ["$mdTheming"];
angular.module('material.components.card', [
'material.core'
])
.directive('mdCard', mdCardDirective);
/**
* @ngdoc directive
* @name mdCard
* @module material.components.card
*
* @restrict E
*
* @description
* The `<md-card>` directive is a container element used within `<md-content>` containers.
*
* An image included as a direct descendant will fill the card's width. If you want to avoid this,
* you can add the `md-image-no-fill` class to the parent element. The `<md-card-content>`
* container will wrap text content and provide padding. An `<md-card-footer>` element can be
* optionally included to put content flush against the bottom edge of the card.
*
* Action buttons can be included in an `<md-card-actions>` element, similar to `<md-dialog-actions>`.
* You can then position buttons using layout attributes.
*
* Card is built with:
* * `<md-card-header>` - Header for the card, holds avatar, text and squared image
* - `<md-card-avatar>` - Card avatar
* - `md-user-avatar` - Class for user image
* - `<md-icon>`
* - `<md-card-header-text>` - Contains elements for the card description
* - `md-title` - Class for the card title
* - `md-subhead` - Class for the card sub header
* * `<img>` - Image for the card
* * `<md-card-title>` - Card content title
* - `<md-card-title-text>`
* - `md-headline` - Class for the card content title
* - `md-subhead` - Class for the card content sub header
* - `<md-card-title-media>` - Squared image within the title
* - `md-media-sm` - Class for small image
* - `md-media-md` - Class for medium image
* - `md-media-lg` - Class for large image
* - `md-media-xl` - Class for extra large image
* * `<md-card-content>` - Card content
* * `<md-card-actions>` - Card actions
* - `<md-card-icon-actions>` - Icon actions
*
* Cards have constant width and variable heights; where the maximum height is limited to what can
* fit within a single view on a platform, but it can temporarily expand as needed.
*
* @usage
* ### Card with optional footer
* <hljs lang="html">
* <md-card>
* <img src="card-image.png" class="md-card-image" alt="image caption">
* <md-card-content>
* <h2>Card headline</h2>
* <p>Card content</p>
* </md-card-content>
* <md-card-footer>
* Card footer
* </md-card-footer>
* </md-card>
* </hljs>
*
* ### Card with actions
* <hljs lang="html">
* <md-card>
* <img src="card-image.png" class="md-card-image" alt="image caption">
* <md-card-content>
* <h2>Card headline</h2>
* <p>Card content</p>
* </md-card-content>
* <md-card-actions layout="row" layout-align="end center">
* <md-button>Action 1</md-button>
* <md-button>Action 2</md-button>
* </md-card-actions>
* </md-card>
* </hljs>
*
* ### Card with header, image, title actions and content
* <hljs lang="html">
* <md-card>
* <md-card-header>
* <md-card-avatar>
* <img class="md-user-avatar" src="avatar.png"/>
* </md-card-avatar>
* <md-card-header-text>
* <span class="md-title">Title</span>
* <span class="md-subhead">Sub header</span>
* </md-card-header-text>
* </md-card-header>
* <img ng-src="card-image.png" class="md-card-image" alt="image caption">
* <md-card-title>
* <md-card-title-text>
* <span class="md-headline">Card headline</span>
* <span class="md-subhead">Card subheader</span>
* </md-card-title-text>
* </md-card-title>
* <md-card-actions layout="row" layout-align="start center">
* <md-button>Action 1</md-button>
* <md-button>Action 2</md-button>
* <md-card-icon-actions>
* <md-button class="md-icon-button" aria-label="icon">
* <md-icon md-svg-icon="icon"></md-icon>
* </md-button>
* </md-card-icon-actions>
* </md-card-actions>
* <md-card-content>
* <p>
* Card content
* </p>
* </md-card-content>
* </md-card>
* </hljs>
*/
function mdCardDirective($mdTheming) {
return {
restrict: 'E',
link: function ($scope, $element, attr) {
$element.addClass('_md'); // private md component indicator for styling
$mdTheming($element);
}
};
}
ngmaterial.components.card = angular.module("material.components.card");

View File

@ -0,0 +1,92 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-checkbox.md-THEME_NAME-theme .md-ripple {
color: '{{accent-A700}}'; }
md-checkbox.md-THEME_NAME-theme.md-checked .md-ripple {
color: '{{background-600}}'; }
md-checkbox.md-THEME_NAME-theme.md-checked.md-focused .md-container:before {
background-color: '{{accent-color-0.26}}'; }
md-checkbox.md-THEME_NAME-theme .md-ink-ripple {
color: '{{foreground-2}}'; }
md-checkbox.md-THEME_NAME-theme.md-checked .md-ink-ripple {
color: '{{accent-color-0.87}}'; }
md-checkbox.md-THEME_NAME-theme:not(.md-checked) .md-icon {
border-color: '{{foreground-2}}'; }
md-checkbox.md-THEME_NAME-theme.md-checked .md-icon {
background-color: '{{accent-color-0.87}}'; }
md-checkbox.md-THEME_NAME-theme.md-checked .md-icon:after {
border-color: '{{accent-contrast-0.87}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary .md-ripple {
color: '{{primary-600}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-ripple {
color: '{{background-600}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary .md-ink-ripple {
color: '{{foreground-2}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-ink-ripple {
color: '{{primary-color-0.87}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary:not(.md-checked) .md-icon {
border-color: '{{foreground-2}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-icon {
background-color: '{{primary-color-0.87}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked.md-focused .md-container:before {
background-color: '{{primary-color-0.26}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-icon:after {
border-color: '{{primary-contrast-0.87}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary .md-indeterminate[disabled] .md-container {
color: '{{foreground-3}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn .md-ripple {
color: '{{warn-600}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn .md-ink-ripple {
color: '{{foreground-2}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-ink-ripple {
color: '{{warn-color-0.87}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn:not(.md-checked) .md-icon {
border-color: '{{foreground-2}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-icon {
background-color: '{{warn-color-0.87}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before {
background-color: '{{warn-color-0.26}}'; }
md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-icon:after {
border-color: '{{background-200}}'; }
md-checkbox.md-THEME_NAME-theme[disabled]:not(.md-checked) .md-icon {
border-color: '{{foreground-3}}'; }
md-checkbox.md-THEME_NAME-theme[disabled].md-checked .md-icon {
background-color: '{{foreground-3}}'; }
md-checkbox.md-THEME_NAME-theme[disabled].md-checked .md-icon:after {
border-color: '{{background-200}}'; }
md-checkbox.md-THEME_NAME-theme[disabled] .md-icon:after {
border-color: '{{foreground-3}}'; }
md-checkbox.md-THEME_NAME-theme[disabled] .md-label {
color: '{{foreground-3}}'; }

View File

@ -0,0 +1,150 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
.md-inline-form md-checkbox {
margin: 19px 0 18px; }
md-checkbox {
box-sizing: border-box;
display: inline-block;
margin-bottom: 16px;
white-space: nowrap;
cursor: pointer;
outline: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
position: relative;
min-width: 20px;
min-height: 20px;
margin-left: 0;
margin-right: 16px; }
[dir=rtl] md-checkbox {
margin-left: 16px; }
[dir=rtl] md-checkbox {
margin-right: 0; }
md-checkbox:last-of-type {
margin-left: 0;
margin-right: 0; }
md-checkbox.md-focused:not([disabled]) .md-container:before {
left: -8px;
top: -8px;
right: -8px;
bottom: -8px; }
md-checkbox.md-focused:not([disabled]):not(.md-checked) .md-container:before {
background-color: rgba(0, 0, 0, 0.12); }
md-checkbox.md-align-top-left > div.md-container {
top: 12px; }
md-checkbox .md-container {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
box-sizing: border-box;
display: inline-block;
width: 20px;
height: 20px;
left: 0;
right: auto; }
[dir=rtl] md-checkbox .md-container {
left: auto; }
[dir=rtl] md-checkbox .md-container {
right: 0; }
md-checkbox .md-container:before {
box-sizing: border-box;
background-color: transparent;
border-radius: 50%;
content: '';
position: absolute;
display: block;
height: auto;
left: 0;
top: 0;
right: 0;
bottom: 0;
-webkit-transition: all 0.5s;
transition: all 0.5s;
width: auto; }
md-checkbox .md-container:after {
box-sizing: border-box;
content: '';
position: absolute;
top: -10px;
right: -10px;
bottom: -10px;
left: -10px; }
md-checkbox .md-container .md-ripple-container {
position: absolute;
display: block;
width: auto;
height: auto;
left: -15px;
top: -15px;
right: -15px;
bottom: -15px; }
md-checkbox .md-icon {
box-sizing: border-box;
-webkit-transition: 240ms;
transition: 240ms;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
border-width: 2px;
border-style: solid;
border-radius: 2px; }
md-checkbox.md-checked .md-icon {
border-color: transparent; }
md-checkbox.md-checked .md-icon:after {
box-sizing: border-box;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
left: 4.66667px;
top: 0.22222px;
display: table;
width: 6.66667px;
height: 13.33333px;
border-width: 2px;
border-style: solid;
border-top: 0;
border-left: 0;
content: ''; }
md-checkbox[disabled] {
cursor: default; }
md-checkbox.md-indeterminate .md-icon:after {
box-sizing: border-box;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
display: table;
width: 12px;
height: 2px;
border-width: 2px;
border-style: solid;
border-top: 0;
border-left: 0;
content: ''; }
md-checkbox .md-label {
box-sizing: border-box;
position: relative;
display: inline-block;
vertical-align: middle;
white-space: normal;
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
margin-left: 30px;
margin-right: 0; }
[dir=rtl] md-checkbox .md-label {
margin-left: 0; }
[dir=rtl] md-checkbox .md-label {
margin-right: 30px; }

View File

@ -0,0 +1,219 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.checkbox');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.checkbox
* @description Checkbox module!
*/
MdCheckboxDirective['$inject'] = ["inputDirective", "$mdAria", "$mdConstant", "$mdTheming", "$mdUtil", "$mdInteraction"];
angular
.module('material.components.checkbox', ['material.core'])
.directive('mdCheckbox', MdCheckboxDirective);
/**
* @ngdoc directive
* @name mdCheckbox
* @module material.components.checkbox
* @restrict E
*
* @description
* The checkbox directive is used like the normal [angular checkbox](https://docs.angularjs.org/api/ng/input/input%5Bcheckbox%5D).
*
* As per the [material design spec](http://www.google.com/design/spec/style/color.html#color-color-schemes)
* the checkbox is in the accent color by default. The primary color palette may be used with
* the `md-primary` class.
*
* @param {string} ng-model Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {expression=} ng-true-value The value to which the expression should be set when selected.
* @param {expression=} ng-false-value The value to which the expression should be set when not selected.
* @param {string=} ng-change AngularJS expression to be executed when input changes due to user interaction with the input element.
* @param {boolean=} md-no-ink Use of attribute indicates use of ripple ink effects
* @param {string=} aria-label Adds label to checkbox for accessibility.
* Defaults to checkbox's text. If no default text is found, a warning will be logged.
* @param {expression=} md-indeterminate This determines when the checkbox should be rendered as 'indeterminate'.
* If a truthy expression or no value is passed in the checkbox renders in the md-indeterminate state.
* If falsy expression is passed in it just looks like a normal unchecked checkbox.
* The indeterminate, checked, and unchecked states are mutually exclusive. A box cannot be in any two states at the same time.
* Adding the 'md-indeterminate' attribute overrides any checked/unchecked rendering logic.
* When using the 'md-indeterminate' attribute use 'ng-checked' to define rendering logic instead of using 'ng-model'.
* @param {expression=} ng-checked If this expression evaluates as truthy, the 'md-checked' css class is added to the checkbox and it
* will appear checked.
*
* @usage
* <hljs lang="html">
* <md-checkbox ng-model="isChecked" aria-label="Finished?">
* Finished ?
* </md-checkbox>
*
* <md-checkbox md-no-ink ng-model="hasInk" aria-label="No Ink Effects">
* No Ink Effects
* </md-checkbox>
*
* <md-checkbox ng-disabled="true" ng-model="isDisabled" aria-label="Disabled">
* Disabled
* </md-checkbox>
*
* </hljs>
*
*/
function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $mdUtil, $mdInteraction) {
inputDirective = inputDirective[0];
return {
restrict: 'E',
transclude: true,
require: ['^?mdInputContainer', '?ngModel', '?^form'],
priority: $mdConstant.BEFORE_NG_ARIA,
template:
'<div class="md-container" md-ink-ripple md-ink-ripple-checkbox>' +
'<div class="md-icon"></div>' +
'</div>' +
'<div ng-transclude class="md-label"></div>',
compile: compile
};
// **********************************************************
// Private Methods
// **********************************************************
function compile (tElement, tAttrs) {
tAttrs.$set('tabindex', tAttrs.tabindex || '0');
tAttrs.$set('type', 'checkbox');
tAttrs.$set('role', tAttrs.type);
return {
pre: function(scope, element) {
// Attach a click handler during preLink, in order to immediately stop propagation
// (especially for ng-click) when the checkbox is disabled.
element.on('click', function(e) {
if (this.hasAttribute('disabled')) {
e.stopImmediatePropagation();
}
});
},
post: postLink
};
function postLink(scope, element, attr, ctrls) {
var isIndeterminate;
var containerCtrl = ctrls[0];
var ngModelCtrl = ctrls[1] || $mdUtil.fakeNgModel();
var formCtrl = ctrls[2];
if (containerCtrl) {
var isErrorGetter = containerCtrl.isErrorGetter || function() {
return ngModelCtrl.$invalid && (ngModelCtrl.$touched || (formCtrl && formCtrl.$submitted));
};
containerCtrl.input = element;
scope.$watch(isErrorGetter, containerCtrl.setInvalid);
}
$mdTheming(element);
// Redirect focus events to the root element, because IE11 is always focusing the container element instead
// of the md-checkbox element. This causes issues when using ngModelOptions: `updateOnBlur`
element.children().on('focus', function() {
element.focus();
});
if ($mdUtil.parseAttributeBoolean(attr.mdIndeterminate)) {
setIndeterminateState();
scope.$watch(attr.mdIndeterminate, setIndeterminateState);
}
if (attr.ngChecked) {
scope.$watch(scope.$eval.bind(scope, attr.ngChecked), function(value) {
ngModelCtrl.$setViewValue(value);
ngModelCtrl.$render();
});
}
$$watchExpr('ngDisabled', 'tabindex', {
true: '-1',
false: attr.tabindex
});
$mdAria.expectWithText(element, 'aria-label');
// Reuse the original input[type=checkbox] directive from AngularJS core.
// This is a bit hacky as we need our own event listener and own render
// function.
inputDirective.link.pre(scope, {
on: angular.noop,
0: {}
}, attr, [ngModelCtrl]);
element.on('click', listener)
.on('keypress', keypressHandler)
.on('focus', function() {
if ($mdInteraction.getLastInteractionType() === 'keyboard') {
element.addClass('md-focused');
}
})
.on('blur', function() {
element.removeClass('md-focused');
});
ngModelCtrl.$render = render;
function $$watchExpr(expr, htmlAttr, valueOpts) {
if (attr[expr]) {
scope.$watch(attr[expr], function(val) {
if (valueOpts[val]) {
element.attr(htmlAttr, valueOpts[val]);
}
});
}
}
function keypressHandler(ev) {
var keyCode = ev.which || ev.keyCode;
if (keyCode === $mdConstant.KEY_CODE.SPACE || keyCode === $mdConstant.KEY_CODE.ENTER) {
ev.preventDefault();
element.addClass('md-focused');
listener(ev);
}
}
function listener(ev) {
// skipToggle boolean is used by the switch directive to prevent the click event
// when releasing the drag. There will be always a click if releasing the drag over the checkbox
if (element[0].hasAttribute('disabled') || scope.skipToggle) {
return;
}
scope.$apply(function() {
// Toggle the checkbox value...
var viewValue = attr.ngChecked && attr.ngClick ? attr.checked : !ngModelCtrl.$viewValue;
ngModelCtrl.$setViewValue(viewValue, ev && ev.type);
ngModelCtrl.$render();
});
}
function render() {
// Cast the $viewValue to a boolean since it could be undefined
element.toggleClass('md-checked', !!ngModelCtrl.$viewValue && !isIndeterminate);
}
function setIndeterminateState(newValue) {
isIndeterminate = newValue !== false;
if (isIndeterminate) {
element.attr('aria-checked', 'mixed');
}
element.toggleClass('md-indeterminate', isIndeterminate);
}
}
}
}
ngmaterial.components.checkbox = angular.module("material.components.checkbox");

View File

@ -0,0 +1,42 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-chips.md-THEME_NAME-theme .md-chips {
box-shadow: 0 1px '{{foreground-4}}'; }
md-chips.md-THEME_NAME-theme .md-chips.md-focused {
box-shadow: 0 2px '{{primary-color}}'; }
md-chips.md-THEME_NAME-theme .md-chips .md-chip-input-container input {
color: '{{foreground-1}}'; }
md-chips.md-THEME_NAME-theme .md-chips .md-chip-input-container input::-webkit-input-placeholder {
color: '{{foreground-3}}'; }
md-chips.md-THEME_NAME-theme .md-chips .md-chip-input-container input:-moz-placeholder {
color: '{{foreground-3}}'; }
md-chips.md-THEME_NAME-theme .md-chips .md-chip-input-container input::-moz-placeholder {
color: '{{foreground-3}}'; }
md-chips.md-THEME_NAME-theme .md-chips .md-chip-input-container input:-ms-input-placeholder {
color: '{{foreground-3}}'; }
md-chips.md-THEME_NAME-theme .md-chips .md-chip-input-container input::-webkit-input-placeholder {
color: '{{foreground-3}}'; }
md-chips.md-THEME_NAME-theme md-chip {
background: '{{background-300}}';
color: '{{background-800}}'; }
md-chips.md-THEME_NAME-theme md-chip md-icon {
color: '{{background-700}}'; }
md-chips.md-THEME_NAME-theme md-chip.md-focused {
background: '{{primary-color}}';
color: '{{primary-contrast}}'; }
md-chips.md-THEME_NAME-theme md-chip.md-focused md-icon {
color: '{{primary-contrast}}'; }
md-chips.md-THEME_NAME-theme md-chip._md-chip-editing {
background: transparent;
color: '{{background-800}}'; }
md-chips.md-THEME_NAME-theme md-chip-remove .md-button md-icon path {
fill: '{{background-500}}'; }
.md-contact-suggestion span.md-contact-email {
color: '{{background-400}}'; }

View File

@ -0,0 +1,186 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
.md-contact-chips .md-chips md-chip {
padding: 0 25px 0 0; }
[dir=rtl] .md-contact-chips .md-chips md-chip {
padding: 0 0 0 25px; }
.md-contact-chips .md-chips md-chip .md-contact-avatar {
float: left; }
[dir=rtl] .md-contact-chips .md-chips md-chip .md-contact-avatar {
float: right; }
.md-contact-chips .md-chips md-chip .md-contact-avatar img {
height: 32px;
border-radius: 16px; }
.md-contact-chips .md-chips md-chip .md-contact-name {
display: inline-block;
height: 32px;
margin-left: 8px; }
[dir=rtl] .md-contact-chips .md-chips md-chip .md-contact-name {
margin-left: auto;
margin-right: 8px; }
.md-contact-suggestion {
height: 56px; }
.md-contact-suggestion img {
height: 40px;
border-radius: 20px;
margin-top: 8px; }
.md-contact-suggestion .md-contact-name {
margin-left: 8px;
width: 120px; }
[dir=rtl] .md-contact-suggestion .md-contact-name {
margin-left: auto;
margin-right: 8px; }
.md-contact-suggestion .md-contact-name, .md-contact-suggestion .md-contact-email {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis; }
.md-contact-chips-suggestions li {
height: 100%; }
.md-chips {
display: block;
font-family: Roboto, "Helvetica Neue", sans-serif;
font-size: 16px;
padding: 0 0 8px 3px;
vertical-align: middle; }
.md-chips:after {
content: '';
display: table;
clear: both; }
[dir=rtl] .md-chips {
padding: 0 3px 8px 0; }
.md-chips.md-readonly .md-chip-input-container {
min-height: 32px; }
.md-chips:not(.md-readonly) {
cursor: text; }
.md-chips.md-removable md-chip {
padding-right: 22px; }
[dir=rtl] .md-chips.md-removable md-chip {
padding-right: 0;
padding-left: 22px; }
.md-chips.md-removable md-chip .md-chip-content {
padding-right: 4px; }
[dir=rtl] .md-chips.md-removable md-chip .md-chip-content {
padding-right: 0;
padding-left: 4px; }
.md-chips md-chip {
cursor: default;
border-radius: 16px;
display: block;
height: 32px;
line-height: 32px;
margin: 8px 8px 0 0;
padding: 0 12px 0 12px;
float: left;
box-sizing: border-box;
max-width: 100%;
position: relative; }
[dir=rtl] .md-chips md-chip {
margin: 8px 0 0 8px; }
[dir=rtl] .md-chips md-chip {
float: right; }
.md-chips md-chip .md-chip-content {
display: block;
float: left;
white-space: nowrap;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis; }
[dir=rtl] .md-chips md-chip .md-chip-content {
float: right; }
.md-chips md-chip .md-chip-content:focus {
outline: none; }
.md-chips md-chip._md-chip-content-edit-is-enabled {
-webkit-user-select: none;
/* webkit (safari, chrome) browsers */
-moz-user-select: none;
/* mozilla browsers */
-khtml-user-select: none;
/* webkit (konqueror) browsers */
-ms-user-select: none;
/* IE10+ */ }
.md-chips md-chip .md-chip-remove-container {
position: absolute;
right: 0;
line-height: 22px; }
[dir=rtl] .md-chips md-chip .md-chip-remove-container {
right: auto;
left: 0; }
.md-chips md-chip .md-chip-remove {
text-align: center;
width: 32px;
height: 32px;
min-width: 0;
padding: 0;
background: transparent;
border: none;
box-shadow: none;
margin: 0;
position: relative; }
.md-chips md-chip .md-chip-remove md-icon {
height: 18px;
width: 18px;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0); }
.md-chips .md-chip-input-container {
display: block;
line-height: 32px;
margin: 8px 8px 0 0;
padding: 0;
float: left; }
[dir=rtl] .md-chips .md-chip-input-container {
margin: 8px 0 0 8px; }
[dir=rtl] .md-chips .md-chip-input-container {
float: right; }
.md-chips .md-chip-input-container input:not([type]), .md-chips .md-chip-input-container input[type="email"], .md-chips .md-chip-input-container input[type="number"], .md-chips .md-chip-input-container input[type="tel"], .md-chips .md-chip-input-container input[type="url"], .md-chips .md-chip-input-container input[type="text"] {
border: 0;
height: 32px;
line-height: 32px;
padding: 0; }
.md-chips .md-chip-input-container input:not([type]):focus, .md-chips .md-chip-input-container input[type="email"]:focus, .md-chips .md-chip-input-container input[type="number"]:focus, .md-chips .md-chip-input-container input[type="tel"]:focus, .md-chips .md-chip-input-container input[type="url"]:focus, .md-chips .md-chip-input-container input[type="text"]:focus {
outline: none; }
.md-chips .md-chip-input-container md-autocomplete, .md-chips .md-chip-input-container md-autocomplete-wrap {
background: transparent;
height: 32px; }
.md-chips .md-chip-input-container md-autocomplete md-autocomplete-wrap {
box-shadow: none; }
.md-chips .md-chip-input-container md-autocomplete input {
position: relative; }
.md-chips .md-chip-input-container input {
border: 0;
height: 32px;
line-height: 32px;
padding: 0; }
.md-chips .md-chip-input-container input:focus {
outline: none; }
.md-chips .md-chip-input-container md-autocomplete, .md-chips .md-chip-input-container md-autocomplete-wrap {
height: 32px; }
.md-chips .md-chip-input-container md-autocomplete {
box-shadow: none; }
.md-chips .md-chip-input-container md-autocomplete input {
position: relative; }
.md-chips .md-chip-input-container:not(:first-child) {
margin: 8px 8px 0 0; }
[dir=rtl] .md-chips .md-chip-input-container:not(:first-child) {
margin: 8px 0 0 8px; }
.md-chips .md-chip-input-container input {
background: transparent;
border-width: 0; }
.md-chips md-autocomplete button {
display: none; }
@media screen and (-ms-high-contrast: active) {
.md-chip-input-container,
md-chip {
border: 1px solid #fff; }
.md-chip-input-container md-autocomplete {
border: none; } }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,410 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.colors');
goog.require('ngmaterial.core');
(function () {
"use strict";
/**
* Use a RegExp to check if the `md-colors="<expression>"` is static string
* or one that should be observed and dynamically interpolated.
*/
MdColorsDirective['$inject'] = ["$mdColors", "$mdUtil", "$log", "$parse"];
MdColorsService['$inject'] = ["$mdTheming", "$mdUtil", "$log"];
var STATIC_COLOR_EXPRESSION = /^{((\s|,)*?["'a-zA-Z-]+?\s*?:\s*?('|")[a-zA-Z0-9-.]*('|"))+\s*}$/;
var colorPalettes = null;
/**
* @ngdoc module
* @name material.components.colors
*
* @description
* Define $mdColors service and a `md-colors=""` attribute directive
*/
angular
.module('material.components.colors', ['material.core'])
.directive('mdColors', MdColorsDirective)
.service('$mdColors', MdColorsService);
/**
* @ngdoc service
* @name $mdColors
* @module material.components.colors
*
* @description
* With only defining themes, one couldn't get non AngularJS Material elements colored with Material colors,
* `$mdColors` service is used by the md-color directive to convert the 1..n color expressions to RGBA values and will apply
* those values to element as CSS property values.
*
* @usage
* <hljs lang="js">
* angular.controller('myCtrl', function ($mdColors) {
* var color = $mdColors.getThemeColor('myTheme-red-200-0.5');
* ...
* });
* </hljs>
*
*/
function MdColorsService($mdTheming, $mdUtil, $log) {
colorPalettes = colorPalettes || Object.keys($mdTheming.PALETTES);
// Publish service instance
return {
applyThemeColors: applyThemeColors,
getThemeColor: getThemeColor,
hasTheme: hasTheme
};
// ********************************************
// Internal Methods
// ********************************************
/**
* @ngdoc method
* @name $mdColors#applyThemeColors
*
* @description
* Gets a color json object, keys are css properties and values are string of the wanted color
* Then calculate the rgba() values based on the theme color parts
*
* @param {DOMElement} element the element to apply the styles on.
* @param {object} colorExpression json object, keys are css properties and values are string of the wanted color,
* for example: `{color: 'red-A200-0.3'}`.
*
* @usage
* <hljs lang="js">
* app.directive('myDirective', function($mdColors) {
* return {
* ...
* link: function (scope, elem) {
* $mdColors.applyThemeColors(elem, {color: 'red'});
* }
* }
* });
* </hljs>
*/
function applyThemeColors(element, colorExpression) {
try {
if (colorExpression) {
// Assign the calculate RGBA color values directly as inline CSS
element.css(interpolateColors(colorExpression));
}
} catch (e) {
$log.error(e.message);
}
}
/**
* @ngdoc method
* @name $mdColors#getThemeColor
*
* @description
* Get parsed color from expression
*
* @param {string} expression string of a color expression (for instance `'red-700-0.8'`)
*
* @returns {string} a css color expression (for instance `rgba(211, 47, 47, 0.8)`)
*
* @usage
* <hljs lang="js">
* angular.controller('myCtrl', function ($mdColors) {
* var color = $mdColors.getThemeColor('myTheme-red-200-0.5');
* ...
* });
* </hljs>
*/
function getThemeColor(expression) {
var color = extractColorOptions(expression);
return parseColor(color);
}
/**
* Return the parsed color
* @param color hashmap of color definitions
* @param contrast whether use contrast color for foreground
* @returns rgba color string
*/
function parseColor(color, contrast) {
contrast = contrast || false;
var rgbValues = $mdTheming.PALETTES[color.palette][color.hue];
rgbValues = contrast ? rgbValues.contrast : rgbValues.value;
return $mdUtil.supplant('rgba({0}, {1}, {2}, {3})',
[rgbValues[0], rgbValues[1], rgbValues[2], rgbValues[3] || color.opacity]
);
}
/**
* Convert the color expression into an object with scope-interpolated values
* Then calculate the rgba() values based on the theme color parts
*
* @results Hashmap of CSS properties with associated `rgba( )` string vales
*
*
*/
function interpolateColors(themeColors) {
var rgbColors = {};
var hasColorProperty = themeColors.hasOwnProperty('color');
angular.forEach(themeColors, function (value, key) {
var color = extractColorOptions(value);
var hasBackground = key.indexOf('background') > -1;
rgbColors[key] = parseColor(color);
if (hasBackground && !hasColorProperty) {
rgbColors.color = parseColor(color, true);
}
});
return rgbColors;
}
/**
* Check if expression has defined theme
* e.g.
* 'myTheme-primary' => true
* 'red-800' => false
*/
function hasTheme(expression) {
return angular.isDefined($mdTheming.THEMES[expression.split('-')[0]]);
}
/**
* For the evaluated expression, extract the color parts into a hash map
*/
function extractColorOptions(expression) {
var parts = expression.split('-');
var hasTheme = angular.isDefined($mdTheming.THEMES[parts[0]]);
var theme = hasTheme ? parts.splice(0, 1)[0] : $mdTheming.defaultTheme();
return {
theme: theme,
palette: extractPalette(parts, theme),
hue: extractHue(parts, theme),
opacity: parts[2] || 1
};
}
/**
* Calculate the theme palette name
*/
function extractPalette(parts, theme) {
// If the next section is one of the palettes we assume it's a two word palette
// Two word palette can be also written in camelCase, forming camelCase to dash-case
var isTwoWord = parts.length > 1 && colorPalettes.indexOf(parts[1]) !== -1;
var palette = parts[0].replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
if (isTwoWord) palette = parts[0] + '-' + parts.splice(1, 1);
if (colorPalettes.indexOf(palette) === -1) {
// If the palette is not in the palette list it's one of primary/accent/warn/background
var scheme = $mdTheming.THEMES[theme].colors[palette];
if (!scheme) {
throw new Error($mdUtil.supplant('mdColors: couldn\'t find \'{palette}\' in the palettes.', {palette: palette}));
}
palette = scheme.name;
}
return palette;
}
function extractHue(parts, theme) {
var themeColors = $mdTheming.THEMES[theme].colors;
if (parts[1] === 'hue') {
var hueNumber = parseInt(parts.splice(2, 1)[0], 10);
if (hueNumber < 1 || hueNumber > 3) {
throw new Error($mdUtil.supplant('mdColors: \'hue-{hueNumber}\' is not a valid hue, can be only \'hue-1\', \'hue-2\' and \'hue-3\'', {hueNumber: hueNumber}));
}
parts[1] = 'hue-' + hueNumber;
if (!(parts[0] in themeColors)) {
throw new Error($mdUtil.supplant('mdColors: \'hue-x\' can only be used with [{availableThemes}], but was used with \'{usedTheme}\'', {
availableThemes: Object.keys(themeColors).join(', '),
usedTheme: parts[0]
}));
}
return themeColors[parts[0]].hues[parts[1]];
}
return parts[1] || themeColors[parts[0] in themeColors ? parts[0] : 'primary'].hues['default'];
}
}
/**
* @ngdoc directive
* @name mdColors
* @module material.components.colors
*
* @restrict A
*
* @description
* `mdColors` directive will apply the theme-based color expression as RGBA CSS style values.
*
* The format will be similar to our color defining in the scss files:
*
* ## `[?theme]-[palette]-[?hue]-[?opacity]`
* - [theme] - default value is the default theme
* - [palette] - can be either palette name or primary/accent/warn/background
* - [hue] - default is 500 (hue-x can be used with primary/accent/warn/background)
* - [opacity] - default is 1
*
* > `?` indicates optional parameter
*
* @usage
* <hljs lang="html">
* <div md-colors="{background: 'myTheme-accent-900-0.43'}">
* <div md-colors="{color: 'red-A100', 'border-color': 'primary-600'}">
* <span>Color demo</span>
* </div>
* </div>
* </hljs>
*
* `mdColors` directive will automatically watch for changes in the expression if it recognizes an interpolation
* expression or a function. For performance options, you can use `::` prefix to the `md-colors` expression
* to indicate a one-time data binding.
* <hljs lang="html">
* <md-card md-colors="::{background: '{{theme}}-primary-700'}">
* </md-card>
* </hljs>
*
*/
function MdColorsDirective($mdColors, $mdUtil, $log, $parse) {
return {
restrict: 'A',
require: ['^?mdTheme'],
compile: function (tElem, tAttrs) {
var shouldWatch = shouldColorsWatch();
return function (scope, element, attrs, ctrl) {
var mdThemeController = ctrl[0];
var lastColors = {};
var parseColors = function (theme) {
if (typeof theme !== 'string') {
theme = '';
}
if (!attrs.mdColors) {
attrs.mdColors = '{}';
}
/**
* Json.parse() does not work because the keys are not quoted;
* use $parse to convert to a hash map
*/
var colors = $parse(attrs.mdColors)(scope);
/**
* If mdTheme is defined up the DOM tree
* we add mdTheme theme to colors who doesn't specified a theme
*
* # example
* <hljs lang="html">
* <div md-theme="myTheme">
* <div md-colors="{background: 'primary-600'}">
* <span md-colors="{background: 'mySecondTheme-accent-200'}">Color demo</span>
* </div>
* </div>
* </hljs>
*
* 'primary-600' will be 'myTheme-primary-600',
* but 'mySecondTheme-accent-200' will stay the same cause it has a theme prefix
*/
if (mdThemeController) {
Object.keys(colors).forEach(function (prop) {
var color = colors[prop];
if (!$mdColors.hasTheme(color)) {
colors[prop] = (theme || mdThemeController.$mdTheme) + '-' + color;
}
});
}
cleanElement(colors);
return colors;
};
var cleanElement = function (colors) {
if (!angular.equals(colors, lastColors)) {
var keys = Object.keys(lastColors);
if (lastColors.background && !keys.color) {
keys.push('color');
}
keys.forEach(function (key) {
element.css(key, '');
});
}
lastColors = colors;
};
/**
* Registering for mgTheme changes and asking mdTheme controller run our callback whenever a theme changes
*/
var unregisterChanges = angular.noop;
if (mdThemeController) {
unregisterChanges = mdThemeController.registerChanges(function (theme) {
$mdColors.applyThemeColors(element, parseColors(theme));
});
}
scope.$on('$destroy', function () {
unregisterChanges();
});
try {
if (shouldWatch) {
scope.$watch(parseColors, angular.bind(this,
$mdColors.applyThemeColors, element
), true);
}
else {
$mdColors.applyThemeColors(element, parseColors());
}
}
catch (e) {
$log.error(e.message);
}
};
function shouldColorsWatch() {
// Simulate 1x binding and mark mdColorsWatch == false
var rawColorExpression = tAttrs.mdColors;
var bindOnce = rawColorExpression.indexOf('::') > -1;
var isStatic = bindOnce ? true : STATIC_COLOR_EXPRESSION.test(tAttrs.mdColors);
// Remove it for the postLink...
tAttrs.mdColors = rawColorExpression.replace('::', '');
var hasWatchAttr = angular.isDefined(tAttrs.mdColorsWatch);
return (bindOnce || isStatic) ? false :
hasWatchAttr ? $mdUtil.parseAttributeBoolean(tAttrs.mdColorsWatch) : true;
}
}
};
}
})();
ngmaterial.components.colors = angular.module("material.components.colors");

View File

@ -0,0 +1,9 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-content.md-THEME_NAME-theme {
color: '{{foreground-1}}';
background-color: '{{background-default}}'; }

View File

@ -0,0 +1,20 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-content {
display: block;
position: relative;
overflow: auto;
-webkit-overflow-scrolling: touch; }
md-content[md-scroll-y] {
overflow-y: auto;
overflow-x: hidden; }
md-content[md-scroll-x] {
overflow-x: auto;
overflow-y: hidden; }
@media print {
md-content {
overflow: visible !important; } }

View File

@ -0,0 +1,102 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.content');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.content
*
* @description
* Scrollable content
*/
mdContentDirective['$inject'] = ["$mdTheming"];
angular.module('material.components.content', [
'material.core'
])
.directive('mdContent', mdContentDirective);
/**
* @ngdoc directive
* @name mdContent
* @module material.components.content
*
* @restrict E
*
* @description
*
* The `<md-content>` directive is a container element useful for scrollable content. It achieves
* this by setting the CSS `overflow` property to `auto` so that content can properly scroll.
*
* In general, `<md-content>` components are not designed to be nested inside one another. If
* possible, it is better to make them siblings. This often results in a better user experience as
* having nested scrollbars may confuse the user.
*
* ## Troubleshooting
*
* In some cases, you may wish to apply the `md-no-momentum` class to ensure that Safari's
* momentum scrolling is disabled. Momentum scrolling can cause flickering issues while scrolling
* SVG icons and some other components.
*
* Additionally, we now also offer the `md-no-flicker` class which can be applied to any element
* and uses a Webkit-specific filter of `blur(0px)` that forces GPU rendering of all elements
* inside (which eliminates the flicker on iOS devices).
*
* _<b>Note:</b> Forcing an element to render on the GPU can have unintended side-effects, especially
* related to the z-index of elements. Please use with caution and only on the elements needed._
*
* @usage
*
* Add the `[layout-padding]` attribute to make the content padded.
*
* <hljs lang="html">
* <md-content layout-padding>
* Lorem ipsum dolor sit amet, ne quod novum mei.
* </md-content>
* </hljs>
*/
function mdContentDirective($mdTheming) {
return {
restrict: 'E',
controller: ['$scope', '$element', ContentController],
link: function(scope, element) {
element.addClass('_md'); // private md component indicator for styling
$mdTheming(element);
scope.$broadcast('$mdContentLoaded', element);
iosScrollFix(element[0]);
}
};
function ContentController($scope, $element) {
this.$scope = $scope;
this.$element = $element;
}
}
function iosScrollFix(node) {
// IOS FIX:
// If we scroll where there is no more room for the webview to scroll,
// by default the webview itself will scroll up and down, this looks really
// bad. So if we are scrolling to the very top or bottom, add/subtract one
angular.element(node).on('$md.pressdown', function(ev) {
// Only touch events
if (ev.pointer.type !== 't') return;
// Don't let a child content's touchstart ruin it for us.
if (ev.$materialScrollFixed) return;
ev.$materialScrollFixed = true;
if (node.scrollTop === 0) {
node.scrollTop = 1;
} else if (node.scrollHeight === node.scrollTop + node.offsetHeight) {
node.scrollTop -= 1;
}
});
}
ngmaterial.components.content = angular.module("material.components.content");

View File

@ -0,0 +1,10 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
/* Only used with Theme processes */
html.md-THEME_NAME-theme, body.md-THEME_NAME-theme {
color: '{{foreground-1}}';
background-color: '{{background-color}}'; }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,84 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
/** Theme styles for mdCalendar. */
.md-calendar.md-THEME_NAME-theme {
background: '{{background-A100}}';
color: '{{background-A200-0.87}}'; }
.md-calendar.md-THEME_NAME-theme tr:last-child td {
border-bottom-color: '{{background-200}}'; }
.md-THEME_NAME-theme .md-calendar-day-header {
background: '{{background-300}}';
color: '{{background-A200-0.87}}'; }
.md-THEME_NAME-theme .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator {
border: 1px solid '{{primary-500}}'; }
.md-THEME_NAME-theme .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled {
color: '{{primary-500-0.6}}'; }
.md-calendar-date.md-focus .md-THEME_NAME-theme .md-calendar-date-selection-indicator, .md-THEME_NAME-theme .md-calendar-date-selection-indicator:hover {
background: '{{background-300}}'; }
.md-THEME_NAME-theme .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator,
.md-THEME_NAME-theme .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator {
background: '{{primary-500}}';
color: '{{primary-500-contrast}}';
border-color: transparent; }
.md-THEME_NAME-theme .md-calendar-date-disabled,
.md-THEME_NAME-theme .md-calendar-month-label-disabled {
color: '{{background-A200-0.435}}'; }
/** Theme styles for mdDatepicker. */
.md-THEME_NAME-theme .md-datepicker-input {
color: '{{foreground-1}}'; }
.md-THEME_NAME-theme .md-datepicker-input::-webkit-input-placeholder {
color: '{{foreground-3}}'; }
.md-THEME_NAME-theme .md-datepicker-input:-moz-placeholder {
color: '{{foreground-3}}'; }
.md-THEME_NAME-theme .md-datepicker-input::-moz-placeholder {
color: '{{foreground-3}}'; }
.md-THEME_NAME-theme .md-datepicker-input:-ms-input-placeholder {
color: '{{foreground-3}}'; }
.md-THEME_NAME-theme .md-datepicker-input::-webkit-input-placeholder {
color: '{{foreground-3}}'; }
.md-THEME_NAME-theme .md-datepicker-input-container {
border-bottom-color: '{{foreground-4}}'; }
.md-THEME_NAME-theme .md-datepicker-input-container.md-datepicker-focused {
border-bottom-color: '{{primary-color}}'; }
.md-accent .md-THEME_NAME-theme .md-datepicker-input-container.md-datepicker-focused {
border-bottom-color: '{{accent-color}}'; }
.md-warn .md-THEME_NAME-theme .md-datepicker-input-container.md-datepicker-focused {
border-bottom-color: '{{warn-A700}}'; }
.md-THEME_NAME-theme .md-datepicker-input-container.md-datepicker-invalid {
border-bottom-color: '{{warn-A700}}'; }
.md-THEME_NAME-theme .md-datepicker-calendar-pane {
border-color: '{{background-hue-1}}'; }
.md-THEME_NAME-theme .md-datepicker-triangle-button .md-datepicker-expand-triangle {
border-top-color: '{{foreground-2}}'; }
.md-THEME_NAME-theme .md-datepicker-open .md-datepicker-calendar-icon {
color: '{{primary-color}}'; }
.md-THEME_NAME-theme .md-datepicker-open.md-accent .md-datepicker-calendar-icon, .md-accent .md-THEME_NAME-theme .md-datepicker-open .md-datepicker-calendar-icon {
color: '{{accent-color}}'; }
.md-THEME_NAME-theme .md-datepicker-open.md-warn .md-datepicker-calendar-icon, .md-warn .md-THEME_NAME-theme .md-datepicker-open .md-datepicker-calendar-icon {
color: '{{warn-A700}}'; }
.md-THEME_NAME-theme .md-datepicker-calendar {
background: '{{background-A100}}'; }
.md-THEME_NAME-theme .md-datepicker-input-mask-opaque {
box-shadow: 0 0 0 9999px "{{background-hue-1}}"; }
.md-THEME_NAME-theme .md-datepicker-open .md-datepicker-input-container {
background: "{{background-hue-1}}"; }

View File

@ -0,0 +1,311 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
/** Styles for mdCalendar. */
md-calendar {
font-size: 13px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; }
.md-calendar-scroll-mask {
display: inline-block;
overflow: hidden;
height: 308px; }
.md-calendar-scroll-mask .md-virtual-repeat-scroller {
overflow-y: scroll;
-webkit-overflow-scrolling: touch; }
.md-calendar-scroll-mask .md-virtual-repeat-scroller::-webkit-scrollbar {
display: none; }
.md-calendar-scroll-mask .md-virtual-repeat-offsetter {
width: 100%; }
.md-calendar-scroll-container {
box-shadow: inset -3px 3px 6px rgba(0, 0, 0, 0.2);
display: inline-block;
height: 308px;
width: 346px; }
.md-calendar-date {
height: 44px;
width: 44px;
text-align: center;
padding: 0;
border: none;
box-sizing: content-box; }
.md-calendar-date:first-child {
padding-left: 16px; }
[dir=rtl] .md-calendar-date:first-child {
padding-left: 0;
padding-right: 16px; }
.md-calendar-date:last-child {
padding-right: 16px; }
[dir=rtl] .md-calendar-date:last-child {
padding-right: 0;
padding-left: 16px; }
.md-calendar-date.md-calendar-date-disabled {
cursor: default; }
.md-calendar-date-selection-indicator {
-webkit-transition: background-color, color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: background-color, color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
border-radius: 50%;
display: inline-block;
width: 40px;
height: 40px;
line-height: 40px; }
.md-calendar-date:not(.md-disabled) .md-calendar-date-selection-indicator {
cursor: pointer; }
.md-calendar-month-label {
height: 44px;
font-size: 14px;
font-weight: 500;
padding: 0 0 0 24px; }
[dir=rtl] .md-calendar-month-label {
padding: 0 24px 0 0; }
md-calendar-month .md-calendar-month-label:not(.md-calendar-month-label-disabled) {
cursor: pointer; }
.md-calendar-month-label md-icon {
-webkit-transform: rotate(180deg);
transform: rotate(180deg); }
[dir=rtl] .md-calendar-month-label md-icon {
-webkit-transform: none;
transform: none; }
.md-calendar-month-label span {
vertical-align: middle; }
.md-calendar-day-header {
table-layout: fixed;
border-spacing: 0;
border-collapse: collapse; }
.md-calendar-day-header th {
height: 40px;
width: 44px;
text-align: center;
padding: 0;
border: none;
box-sizing: content-box;
font-weight: normal; }
.md-calendar-day-header th:first-child {
padding-left: 16px; }
[dir=rtl] .md-calendar-day-header th:first-child {
padding-left: 0;
padding-right: 16px; }
.md-calendar-day-header th:last-child {
padding-right: 16px; }
[dir=rtl] .md-calendar-day-header th:last-child {
padding-right: 0;
padding-left: 16px; }
.md-calendar {
table-layout: fixed;
border-spacing: 0;
border-collapse: collapse; }
.md-calendar tr:last-child td {
border-bottom-width: 1px;
border-bottom-style: solid; }
.md-calendar:first-child {
border-top: 1px solid transparent; }
.md-calendar tbody, .md-calendar td, .md-calendar tr {
vertical-align: middle;
box-sizing: content-box; }
/** Styles for mdDatepicker. */
md-datepicker {
white-space: nowrap;
overflow: hidden;
vertical-align: middle; }
.md-inline-form md-datepicker {
margin-top: 12px; }
.md-datepicker-button {
display: inline-block;
box-sizing: border-box;
background: none;
vertical-align: middle;
position: relative; }
.md-datepicker-button:before {
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
content: '';
speak: none; }
.md-datepicker-input {
font-size: 14px;
box-sizing: border-box;
border: none;
box-shadow: none;
outline: none;
background: transparent;
min-width: 120px;
max-width: 328px;
padding: 0 0 5px; }
.md-datepicker-input::-ms-clear {
display: none; }
._md-datepicker-floating-label > md-datepicker {
overflow: visible; }
._md-datepicker-floating-label > md-datepicker .md-datepicker-input-container {
border: none; }
._md-datepicker-floating-label > md-datepicker .md-datepicker-button {
float: left;
margin-top: -12px;
top: 9.5px; }
[dir=rtl] ._md-datepicker-floating-label > md-datepicker .md-datepicker-button {
float: right; }
._md-datepicker-floating-label .md-input {
float: none; }
._md-datepicker-floating-label._md-datepicker-has-calendar-icon > label:not(.md-no-float):not(.md-container-ignore) {
right: 18px;
left: auto;
width: calc(100% - 84px); }
[dir=rtl] ._md-datepicker-floating-label._md-datepicker-has-calendar-icon > label:not(.md-no-float):not(.md-container-ignore) {
right: auto; }
[dir=rtl] ._md-datepicker-floating-label._md-datepicker-has-calendar-icon > label:not(.md-no-float):not(.md-container-ignore) {
left: 18px; }
._md-datepicker-floating-label._md-datepicker-has-calendar-icon .md-input-message-animation {
margin-left: 64px; }
[dir=rtl] ._md-datepicker-floating-label._md-datepicker-has-calendar-icon .md-input-message-animation {
margin-left: auto;
margin-right: 64px; }
._md-datepicker-has-triangle-icon {
padding-right: 18px;
margin-right: -18px; }
[dir=rtl] ._md-datepicker-has-triangle-icon {
padding-right: 0;
padding-left: 18px; }
[dir=rtl] ._md-datepicker-has-triangle-icon {
margin-right: auto;
margin-left: -18px; }
.md-datepicker-input-container {
position: relative;
border-bottom-width: 1px;
border-bottom-style: solid;
display: inline-block;
width: auto; }
.md-icon-button + .md-datepicker-input-container {
margin-left: 12px; }
[dir=rtl] .md-icon-button + .md-datepicker-input-container {
margin-left: auto;
margin-right: 12px; }
.md-datepicker-input-container.md-datepicker-focused {
border-bottom-width: 2px; }
.md-datepicker-is-showing .md-scroll-mask {
z-index: 99; }
.md-datepicker-calendar-pane {
position: absolute;
top: 0;
left: -100%;
z-index: 100;
border-width: 1px;
border-style: solid;
background: transparent;
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transition: -webkit-transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: -webkit-transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1); }
.md-datepicker-calendar-pane.md-pane-open {
-webkit-transform: scale(1);
transform: scale(1); }
.md-datepicker-input-mask {
height: 40px;
width: 340px;
position: relative;
overflow: hidden;
background: transparent;
pointer-events: none;
cursor: text; }
.md-datepicker-calendar {
opacity: 0;
-webkit-transition: opacity 0.2s cubic-bezier(0.5, 0, 0.25, 1);
transition: opacity 0.2s cubic-bezier(0.5, 0, 0.25, 1); }
.md-pane-open .md-datepicker-calendar {
opacity: 1; }
.md-datepicker-calendar md-calendar:focus {
outline: none; }
.md-datepicker-expand-triangle {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid; }
.md-datepicker-triangle-button {
position: absolute;
right: 0;
bottom: -2.5px;
-webkit-transform: translateX(45%);
transform: translateX(45%); }
[dir=rtl] .md-datepicker-triangle-button {
right: auto;
left: 0; }
[dir=rtl] .md-datepicker-triangle-button {
-webkit-transform: translateX(-45%);
transform: translateX(-45%); }
.md-datepicker-triangle-button.md-button.md-icon-button {
height: 36px;
width: 36px;
position: absolute;
padding: 8px; }
md-datepicker[disabled] .md-datepicker-input-container {
border-bottom-color: transparent; }
md-datepicker[disabled] .md-datepicker-triangle-button {
display: none; }
.md-datepicker-open {
overflow: hidden; }
.md-datepicker-open .md-datepicker-input-container,
.md-datepicker-open input.md-input {
border-bottom-color: transparent; }
.md-datepicker-open .md-datepicker-triangle-button,
.md-datepicker-open.md-input-has-value > label,
.md-datepicker-open.md-input-has-placeholder > label {
display: none; }
.md-datepicker-pos-adjusted .md-datepicker-input-mask {
display: none; }
.md-datepicker-calendar-pane .md-calendar {
-webkit-transform: translateY(-85px);
transform: translateY(-85px);
-webkit-transition: -webkit-transform 0.65s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: -webkit-transform 0.65s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: transform 0.65s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: transform 0.65s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.65s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transition-delay: 0.125s;
transition-delay: 0.125s; }
.md-datepicker-calendar-pane.md-pane-open .md-calendar {
-webkit-transform: translateY(0);
transform: translateY(0); }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-dialog.md-THEME_NAME-theme {
border-radius: 4px;
background-color: '{{background-hue-1}}';
color: '{{foreground-1}}'; }
md-dialog.md-THEME_NAME-theme.md-content-overflow .md-actions, md-dialog.md-THEME_NAME-theme.md-content-overflow md-dialog-actions {
border-top-color: '{{foreground-4}}'; }

View File

@ -0,0 +1,131 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
.md-dialog-is-showing {
max-height: 100%; }
.md-dialog-container {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 80;
overflow: hidden; }
md-dialog {
opacity: 0;
min-width: 240px;
max-width: 80%;
max-height: 80%;
position: relative;
overflow: auto;
box-shadow: 0px 7px 8px -4px rgba(0, 0, 0, 0.2), 0px 13px 19px 2px rgba(0, 0, 0, 0.14), 0px 5px 24px 4px rgba(0, 0, 0, 0.12);
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column; }
md-dialog.md-transition-in {
opacity: 1;
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transform: translate(0, 0) scale(1);
transform: translate(0, 0) scale(1); }
md-dialog.md-transition-out {
opacity: 0;
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transform: translate(0, 100%) scale(0.2);
transform: translate(0, 100%) scale(0.2); }
md-dialog > form {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
overflow: auto; }
md-dialog .md-dialog-content {
padding: 24px; }
md-dialog md-dialog-content {
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
order: 1;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
overflow: auto;
-webkit-overflow-scrolling: touch; }
md-dialog md-dialog-content:not([layout=row]) > *:first-child:not(.md-subheader) {
margin-top: 0; }
md-dialog md-dialog-content:focus {
outline: none; }
md-dialog md-dialog-content .md-subheader {
margin: 0; }
md-dialog md-dialog-content .md-dialog-content-body {
width: 100%; }
md-dialog md-dialog-content .md-prompt-input-container {
width: 100%;
box-sizing: border-box; }
md-dialog .md-actions, md-dialog md-dialog-actions {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-ordinal-group: 3;
-webkit-order: 2;
order: 2;
box-sizing: border-box;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
margin-bottom: 0;
padding-right: 8px;
padding-left: 16px;
min-height: 52px;
overflow: hidden; }
[dir=rtl] md-dialog .md-actions, [dir=rtl] md-dialog md-dialog-actions {
padding-right: 16px; }
[dir=rtl] md-dialog .md-actions, [dir=rtl] md-dialog md-dialog-actions {
padding-left: 8px; }
md-dialog .md-actions .md-button, md-dialog md-dialog-actions .md-button {
margin-bottom: 8px;
margin-left: 8px;
margin-right: 0;
margin-top: 8px; }
[dir=rtl] md-dialog .md-actions .md-button, [dir=rtl] md-dialog md-dialog-actions .md-button {
margin-left: 0; }
[dir=rtl] md-dialog .md-actions .md-button, [dir=rtl] md-dialog md-dialog-actions .md-button {
margin-right: 8px; }
md-dialog.md-content-overflow .md-actions, md-dialog.md-content-overflow md-dialog-actions {
border-top-width: 1px;
border-top-style: solid; }
@media screen and (-ms-high-contrast: active) {
md-dialog {
border: 1px solid #fff; } }
@media (max-width: 959px) {
md-dialog.md-dialog-fullscreen {
min-height: 100%;
min-width: 100%;
border-radius: 0; } }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-divider.md-THEME_NAME-theme {
border-top-color: '{{foreground-4}}'; }
.layout-row > md-divider.md-THEME_NAME-theme,
.layout-xs-row > md-divider.md-THEME_NAME-theme, .layout-gt-xs-row > md-divider.md-THEME_NAME-theme,
.layout-sm-row > md-divider.md-THEME_NAME-theme, .layout-gt-sm-row > md-divider.md-THEME_NAME-theme,
.layout-md-row > md-divider.md-THEME_NAME-theme, .layout-gt-md-row > md-divider.md-THEME_NAME-theme,
.layout-lg-row > md-divider.md-THEME_NAME-theme, .layout-gt-lg-row > md-divider.md-THEME_NAME-theme,
.layout-xl-row > md-divider.md-THEME_NAME-theme {
border-right-color: '{{foreground-4}}'; }

View File

@ -0,0 +1,26 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-divider {
display: block;
border-top-width: 1px;
border-top-style: solid;
margin: 0; }
md-divider[md-inset] {
margin-left: 80px; }
[dir=rtl] md-divider[md-inset] {
margin-left: auto;
margin-right: 80px; }
.layout-row > md-divider,
.layout-xs-row > md-divider, .layout-gt-xs-row > md-divider,
.layout-sm-row > md-divider, .layout-gt-sm-row > md-divider,
.layout-md-row > md-divider, .layout-gt-md-row > md-divider,
.layout-lg-row > md-divider, .layout-gt-lg-row > md-divider,
.layout-xl-row > md-divider {
border-top-width: 0;
border-right-width: 1px;
border-right-style: solid; }

View File

@ -0,0 +1,45 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.divider');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.divider
* @description Divider module!
*/
MdDividerDirective['$inject'] = ["$mdTheming"];
angular.module('material.components.divider', [
'material.core'
])
.directive('mdDivider', MdDividerDirective);
/**
* @ngdoc directive
* @name mdDivider
* @module material.components.divider
* @restrict E
*
* @description
* Dividers group and separate content within lists and page layouts using strong visual and spatial distinctions. This divider is a thin rule, lightweight enough to not distract the user from content.
*
* @param {boolean=} md-inset Add this attribute to activate the inset divider style.
* @usage
* <hljs lang="html">
* <md-divider></md-divider>
*
* <md-divider md-inset></md-divider>
* </hljs>
*
*/
function MdDividerDirective($mdTheming) {
return {
restrict: 'E',
link: $mdTheming
};
}
ngmaterial.components.divider = angular.module("material.components.divider");

View File

@ -0,0 +1,60 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.fabActions');
goog.require('ngmaterial.core');
(function() {
'use strict';
/**
* @ngdoc module
* @name material.components.fabActions
*/
MdFabActionsDirective['$inject'] = ["$mdUtil"];
angular
.module('material.components.fabActions', ['material.core'])
.directive('mdFabActions', MdFabActionsDirective);
/**
* @ngdoc directive
* @name mdFabActions
* @module material.components.fabActions
*
* @restrict E
*
* @description
* The `<md-fab-actions>` directive is used inside of a `<md-fab-speed-dial>` or
* `<md-fab-toolbar>` directive to mark an element (or elements) as the actions and setup the
* proper event listeners.
*
* @usage
* See the `<md-fab-speed-dial>` or `<md-fab-toolbar>` directives for example usage.
*/
function MdFabActionsDirective($mdUtil) {
return {
restrict: 'E',
require: ['^?mdFabSpeedDial', '^?mdFabToolbar'],
compile: function(element, attributes) {
var children = element.children();
var hasNgRepeat = $mdUtil.prefixer().hasAttribute(children, 'ng-repeat');
// Support both ng-repeat and static content
if (hasNgRepeat) {
children.addClass('md-fab-action-item');
} else {
// Wrap every child in a new div and add a class that we can scale/fling independently
children.wrap('<div class="md-fab-action-item">');
}
}
};
}
})();
ngmaterial.components.fabActions = angular.module("material.components.fabActions");

View File

@ -0,0 +1,154 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-fab-speed-dial {
position: relative;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
z-index: 20;
/*
* Hide some graphics glitches if switching animation types
*/
/*
* Handle the animations
*/ }
md-fab-speed-dial.md-fab-bottom-right {
top: auto;
right: 20px;
bottom: 20px;
left: auto;
position: absolute; }
md-fab-speed-dial.md-fab-bottom-left {
top: auto;
right: auto;
bottom: 20px;
left: 20px;
position: absolute; }
md-fab-speed-dial.md-fab-top-right {
top: 20px;
right: 20px;
bottom: auto;
left: auto;
position: absolute; }
md-fab-speed-dial.md-fab-top-left {
top: 20px;
right: auto;
bottom: auto;
left: 20px;
position: absolute; }
md-fab-speed-dial:not(.md-hover-full) {
pointer-events: none; }
md-fab-speed-dial:not(.md-hover-full) md-fab-trigger, md-fab-speed-dial:not(.md-hover-full) .md-fab-action-item {
pointer-events: auto; }
md-fab-speed-dial:not(.md-hover-full).md-is-open {
pointer-events: auto; }
md-fab-speed-dial ._md-css-variables {
z-index: 20; }
md-fab-speed-dial.md-is-open .md-fab-action-item {
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center; }
md-fab-speed-dial md-fab-actions {
display: -webkit-box;
display: -webkit-flex;
display: flex;
height: auto; }
md-fab-speed-dial md-fab-actions .md-fab-action-item {
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-fab-speed-dial.md-down {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column; }
md-fab-speed-dial.md-down md-fab-trigger {
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
order: 1; }
md-fab-speed-dial.md-down md-fab-actions {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-box-ordinal-group: 3;
-webkit-order: 2;
order: 2; }
md-fab-speed-dial.md-up {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column; }
md-fab-speed-dial.md-up md-fab-trigger {
-webkit-box-ordinal-group: 3;
-webkit-order: 2;
order: 2; }
md-fab-speed-dial.md-up md-fab-actions {
-webkit-box-orient: vertical;
-webkit-box-direction: reverse;
-webkit-flex-direction: column-reverse;
flex-direction: column-reverse;
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
order: 1; }
md-fab-speed-dial.md-left {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
md-fab-speed-dial.md-left md-fab-trigger {
-webkit-box-ordinal-group: 3;
-webkit-order: 2;
order: 2; }
md-fab-speed-dial.md-left md-fab-actions {
-webkit-box-orient: horizontal;
-webkit-box-direction: reverse;
-webkit-flex-direction: row-reverse;
flex-direction: row-reverse;
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
order: 1; }
md-fab-speed-dial.md-left md-fab-actions .md-fab-action-item {
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-fab-speed-dial.md-right {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
md-fab-speed-dial.md-right md-fab-trigger {
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
order: 1; }
md-fab-speed-dial.md-right md-fab-actions {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
-webkit-box-ordinal-group: 3;
-webkit-order: 2;
order: 2; }
md-fab-speed-dial.md-right md-fab-actions .md-fab-action-item {
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-fab-speed-dial.md-fling-remove .md-fab-action-item > *, md-fab-speed-dial.md-scale-remove .md-fab-action-item > * {
visibility: hidden; }
md-fab-speed-dial.md-fling .md-fab-action-item {
opacity: 1; }
md-fab-speed-dial.md-fling.md-animations-waiting .md-fab-action-item {
opacity: 0;
-webkit-transition-duration: 0s;
transition-duration: 0s; }
md-fab-speed-dial.md-scale .md-fab-action-item {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
-webkit-transition-duration: 0.14286s;
transition-duration: 0.14286s; }

View File

@ -0,0 +1,575 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.fabShared');
goog.require('ngmaterial.core');
(function() {
'use strict';
MdFabController['$inject'] = ["$scope", "$element", "$animate", "$mdUtil", "$mdConstant", "$timeout"];
angular.module('material.components.fabShared', ['material.core'])
.controller('MdFabController', MdFabController);
function MdFabController($scope, $element, $animate, $mdUtil, $mdConstant, $timeout) {
var vm = this;
var initialAnimationAttempts = 0;
// NOTE: We use async eval(s) below to avoid conflicts with any existing digest loops
vm.open = function() {
$scope.$evalAsync("vm.isOpen = true");
};
vm.close = function() {
// Async eval to avoid conflicts with existing digest loops
$scope.$evalAsync("vm.isOpen = false");
// Focus the trigger when the element closes so users can still tab to the next item
$element.find('md-fab-trigger')[0].focus();
};
// Toggle the open/close state when the trigger is clicked
vm.toggle = function() {
$scope.$evalAsync("vm.isOpen = !vm.isOpen");
};
/*
* AngularJS Lifecycle hook for newer AngularJS versions.
* Bindings are not guaranteed to have been assigned in the controller, but they are in the $onInit hook.
*/
vm.$onInit = function() {
setupDefaults();
setupListeners();
setupWatchers();
fireInitialAnimations();
};
// For AngularJS 1.4 and older, where there are no lifecycle hooks but bindings are pre-assigned,
// manually call the $onInit hook.
if (angular.version.major === 1 && angular.version.minor <= 4) {
this.$onInit();
}
function setupDefaults() {
// Set the default direction to 'down' if none is specified
vm.direction = vm.direction || 'down';
// Set the default to be closed
vm.isOpen = vm.isOpen || false;
// Start the keyboard interaction at the first action
resetActionIndex();
// Add an animations waiting class so we know not to run
$element.addClass('md-animations-waiting');
}
function setupListeners() {
var eventTypes = [
'click', 'focusin', 'focusout'
];
// Add our listeners
angular.forEach(eventTypes, function(eventType) {
$element.on(eventType, parseEvents);
});
// Remove our listeners when destroyed
$scope.$on('$destroy', function() {
angular.forEach(eventTypes, function(eventType) {
$element.off(eventType, parseEvents);
});
// remove any attached keyboard handlers in case element is removed while
// speed dial is open
disableKeyboard();
});
}
var closeTimeout;
function parseEvents(event) {
// If the event is a click, just handle it
if (event.type == 'click') {
handleItemClick(event);
}
// If we focusout, set a timeout to close the element
if (event.type == 'focusout' && !closeTimeout) {
closeTimeout = $timeout(function() {
vm.close();
}, 100, false);
}
// If we see a focusin and there is a timeout about to run, cancel it so we stay open
if (event.type == 'focusin' && closeTimeout) {
$timeout.cancel(closeTimeout);
closeTimeout = null;
}
}
function resetActionIndex() {
vm.currentActionIndex = -1;
}
function setupWatchers() {
// Watch for changes to the direction and update classes/attributes
$scope.$watch('vm.direction', function(newDir, oldDir) {
// Add the appropriate classes so we can target the direction in the CSS
$animate.removeClass($element, 'md-' + oldDir);
$animate.addClass($element, 'md-' + newDir);
// Reset the action index since it may have changed
resetActionIndex();
});
var trigger, actions;
// Watch for changes to md-open
$scope.$watch('vm.isOpen', function(isOpen) {
// Reset the action index since it may have changed
resetActionIndex();
// We can't get the trigger/actions outside of the watch because the component hasn't been
// linked yet, so we wait until the first watch fires to cache them.
if (!trigger || !actions) {
trigger = getTriggerElement();
actions = getActionsElement();
}
if (isOpen) {
enableKeyboard();
} else {
disableKeyboard();
}
var toAdd = isOpen ? 'md-is-open' : '';
var toRemove = isOpen ? '' : 'md-is-open';
// Set the proper ARIA attributes
trigger.attr('aria-haspopup', true);
trigger.attr('aria-expanded', isOpen);
actions.attr('aria-hidden', !isOpen);
// Animate the CSS classes
$animate.setClass($element, toAdd, toRemove);
});
}
function fireInitialAnimations() {
// If the element is actually visible on the screen
if ($element[0].scrollHeight > 0) {
// Fire our animation
$animate.addClass($element, '_md-animations-ready').then(function() {
// Remove the waiting class
$element.removeClass('md-animations-waiting');
});
}
// Otherwise, try for up to 1 second before giving up
else if (initialAnimationAttempts < 10) {
$timeout(fireInitialAnimations, 100);
// Increment our counter
initialAnimationAttempts = initialAnimationAttempts + 1;
}
}
function enableKeyboard() {
$element.on('keydown', keyPressed);
// On the next tick, setup a check for outside clicks; we do this on the next tick to avoid
// clicks/touches that result in the isOpen attribute changing (e.g. a bound radio button)
$mdUtil.nextTick(function() {
angular.element(document).on('click touchend', checkForOutsideClick);
});
// TODO: On desktop, we should be able to reset the indexes so you cannot tab through, but
// this breaks accessibility, especially on mobile, since you have no arrow keys to press
//resetActionTabIndexes();
}
function disableKeyboard() {
$element.off('keydown', keyPressed);
angular.element(document).off('click touchend', checkForOutsideClick);
}
function checkForOutsideClick(event) {
if (event.target) {
var closestTrigger = $mdUtil.getClosest(event.target, 'md-fab-trigger');
var closestActions = $mdUtil.getClosest(event.target, 'md-fab-actions');
if (!closestTrigger && !closestActions) {
vm.close();
}
}
}
function keyPressed(event) {
switch (event.which) {
case $mdConstant.KEY_CODE.ESCAPE: vm.close(); event.preventDefault(); return false;
case $mdConstant.KEY_CODE.LEFT_ARROW: doKeyLeft(event); return false;
case $mdConstant.KEY_CODE.UP_ARROW: doKeyUp(event); return false;
case $mdConstant.KEY_CODE.RIGHT_ARROW: doKeyRight(event); return false;
case $mdConstant.KEY_CODE.DOWN_ARROW: doKeyDown(event); return false;
}
}
function doActionPrev(event) {
focusAction(event, -1);
}
function doActionNext(event) {
focusAction(event, 1);
}
function focusAction(event, direction) {
var actions = resetActionTabIndexes();
// Increment/decrement the counter with restrictions
vm.currentActionIndex = vm.currentActionIndex + direction;
vm.currentActionIndex = Math.min(actions.length - 1, vm.currentActionIndex);
vm.currentActionIndex = Math.max(0, vm.currentActionIndex);
// Focus the element
var focusElement = angular.element(actions[vm.currentActionIndex]).children()[0];
angular.element(focusElement).attr('tabindex', 0);
focusElement.focus();
// Make sure the event doesn't bubble and cause something else
event.preventDefault();
event.stopImmediatePropagation();
}
function resetActionTabIndexes() {
// Grab all of the actions
var actions = getActionsElement()[0].querySelectorAll('.md-fab-action-item');
// Disable all other actions for tabbing
angular.forEach(actions, function(action) {
angular.element(angular.element(action).children()[0]).attr('tabindex', -1);
});
return actions;
}
function doKeyLeft(event) {
if (vm.direction === 'left') {
doActionNext(event);
} else {
doActionPrev(event);
}
}
function doKeyUp(event) {
if (vm.direction === 'down') {
doActionPrev(event);
} else {
doActionNext(event);
}
}
function doKeyRight(event) {
if (vm.direction === 'left') {
doActionPrev(event);
} else {
doActionNext(event);
}
}
function doKeyDown(event) {
if (vm.direction === 'up') {
doActionPrev(event);
} else {
doActionNext(event);
}
}
function isTrigger(element) {
return $mdUtil.getClosest(element, 'md-fab-trigger');
}
function isAction(element) {
return $mdUtil.getClosest(element, 'md-fab-actions');
}
function handleItemClick(event) {
if (isTrigger(event.target)) {
vm.toggle();
}
if (isAction(event.target)) {
vm.close();
}
}
function getTriggerElement() {
return $element.find('md-fab-trigger');
}
function getActionsElement() {
return $element.find('md-fab-actions');
}
}
})();
(function() {
'use strict';
/**
* The duration of the CSS animation in milliseconds.
*
* @type {number}
*/
MdFabSpeedDialFlingAnimation['$inject'] = ["$timeout"];
MdFabSpeedDialScaleAnimation['$inject'] = ["$timeout"];
var cssAnimationDuration = 300;
/**
* @ngdoc module
* @name material.components.fabSpeedDial
*/
angular
// Declare our module
.module('material.components.fabSpeedDial', [
'material.core',
'material.components.fabShared',
'material.components.fabActions'
])
// Register our directive
.directive('mdFabSpeedDial', MdFabSpeedDialDirective)
// Register our custom animations
.animation('.md-fling', MdFabSpeedDialFlingAnimation)
.animation('.md-scale', MdFabSpeedDialScaleAnimation)
// Register a service for each animation so that we can easily inject them into unit tests
.service('mdFabSpeedDialFlingAnimation', MdFabSpeedDialFlingAnimation)
.service('mdFabSpeedDialScaleAnimation', MdFabSpeedDialScaleAnimation);
/**
* @ngdoc directive
* @name mdFabSpeedDial
* @module material.components.fabSpeedDial
*
* @restrict E
*
* @description
* The `<md-fab-speed-dial>` directive is used to present a series of popup elements (usually
* `<md-button>`s) for quick access to common actions.
*
* There are currently two animations available by applying one of the following classes to
* the component:
*
* - `md-fling` - The speed dial items appear from underneath the trigger and move into their
* appropriate positions.
* - `md-scale` - The speed dial items appear in their proper places by scaling from 0% to 100%.
*
* You may also easily position the trigger by applying one one of the following classes to the
* `<md-fab-speed-dial>` element:
* - `md-fab-top-left`
* - `md-fab-top-right`
* - `md-fab-bottom-left`
* - `md-fab-bottom-right`
*
* These CSS classes use `position: absolute`, so you need to ensure that the container element
* also uses `position: absolute` or `position: relative` in order for them to work.
*
* Additionally, you may use the standard `ng-mouseenter` and `ng-mouseleave` directives to
* open or close the speed dial. However, if you wish to allow users to hover over the empty
* space where the actions will appear, you must also add the `md-hover-full` class to the speed
* dial element. Without this, the hover effect will only occur on top of the trigger.
*
* See the demos for more information.
*
* ## Troubleshooting
*
* If your speed dial shows the closing animation upon launch, you may need to use `ng-cloak` on
* the parent container to ensure that it is only visible once ready. We have plans to remove this
* necessity in the future.
*
* @usage
* <hljs lang="html">
* <md-fab-speed-dial md-direction="up" class="md-fling">
* <md-fab-trigger>
* <md-button aria-label="Add..."><md-icon md-svg-src="/img/icons/plus.svg"></md-icon></md-button>
* </md-fab-trigger>
*
* <md-fab-actions>
* <md-button aria-label="Add User">
* <md-icon md-svg-src="/img/icons/user.svg"></md-icon>
* </md-button>
*
* <md-button aria-label="Add Group">
* <md-icon md-svg-src="/img/icons/group.svg"></md-icon>
* </md-button>
* </md-fab-actions>
* </md-fab-speed-dial>
* </hljs>
*
* @param {string} md-direction From which direction you would like the speed dial to appear
* relative to the trigger element.
* @param {expression=} md-open Programmatically control whether or not the speed-dial is visible.
*/
function MdFabSpeedDialDirective() {
return {
restrict: 'E',
scope: {
direction: '@?mdDirection',
isOpen: '=?mdOpen'
},
bindToController: true,
controller: 'MdFabController',
controllerAs: 'vm',
link: FabSpeedDialLink
};
function FabSpeedDialLink(scope, element) {
// Prepend an element to hold our CSS variables so we can use them in the animations below
element.prepend('<div class="_md-css-variables"></div>');
}
}
function MdFabSpeedDialFlingAnimation($timeout) {
function delayDone(done) { $timeout(done, cssAnimationDuration, false); }
function runAnimation(element) {
// Don't run if we are still waiting and we are not ready
if (element.hasClass('md-animations-waiting') && !element.hasClass('_md-animations-ready')) {
return;
}
var el = element[0];
var ctrl = element.controller('mdFabSpeedDial');
var items = el.querySelectorAll('.md-fab-action-item');
// Grab our trigger element
var triggerElement = el.querySelector('md-fab-trigger');
// Grab our element which stores CSS variables
var variablesElement = el.querySelector('._md-css-variables');
// Setup JS variables based on our CSS variables
var startZIndex = parseInt(window.getComputedStyle(variablesElement).zIndex);
// Always reset the items to their natural position/state
angular.forEach(items, function(item, index) {
var styles = item.style;
styles.transform = styles.webkitTransform = '';
styles.transitionDelay = '';
styles.opacity = 1;
// Make the items closest to the trigger have the highest z-index
styles.zIndex = (items.length - index) + startZIndex;
});
// Set the trigger to be above all of the actions so they disappear behind it.
triggerElement.style.zIndex = startZIndex + items.length + 1;
// If the control is closed, hide the items behind the trigger
if (!ctrl.isOpen) {
angular.forEach(items, function(item, index) {
var newPosition, axis;
var styles = item.style;
// Make sure to account for differences in the dimensions of the trigger verses the items
// so that we can properly center everything; this helps hide the item's shadows behind
// the trigger.
var triggerItemHeightOffset = (triggerElement.clientHeight - item.clientHeight) / 2;
var triggerItemWidthOffset = (triggerElement.clientWidth - item.clientWidth) / 2;
switch (ctrl.direction) {
case 'up':
newPosition = (item.scrollHeight * (index + 1) + triggerItemHeightOffset);
axis = 'Y';
break;
case 'down':
newPosition = -(item.scrollHeight * (index + 1) + triggerItemHeightOffset);
axis = 'Y';
break;
case 'left':
newPosition = (item.scrollWidth * (index + 1) + triggerItemWidthOffset);
axis = 'X';
break;
case 'right':
newPosition = -(item.scrollWidth * (index + 1) + triggerItemWidthOffset);
axis = 'X';
break;
}
var newTranslate = 'translate' + axis + '(' + newPosition + 'px)';
styles.transform = styles.webkitTransform = newTranslate;
});
}
}
return {
addClass: function(element, className, done) {
if (element.hasClass('md-fling')) {
runAnimation(element);
delayDone(done);
} else {
done();
}
},
removeClass: function(element, className, done) {
runAnimation(element);
delayDone(done);
}
};
}
function MdFabSpeedDialScaleAnimation($timeout) {
function delayDone(done) { $timeout(done, cssAnimationDuration, false); }
var delay = 65;
function runAnimation(element) {
var el = element[0];
var ctrl = element.controller('mdFabSpeedDial');
var items = el.querySelectorAll('.md-fab-action-item');
// Grab our element which stores CSS variables
var variablesElement = el.querySelector('._md-css-variables');
// Setup JS variables based on our CSS variables
var startZIndex = parseInt(window.getComputedStyle(variablesElement).zIndex);
// Always reset the items to their natural position/state
angular.forEach(items, function(item, index) {
var styles = item.style,
offsetDelay = index * delay;
styles.opacity = ctrl.isOpen ? 1 : 0;
styles.transform = styles.webkitTransform = ctrl.isOpen ? 'scale(1)' : 'scale(0)';
styles.transitionDelay = (ctrl.isOpen ? offsetDelay : (items.length - offsetDelay)) + 'ms';
// Make the items closest to the trigger have the highest z-index
styles.zIndex = (items.length - index) + startZIndex;
});
}
return {
addClass: function(element, className, done) {
runAnimation(element);
delayDone(done);
},
removeClass: function(element, className, done) {
runAnimation(element);
delayDone(done);
}
};
}
})();
ngmaterial.components.fabShared = angular.module("material.components.fabShared");

View File

@ -0,0 +1,119 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-fab-toolbar {
display: block;
/*
* Closed styling
*/
/*
* Hover styling
*/ }
md-fab-toolbar.md-fab-bottom-right {
top: auto;
right: 20px;
bottom: 20px;
left: auto;
position: absolute; }
md-fab-toolbar.md-fab-bottom-left {
top: auto;
right: auto;
bottom: 20px;
left: 20px;
position: absolute; }
md-fab-toolbar.md-fab-top-right {
top: 20px;
right: 20px;
bottom: auto;
left: auto;
position: absolute; }
md-fab-toolbar.md-fab-top-left {
top: 20px;
right: auto;
bottom: auto;
left: 20px;
position: absolute; }
md-fab-toolbar .md-fab-toolbar-wrapper {
display: block;
position: relative;
overflow: hidden;
height: 68px; }
md-fab-toolbar md-fab-trigger {
position: absolute;
z-index: 20; }
md-fab-toolbar md-fab-trigger button {
overflow: visible !important; }
md-fab-toolbar md-fab-trigger .md-fab-toolbar-background {
display: block;
position: absolute;
z-index: 21;
opacity: 1;
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-fab-toolbar md-fab-trigger md-icon {
position: relative;
z-index: 22;
opacity: 1;
-webkit-transition: all 200ms ease-in;
transition: all 200ms ease-in; }
md-fab-toolbar.md-left md-fab-trigger {
right: 0; }
[dir=rtl] md-fab-toolbar.md-left md-fab-trigger {
right: auto;
left: 0; }
md-fab-toolbar.md-left .md-toolbar-tools {
-webkit-box-orient: horizontal;
-webkit-box-direction: reverse;
-webkit-flex-direction: row-reverse;
flex-direction: row-reverse; }
md-fab-toolbar.md-left .md-toolbar-tools > .md-button:first-child {
margin-right: 0.6rem; }
[dir=rtl] md-fab-toolbar.md-left .md-toolbar-tools > .md-button:first-child {
margin-right: auto;
margin-left: 0.6rem; }
md-fab-toolbar.md-left .md-toolbar-tools > .md-button:first-child {
margin-left: -0.8rem; }
[dir=rtl] md-fab-toolbar.md-left .md-toolbar-tools > .md-button:first-child {
margin-left: auto;
margin-right: -0.8rem; }
md-fab-toolbar.md-left .md-toolbar-tools > .md-button:last-child {
margin-right: 8px; }
[dir=rtl] md-fab-toolbar.md-left .md-toolbar-tools > .md-button:last-child {
margin-right: auto;
margin-left: 8px; }
md-fab-toolbar.md-right md-fab-trigger {
left: 0; }
[dir=rtl] md-fab-toolbar.md-right md-fab-trigger {
left: auto;
right: 0; }
md-fab-toolbar.md-right .md-toolbar-tools {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
md-fab-toolbar md-toolbar {
background-color: transparent !important;
pointer-events: none;
z-index: 23; }
md-fab-toolbar md-toolbar .md-toolbar-tools {
padding: 0 20px;
margin-top: 3px; }
md-fab-toolbar md-toolbar .md-fab-action-item {
opacity: 0;
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
-webkit-transition-duration: 0.15s;
transition-duration: 0.15s; }
md-fab-toolbar.md-is-open md-fab-trigger > button {
box-shadow: none; }
md-fab-toolbar.md-is-open md-fab-trigger > button md-icon {
opacity: 0; }
md-fab-toolbar.md-is-open .md-fab-action-item {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1); }

View File

@ -0,0 +1,209 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.fabToolbar');
goog.require('ngmaterial.components.fabActions');
goog.require('ngmaterial.components.fabShared');
goog.require('ngmaterial.core');
(function() {
'use strict';
/**
* @ngdoc module
* @name material.components.fabToolbar
*/
angular
// Declare our module
.module('material.components.fabToolbar', [
'material.core',
'material.components.fabShared',
'material.components.fabActions'
])
// Register our directive
.directive('mdFabToolbar', MdFabToolbarDirective)
// Register our custom animations
.animation('.md-fab-toolbar', MdFabToolbarAnimation)
// Register a service for the animation so that we can easily inject it into unit tests
.service('mdFabToolbarAnimation', MdFabToolbarAnimation);
/**
* @ngdoc directive
* @name mdFabToolbar
* @module material.components.fabToolbar
*
* @restrict E
*
* @description
*
* The `<md-fab-toolbar>` directive is used to present a toolbar of elements (usually `<md-button>`s)
* for quick access to common actions when a floating action button is activated (via click or
* keyboard navigation).
*
* You may also easily position the trigger by applying one one of the following classes to the
* `<md-fab-toolbar>` element:
* - `md-fab-top-left`
* - `md-fab-top-right`
* - `md-fab-bottom-left`
* - `md-fab-bottom-right`
*
* These CSS classes use `position: absolute`, so you need to ensure that the container element
* also uses `position: absolute` or `position: relative` in order for them to work.
*
* @usage
*
* <hljs lang="html">
* <md-fab-toolbar md-direction='left'>
* <md-fab-trigger>
* <md-button aria-label="Add..."><md-icon md-svg-src="/img/icons/plus.svg"></md-icon></md-button>
* </md-fab-trigger>
*
* <md-toolbar>
* <md-fab-actions>
* <md-button aria-label="Add User">
* <md-icon md-svg-src="/img/icons/user.svg"></md-icon>
* </md-button>
*
* <md-button aria-label="Add Group">
* <md-icon md-svg-src="/img/icons/group.svg"></md-icon>
* </md-button>
* </md-fab-actions>
* </md-toolbar>
* </md-fab-toolbar>
* </hljs>
*
* @param {string} md-direction From which direction you would like the toolbar items to appear
* relative to the trigger element. Supports `left` and `right` directions.
* @param {expression=} md-open Programmatically control whether or not the toolbar is visible.
*/
function MdFabToolbarDirective() {
return {
restrict: 'E',
transclude: true,
template: '<div class="md-fab-toolbar-wrapper">' +
' <div class="md-fab-toolbar-content" ng-transclude></div>' +
'</div>',
scope: {
direction: '@?mdDirection',
isOpen: '=?mdOpen'
},
bindToController: true,
controller: 'MdFabController',
controllerAs: 'vm',
link: link
};
function link(scope, element, attributes) {
// Add the base class for animations
element.addClass('md-fab-toolbar');
// Prepend the background element to the trigger's button
element.find('md-fab-trigger').find('button')
.prepend('<div class="md-fab-toolbar-background"></div>');
}
}
function MdFabToolbarAnimation() {
function runAnimation(element, className, done) {
// If no className was specified, don't do anything
if (!className) {
return;
}
var el = element[0];
var ctrl = element.controller('mdFabToolbar');
// Grab the relevant child elements
var backgroundElement = el.querySelector('.md-fab-toolbar-background');
var triggerElement = el.querySelector('md-fab-trigger button');
var toolbarElement = el.querySelector('md-toolbar');
var iconElement = el.querySelector('md-fab-trigger button md-icon');
var actions = element.find('md-fab-actions').children();
// If we have both elements, use them to position the new background
if (triggerElement && backgroundElement) {
// Get our variables
var color = window.getComputedStyle(triggerElement).getPropertyValue('background-color');
var width = el.offsetWidth;
var height = el.offsetHeight;
// Make it twice as big as it should be since we scale from the center
var scale = 2 * (width / triggerElement.offsetWidth);
// Set some basic styles no matter what animation we're doing
backgroundElement.style.backgroundColor = color;
backgroundElement.style.borderRadius = width + 'px';
// If we're open
if (ctrl.isOpen) {
// Turn on toolbar pointer events when closed
toolbarElement.style.pointerEvents = 'inherit';
backgroundElement.style.width = triggerElement.offsetWidth + 'px';
backgroundElement.style.height = triggerElement.offsetHeight + 'px';
backgroundElement.style.transform = 'scale(' + scale + ')';
// Set the next close animation to have the proper delays
backgroundElement.style.transitionDelay = '0ms';
iconElement && (iconElement.style.transitionDelay = '.3s');
// Apply a transition delay to actions
angular.forEach(actions, function(action, index) {
action.style.transitionDelay = (actions.length - index) * 25 + 'ms';
});
} else {
// Turn off toolbar pointer events when closed
toolbarElement.style.pointerEvents = 'none';
// Scale it back down to the trigger's size
backgroundElement.style.transform = 'scale(1)';
// Reset the position
backgroundElement.style.top = '0';
if (element.hasClass('md-right')) {
backgroundElement.style.left = '0';
backgroundElement.style.right = null;
}
if (element.hasClass('md-left')) {
backgroundElement.style.right = '0';
backgroundElement.style.left = null;
}
// Set the next open animation to have the proper delays
backgroundElement.style.transitionDelay = '200ms';
iconElement && (iconElement.style.transitionDelay = '0ms');
// Apply a transition delay to actions
angular.forEach(actions, function(action, index) {
action.style.transitionDelay = 200 + (index * 25) + 'ms';
});
}
}
}
return {
addClass: function(element, className, done) {
runAnimation(element, className, done);
done();
},
removeClass: function(element, className, done) {
runAnimation(element, className, done);
done();
}
};
}
})();
ngmaterial.components.fabToolbar = angular.module("material.components.fabToolbar");

View File

@ -0,0 +1,46 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.0-rc.5-master-26a5fb8
*/
goog.provide('ng.material.components.fabTrigger');
goog.require('ng.material.core');
(function() {
'use strict';
/**
* @ngdoc module
* @name material.components.fabTrigger
*/
angular
.module('material.components.fabTrigger', ['material.core'])
.directive('mdFabTrigger', MdFabTriggerDirective);
/**
* @ngdoc directive
* @name mdFabTrigger
* @module material.components.fabSpeedDial
*
* @restrict E
*
* @description
* The `<md-fab-trigger>` directive is used inside of a `<md-fab-speed-dial>` or
* `<md-fab-toolbar>` directive to mark an element (or elements) as the trigger and setup the
* proper event listeners.
*
* @usage
* See the `<md-fab-speed-dial>` or `<md-fab-toolbar>` directives for example usage.
*/
function MdFabTriggerDirective() {
// TODO: Remove this completely?
return {
restrict: 'E',
require: ['^?mdFabSpeedDial', '^?mdFabToolbar']
};
}
})();
ng.material.components.fabTrigger = angular.module("material.components.fabTrigger");

View File

@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.8.0-rc1-master-91053dc
*/

View File

@ -0,0 +1,77 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-grid-list {
box-sizing: border-box;
display: block;
position: relative; }
md-grid-list md-grid-tile,
md-grid-list md-grid-tile > figure,
md-grid-list md-grid-tile-header,
md-grid-list md-grid-tile-footer {
box-sizing: border-box; }
md-grid-list md-grid-tile {
display: block;
position: absolute; }
md-grid-list md-grid-tile figure {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
height: 100%;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 0;
margin: 0; }
md-grid-list md-grid-tile md-grid-tile-header,
md-grid-list md-grid-tile md-grid-tile-footer {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
height: 48px;
color: #fff;
background: rgba(0, 0, 0, 0.18);
overflow: hidden;
position: absolute;
left: 0;
right: 0; }
md-grid-list md-grid-tile md-grid-tile-header h3,
md-grid-list md-grid-tile md-grid-tile-header h4,
md-grid-list md-grid-tile md-grid-tile-footer h3,
md-grid-list md-grid-tile md-grid-tile-footer h4 {
font-weight: 400;
margin: 0 0 0 16px; }
md-grid-list md-grid-tile md-grid-tile-header h3,
md-grid-list md-grid-tile md-grid-tile-footer h3 {
font-size: 14px; }
md-grid-list md-grid-tile md-grid-tile-header h4,
md-grid-list md-grid-tile md-grid-tile-footer h4 {
font-size: 12px; }
md-grid-list md-grid-tile md-grid-tile-header {
top: 0; }
md-grid-list md-grid-tile md-grid-tile-footer {
bottom: 0; }
@media screen and (-ms-high-contrast: active) {
md-grid-tile {
border: 1px solid #fff; }
md-grid-tile-footer {
border-top: 1px solid #fff; } }

View File

@ -0,0 +1,783 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.gridList');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.gridList
*/
GridListController['$inject'] = ["$mdUtil"];
GridLayoutFactory['$inject'] = ["$mdUtil"];
GridListDirective['$inject'] = ["$interpolate", "$mdConstant", "$mdGridLayout", "$mdMedia"];
GridTileDirective['$inject'] = ["$mdMedia"];
angular.module('material.components.gridList', ['material.core'])
.directive('mdGridList', GridListDirective)
.directive('mdGridTile', GridTileDirective)
.directive('mdGridTileFooter', GridTileCaptionDirective)
.directive('mdGridTileHeader', GridTileCaptionDirective)
.factory('$mdGridLayout', GridLayoutFactory);
/**
* @ngdoc directive
* @name mdGridList
* @module material.components.gridList
* @restrict E
* @description
* Grid lists are an alternative to standard list views. Grid lists are distinct
* from grids used for layouts and other visual presentations.
*
* A grid list is best suited to presenting a homogenous data type, typically
* images, and is optimized for visual comprehension and differentiating between
* like data types.
*
* A grid list is a continuous element consisting of tessellated, regular
* subdivisions called cells that contain tiles (`md-grid-tile`).
*
* <img src="//material-design.storage.googleapis.com/publish/v_2/material_ext_publish/0Bx4BSt6jniD7OVlEaXZ5YmU1Xzg/components_grids_usage2.png"
* style="width: 300px; height: auto; margin-right: 16px;" alt="Concept of grid explained visually">
* <img src="//material-design.storage.googleapis.com/publish/v_2/material_ext_publish/0Bx4BSt6jniD7VGhsOE5idWlJWXM/components_grids_usage3.png"
* style="width: 300px; height: auto;" alt="Grid concepts legend">
*
* Cells are arrayed vertically and horizontally within the grid.
*
* Tiles hold content and can span one or more cells vertically or horizontally.
*
* ### Responsive Attributes
*
* The `md-grid-list` directive supports "responsive" attributes, which allow
* different `md-cols`, `md-gutter` and `md-row-height` values depending on the
* currently matching media query.
*
* In order to set a responsive attribute, first define the fallback value with
* the standard attribute name, then add additional attributes with the
* following convention: `{base-attribute-name}-{media-query-name}="{value}"`
* (ie. `md-cols-lg="8"`)
*
* @param {number} md-cols Number of columns in the grid.
* @param {string} md-row-height One of
* <ul>
* <li>CSS length - Fixed height rows (eg. `8px` or `1rem`)</li>
* <li>`{width}:{height}` - Ratio of width to height (eg.
* `md-row-height="16:9"`)</li>
* <li>`"fit"` - Height will be determined by subdividing the available
* height by the number of rows</li>
* </ul>
* @param {string=} md-gutter The amount of space between tiles in CSS units
* (default 1px)
* @param {expression=} md-on-layout Expression to evaluate after layout. Event
* object is available as `$event`, and contains performance information.
*
* @usage
* Basic:
* <hljs lang="html">
* <md-grid-list md-cols="5" md-gutter="1em" md-row-height="4:3">
* <md-grid-tile></md-grid-tile>
* </md-grid-list>
* </hljs>
*
* Fixed-height rows:
* <hljs lang="html">
* <md-grid-list md-cols="4" md-row-height="200px" ...>
* <md-grid-tile></md-grid-tile>
* </md-grid-list>
* </hljs>
*
* Fit rows:
* <hljs lang="html">
* <md-grid-list md-cols="4" md-row-height="fit" style="height: 400px;" ...>
* <md-grid-tile></md-grid-tile>
* </md-grid-list>
* </hljs>
*
* Using responsive attributes:
* <hljs lang="html">
* <md-grid-list
* md-cols-sm="2"
* md-cols-md="4"
* md-cols-lg="8"
* md-cols-gt-lg="12"
* ...>
* <md-grid-tile></md-grid-tile>
* </md-grid-list>
* </hljs>
*/
function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia) {
return {
restrict: 'E',
controller: GridListController,
scope: {
mdOnLayout: '&'
},
link: postLink
};
function postLink(scope, element, attrs, ctrl) {
element.addClass('_md'); // private md component indicator for styling
// Apply semantics
element.attr('role', 'list');
// Provide the controller with a way to trigger layouts.
ctrl.layoutDelegate = layoutDelegate;
var invalidateLayout = angular.bind(ctrl, ctrl.invalidateLayout),
unwatchAttrs = watchMedia();
scope.$on('$destroy', unwatchMedia);
/**
* Watches for changes in media, invalidating layout as necessary.
*/
function watchMedia() {
for (var mediaName in $mdConstant.MEDIA) {
$mdMedia(mediaName); // initialize
$mdMedia.getQuery($mdConstant.MEDIA[mediaName])
.addListener(invalidateLayout);
}
return $mdMedia.watchResponsiveAttributes(
['md-cols', 'md-row-height', 'md-gutter'], attrs, layoutIfMediaMatch);
}
function unwatchMedia() {
ctrl.layoutDelegate = angular.noop;
unwatchAttrs();
for (var mediaName in $mdConstant.MEDIA) {
$mdMedia.getQuery($mdConstant.MEDIA[mediaName])
.removeListener(invalidateLayout);
}
}
/**
* Performs grid layout if the provided mediaName matches the currently
* active media type.
*/
function layoutIfMediaMatch(mediaName) {
if (mediaName == null) {
// TODO(shyndman): It would be nice to only layout if we have
// instances of attributes using this media type
ctrl.invalidateLayout();
} else if ($mdMedia(mediaName)) {
ctrl.invalidateLayout();
}
}
var lastLayoutProps;
/**
* Invokes the layout engine, and uses its results to lay out our
* tile elements.
*
* @param {boolean} tilesInvalidated Whether tiles have been
* added/removed/moved since the last layout. This is to avoid situations
* where tiles are replaced with properties identical to their removed
* counterparts.
*/
function layoutDelegate(tilesInvalidated) {
var tiles = getTileElements();
var props = {
tileSpans: getTileSpans(tiles),
colCount: getColumnCount(),
rowMode: getRowMode(),
rowHeight: getRowHeight(),
gutter: getGutter()
};
if (!tilesInvalidated && angular.equals(props, lastLayoutProps)) {
return;
}
var performance =
$mdGridLayout(props.colCount, props.tileSpans, tiles)
.map(function(tilePositions, rowCount) {
return {
grid: {
element: element,
style: getGridStyle(props.colCount, rowCount,
props.gutter, props.rowMode, props.rowHeight)
},
tiles: tilePositions.map(function(ps, i) {
return {
element: angular.element(tiles[i]),
style: getTileStyle(ps.position, ps.spans,
props.colCount, rowCount,
props.gutter, props.rowMode, props.rowHeight)
}
})
}
})
.reflow()
.performance();
// Report layout
scope.mdOnLayout({
$event: {
performance: performance
}
});
lastLayoutProps = props;
}
// Use $interpolate to do some simple string interpolation as a convenience.
var startSymbol = $interpolate.startSymbol();
var endSymbol = $interpolate.endSymbol();
// Returns an expression wrapped in the interpolator's start and end symbols.
function expr(exprStr) {
return startSymbol + exprStr + endSymbol;
}
// The amount of space a single 1x1 tile would take up (either width or height), used as
// a basis for other calculations. This consists of taking the base size percent (as would be
// if evenly dividing the size between cells), and then subtracting the size of one gutter.
// However, since there are no gutters on the edges, each tile only uses a fration
// (gutterShare = numGutters / numCells) of the gutter size. (Imagine having one gutter per
// tile, and then breaking up the extra gutter on the edge evenly among the cells).
var UNIT = $interpolate(expr('share') + '% - (' + expr('gutter') + ' * ' + expr('gutterShare') + ')');
// The horizontal or vertical position of a tile, e.g., the 'top' or 'left' property value.
// The position comes the size of a 1x1 tile plus gutter for each previous tile in the
// row/column (offset).
var POSITION = $interpolate('calc((' + expr('unit') + ' + ' + expr('gutter') + ') * ' + expr('offset') + ')');
// The actual size of a tile, e.g., width or height, taking rowSpan or colSpan into account.
// This is computed by multiplying the base unit by the rowSpan/colSpan, and then adding back
// in the space that the gutter would normally have used (which was already accounted for in
// the base unit calculation).
var DIMENSION = $interpolate('calc((' + expr('unit') + ') * ' + expr('span') + ' + (' + expr('span') + ' - 1) * ' + expr('gutter') + ')');
/**
* Gets the styles applied to a tile element described by the given parameters.
* @param {{row: number, col: number}} position The row and column indices of the tile.
* @param {{row: number, col: number}} spans The rowSpan and colSpan of the tile.
* @param {number} colCount The number of columns.
* @param {number} rowCount The number of rows.
* @param {string} gutter The amount of space between tiles. This will be something like
* '5px' or '2em'.
* @param {string} rowMode The row height mode. Can be one of:
* 'fixed': all rows have a fixed size, given by rowHeight,
* 'ratio': row height defined as a ratio to width, or
* 'fit': fit to the grid-list element height, divinding evenly among rows.
* @param {string|number} rowHeight The height of a row. This is only used for 'fixed' mode and
* for 'ratio' mode. For 'ratio' mode, this is the *ratio* of width-to-height (e.g., 0.75).
* @returns {Object} Map of CSS properties to be applied to the style element. Will define
* values for top, left, width, height, marginTop, and paddingTop.
*/
function getTileStyle(position, spans, colCount, rowCount, gutter, rowMode, rowHeight) {
// TODO(shyndman): There are style caching opportunities here.
// Percent of the available horizontal space that one column takes up.
var hShare = (1 / colCount) * 100;
// Fraction of the gutter size that each column takes up.
var hGutterShare = (colCount - 1) / colCount;
// Base horizontal size of a column.
var hUnit = UNIT({share: hShare, gutterShare: hGutterShare, gutter: gutter});
// The width and horizontal position of each tile is always calculated the same way, but the
// height and vertical position depends on the rowMode.
var ltr = document.dir != 'rtl' && document.body.dir != 'rtl';
var style = ltr ? {
left: POSITION({ unit: hUnit, offset: position.col, gutter: gutter }),
width: DIMENSION({ unit: hUnit, span: spans.col, gutter: gutter }),
// resets
paddingTop: '',
marginTop: '',
top: '',
height: ''
} : {
right: POSITION({ unit: hUnit, offset: position.col, gutter: gutter }),
width: DIMENSION({ unit: hUnit, span: spans.col, gutter: gutter }),
// resets
paddingTop: '',
marginTop: '',
top: '',
height: ''
};
switch (rowMode) {
case 'fixed':
// In fixed mode, simply use the given rowHeight.
style.top = POSITION({ unit: rowHeight, offset: position.row, gutter: gutter });
style.height = DIMENSION({ unit: rowHeight, span: spans.row, gutter: gutter });
break;
case 'ratio':
// Percent of the available vertical space that one row takes up. Here, rowHeight holds
// the ratio value. For example, if the width:height ratio is 4:3, rowHeight = 1.333.
var vShare = hShare / rowHeight;
// Base veritcal size of a row.
var vUnit = UNIT({ share: vShare, gutterShare: hGutterShare, gutter: gutter });
// padidngTop and marginTop are used to maintain the given aspect ratio, as
// a percentage-based value for these properties is applied to the *width* of the
// containing block. See http://www.w3.org/TR/CSS2/box.html#margin-properties
style.paddingTop = DIMENSION({ unit: vUnit, span: spans.row, gutter: gutter});
style.marginTop = POSITION({ unit: vUnit, offset: position.row, gutter: gutter });
break;
case 'fit':
// Fraction of the gutter size that each column takes up.
var vGutterShare = (rowCount - 1) / rowCount;
// Percent of the available vertical space that one row takes up.
var vShare = (1 / rowCount) * 100;
// Base vertical size of a row.
var vUnit = UNIT({share: vShare, gutterShare: vGutterShare, gutter: gutter});
style.top = POSITION({unit: vUnit, offset: position.row, gutter: gutter});
style.height = DIMENSION({unit: vUnit, span: spans.row, gutter: gutter});
break;
}
return style;
}
function getGridStyle(colCount, rowCount, gutter, rowMode, rowHeight) {
var style = {};
switch(rowMode) {
case 'fixed':
style.height = DIMENSION({ unit: rowHeight, span: rowCount, gutter: gutter });
style.paddingBottom = '';
break;
case 'ratio':
// rowHeight is width / height
var hGutterShare = colCount === 1 ? 0 : (colCount - 1) / colCount,
hShare = (1 / colCount) * 100,
vShare = hShare * (1 / rowHeight),
vUnit = UNIT({ share: vShare, gutterShare: hGutterShare, gutter: gutter });
style.height = '';
style.paddingBottom = DIMENSION({ unit: vUnit, span: rowCount, gutter: gutter});
break;
case 'fit':
// noop, as the height is user set
break;
}
return style;
}
function getTileElements() {
return [].filter.call(element.children(), function(ele) {
return ele.tagName == 'MD-GRID-TILE' && !ele.$$mdDestroyed;
});
}
/**
* Gets an array of objects containing the rowspan and colspan for each tile.
* @returns {Array<{row: number, col: number}>}
*/
function getTileSpans(tileElements) {
return [].map.call(tileElements, function(ele) {
var ctrl = angular.element(ele).controller('mdGridTile');
return {
row: parseInt(
$mdMedia.getResponsiveAttribute(ctrl.$attrs, 'md-rowspan'), 10) || 1,
col: parseInt(
$mdMedia.getResponsiveAttribute(ctrl.$attrs, 'md-colspan'), 10) || 1
};
});
}
function getColumnCount() {
var colCount = parseInt($mdMedia.getResponsiveAttribute(attrs, 'md-cols'), 10);
if (isNaN(colCount)) {
throw 'md-grid-list: md-cols attribute was not found, or contained a non-numeric value';
}
return colCount;
}
function getGutter() {
return applyDefaultUnit($mdMedia.getResponsiveAttribute(attrs, 'md-gutter') || 1);
}
function getRowHeight() {
var rowHeight = $mdMedia.getResponsiveAttribute(attrs, 'md-row-height');
if (!rowHeight) {
throw 'md-grid-list: md-row-height attribute was not found';
}
switch (getRowMode()) {
case 'fixed':
return applyDefaultUnit(rowHeight);
case 'ratio':
var whRatio = rowHeight.split(':');
return parseFloat(whRatio[0]) / parseFloat(whRatio[1]);
case 'fit':
return 0; // N/A
}
}
function getRowMode() {
var rowHeight = $mdMedia.getResponsiveAttribute(attrs, 'md-row-height');
if (!rowHeight) {
throw 'md-grid-list: md-row-height attribute was not found';
}
if (rowHeight == 'fit') {
return 'fit';
} else if (rowHeight.indexOf(':') !== -1) {
return 'ratio';
} else {
return 'fixed';
}
}
function applyDefaultUnit(val) {
return /\D$/.test(val) ? val : val + 'px';
}
}
}
/* ngInject */
function GridListController($mdUtil) {
this.layoutInvalidated = false;
this.tilesInvalidated = false;
this.$timeout_ = $mdUtil.nextTick;
this.layoutDelegate = angular.noop;
}
GridListController.prototype = {
invalidateTiles: function() {
this.tilesInvalidated = true;
this.invalidateLayout();
},
invalidateLayout: function() {
if (this.layoutInvalidated) {
return;
}
this.layoutInvalidated = true;
this.$timeout_(angular.bind(this, this.layout));
},
layout: function() {
try {
this.layoutDelegate(this.tilesInvalidated);
} finally {
this.layoutInvalidated = false;
this.tilesInvalidated = false;
}
}
};
/* ngInject */
function GridLayoutFactory($mdUtil) {
var defaultAnimator = GridTileAnimator;
/**
* Set the reflow animator callback
*/
GridLayout.animateWith = function(customAnimator) {
defaultAnimator = !angular.isFunction(customAnimator) ? GridTileAnimator : customAnimator;
};
return GridLayout;
/**
* Publish layout function
*/
function GridLayout(colCount, tileSpans) {
var self, layoutInfo, gridStyles, layoutTime, mapTime, reflowTime;
layoutTime = $mdUtil.time(function() {
layoutInfo = calculateGridFor(colCount, tileSpans);
});
return self = {
/**
* An array of objects describing each tile's position in the grid.
*/
layoutInfo: function() {
return layoutInfo;
},
/**
* Maps grid positioning to an element and a set of styles using the
* provided updateFn.
*/
map: function(updateFn) {
mapTime = $mdUtil.time(function() {
var info = self.layoutInfo();
gridStyles = updateFn(info.positioning, info.rowCount);
});
return self;
},
/**
* Default animator simply sets the element.css( <styles> ). An alternate
* animator can be provided as an argument. The function has the following
* signature:
*
* function({grid: {element: JQLite, style: Object}, tiles: Array<{element: JQLite, style: Object}>)
*/
reflow: function(animatorFn) {
reflowTime = $mdUtil.time(function() {
var animator = animatorFn || defaultAnimator;
animator(gridStyles.grid, gridStyles.tiles);
});
return self;
},
/**
* Timing for the most recent layout run.
*/
performance: function() {
return {
tileCount: tileSpans.length,
layoutTime: layoutTime,
mapTime: mapTime,
reflowTime: reflowTime,
totalTime: layoutTime + mapTime + reflowTime
};
}
};
}
/**
* Default Gridlist animator simple sets the css for each element;
* NOTE: any transitions effects must be manually set in the CSS.
* e.g.
*
* md-grid-tile {
* transition: all 700ms ease-out 50ms;
* }
*
*/
function GridTileAnimator(grid, tiles) {
grid.element.css(grid.style);
tiles.forEach(function(t) {
t.element.css(t.style);
})
}
/**
* Calculates the positions of tiles.
*
* The algorithm works as follows:
* An Array<Number> with length colCount (spaceTracker) keeps track of
* available tiling positions, where elements of value 0 represents an
* empty position. Space for a tile is reserved by finding a sequence of
* 0s with length <= than the tile's colspan. When such a space has been
* found, the occupied tile positions are incremented by the tile's
* rowspan value, as these positions have become unavailable for that
* many rows.
*
* If the end of a row has been reached without finding space for the
* tile, spaceTracker's elements are each decremented by 1 to a minimum
* of 0. Rows are searched in this fashion until space is found.
*/
function calculateGridFor(colCount, tileSpans) {
var curCol = 0,
curRow = 0,
spaceTracker = newSpaceTracker();
return {
positioning: tileSpans.map(function(spans, i) {
return {
spans: spans,
position: reserveSpace(spans, i)
};
}),
rowCount: curRow + Math.max.apply(Math, spaceTracker)
};
function reserveSpace(spans, i) {
if (spans.col > colCount) {
throw 'md-grid-list: Tile at position ' + i + ' has a colspan ' +
'(' + spans.col + ') that exceeds the column count ' +
'(' + colCount + ')';
}
var start = 0,
end = 0;
// TODO(shyndman): This loop isn't strictly necessary if you can
// determine the minimum number of rows before a space opens up. To do
// this, recognize that you've iterated across an entire row looking for
// space, and if so fast-forward by the minimum rowSpan count. Repeat
// until the required space opens up.
while (end - start < spans.col) {
if (curCol >= colCount) {
nextRow();
continue;
}
start = spaceTracker.indexOf(0, curCol);
if (start === -1 || (end = findEnd(start + 1)) === -1) {
start = end = 0;
nextRow();
continue;
}
curCol = end + 1;
}
adjustRow(start, spans.col, spans.row);
curCol = start + spans.col;
return {
col: start,
row: curRow
};
}
function nextRow() {
curCol = 0;
curRow++;
adjustRow(0, colCount, -1); // Decrement row spans by one
}
function adjustRow(from, cols, by) {
for (var i = from; i < from + cols; i++) {
spaceTracker[i] = Math.max(spaceTracker[i] + by, 0);
}
}
function findEnd(start) {
var i;
for (i = start; i < spaceTracker.length; i++) {
if (spaceTracker[i] !== 0) {
return i;
}
}
if (i === spaceTracker.length) {
return i;
}
}
function newSpaceTracker() {
var tracker = [];
for (var i = 0; i < colCount; i++) {
tracker.push(0);
}
return tracker;
}
}
}
/**
* @ngdoc directive
* @name mdGridTile
* @module material.components.gridList
* @restrict E
* @description
* Tiles contain the content of an `md-grid-list`. They span one or more grid
* cells vertically or horizontally, and use `md-grid-tile-{footer,header}` to
* display secondary content.
*
* ### Responsive Attributes
*
* The `md-grid-tile` directive supports "responsive" attributes, which allow
* different `md-rowspan` and `md-colspan` values depending on the currently
* matching media query.
*
* In order to set a responsive attribute, first define the fallback value with
* the standard attribute name, then add additional attributes with the
* following convention: `{base-attribute-name}-{media-query-name}="{value}"`
* (ie. `md-colspan-sm="4"`)
*
* @param {number=} md-colspan The number of columns to span (default 1). Cannot
* exceed the number of columns in the grid. Supports interpolation.
* @param {number=} md-rowspan The number of rows to span (default 1). Supports
* interpolation.
*
* @usage
* With header:
* <hljs lang="html">
* <md-grid-tile>
* <md-grid-tile-header>
* <h3>This is a header</h3>
* </md-grid-tile-header>
* </md-grid-tile>
* </hljs>
*
* With footer:
* <hljs lang="html">
* <md-grid-tile>
* <md-grid-tile-footer>
* <h3>This is a footer</h3>
* </md-grid-tile-footer>
* </md-grid-tile>
* </hljs>
*
* Spanning multiple rows/columns:
* <hljs lang="html">
* <md-grid-tile md-colspan="2" md-rowspan="3">
* </md-grid-tile>
* </hljs>
*
* Responsive attributes:
* <hljs lang="html">
* <md-grid-tile md-colspan="1" md-colspan-sm="3" md-colspan-md="5">
* </md-grid-tile>
* </hljs>
*/
function GridTileDirective($mdMedia) {
return {
restrict: 'E',
require: '^mdGridList',
template: '<figure ng-transclude></figure>',
transclude: true,
scope: {},
// Simple controller that exposes attributes to the grid directive
controller: ["$attrs", function($attrs) {
this.$attrs = $attrs;
}],
link: postLink
};
function postLink(scope, element, attrs, gridCtrl) {
// Apply semantics
element.attr('role', 'listitem');
// If our colspan or rowspan changes, trigger a layout
var unwatchAttrs = $mdMedia.watchResponsiveAttributes(['md-colspan', 'md-rowspan'],
attrs, angular.bind(gridCtrl, gridCtrl.invalidateLayout));
// Tile registration/deregistration
gridCtrl.invalidateTiles();
scope.$on('$destroy', function() {
// Mark the tile as destroyed so it is no longer considered in layout,
// even if the DOM element sticks around (like during a leave animation)
element[0].$$mdDestroyed = true;
unwatchAttrs();
gridCtrl.invalidateLayout();
});
if (angular.isDefined(scope.$parent.$index)) {
scope.$watch(function() { return scope.$parent.$index; },
function indexChanged(newIdx, oldIdx) {
if (newIdx === oldIdx) {
return;
}
gridCtrl.invalidateTiles();
});
}
}
}
function GridTileCaptionDirective() {
return {
template: '<figcaption ng-transclude></figcaption>',
transclude: true
};
}
ngmaterial.components.gridList = angular.module("material.components.gridList");

View File

@ -0,0 +1,14 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-icon.md-THEME_NAME-theme {
color: '{{foreground-2}}'; }
md-icon.md-THEME_NAME-theme.md-primary {
color: '{{primary-color}}'; }
md-icon.md-THEME_NAME-theme.md-accent {
color: '{{accent-color}}'; }
md-icon.md-THEME_NAME-theme.md-warn {
color: '{{warn-color}}'; }

View File

@ -0,0 +1,22 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-icon {
margin: auto;
background-repeat: no-repeat no-repeat;
display: inline-block;
vertical-align: middle;
fill: currentColor;
height: 24px;
width: 24px;
min-height: 24px;
min-width: 24px; }
md-icon svg {
pointer-events: none;
display: block; }
md-icon[md-font-icon] {
line-height: 24px;
width: auto; }

View File

@ -0,0 +1,931 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.icon');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.icon
* @description
* Icon
*/
angular.module('material.components.icon', ['material.core']);
angular
.module('material.components.icon')
.directive('mdIcon', ['$mdIcon', '$mdTheming', '$mdAria', '$sce', mdIconDirective]);
/**
* @ngdoc directive
* @name mdIcon
* @module material.components.icon
*
* @restrict E
*
* @description
* The `md-icon` directive makes it easier to use vector-based icons in your app (as opposed to
* raster-based icons types like PNG). The directive supports both icon fonts and SVG icons.
*
* Icons should be considered view-only elements that should not be used directly as buttons; instead nest a `<md-icon>`
* inside a `md-button` to add hover and click features.
*
* ### Icon fonts
* Icon fonts are a technique in which you use a font where the glyphs in the font are
* your icons instead of text. Benefits include a straightforward way to bundle everything into a
* single HTTP request, simple scaling, easy color changing, and more.
*
* `md-icon` lets you consume an icon font by letting you reference specific icons in that font
* by name rather than character code.
*
* ### SVG
* For SVGs, the problem with using `<img>` or a CSS `background-image` is that you can't take
* advantage of some SVG features, such as styling specific parts of the icon with CSS or SVG
* animation.
*
* `md-icon` makes it easier to use SVG icons by *inlining* the SVG into an `<svg>` element in the
* document. The most straightforward way of referencing an SVG icon is via URL, just like a
* traditional `<img>`. `$mdIconProvider`, as a convenience, lets you _name_ an icon so you can
* reference it by name instead of URL throughout your templates.
*
* Additionally, you may not want to make separate HTTP requests for every icon, so you can bundle
* your SVG icons together and pre-load them with $mdIconProvider as an icon set. An icon set can
* also be given a name, which acts as a namespace for individual icons, so you can reference them
* like `"social:cake"`.
*
* When using SVGs, both external SVGs (via URLs) or sets of SVGs [from icon sets] can be
* easily loaded and used. When using font-icons, developers must follow three (3) simple steps:
*
* <ol>
* <li>Load the font library. e.g.<br/>
* `<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
* rel="stylesheet">`
* </li>
* <li>
* Use either (a) font-icon class names or (b) a fontset and a font ligature to render the font glyph by
* using its textual name _or_ numerical character reference. Note that `material-icons` is the default fontset when
* none is specified.
* </li>
* <li> Use any of the following templates: <br/>
* <ul>
* <li>`<md-icon md-font-icon="classname"></md-icon>`</li>
* <li>`<md-icon md-font-set="font library classname or alias">textual_name</md-icon>`</li>
* <li>`<md-icon> numerical_character_reference </md-icon>`</li>
* <li>`<md-icon ng_bind="'textual_name'"></md-icon>`</li>
* <li>`<md-icon ng-bind="scopeVariable"></md-icon>`</li>
* </ul>
* </li>
* </ol>
*
* Full details for these steps can be found:
*
* <ul>
* <li>http://google.github.io/material-design-icons/</li>
* <li>http://google.github.io/material-design-icons/#icon-font-for-the-web</li>
* </ul>
*
* The Material Design icon style <code>.material-icons</code> and the icon font references are published in
* Material Design Icons:
*
* <ul>
* <li>https://design.google.com/icons/</li>
* <li>https://design.google.com/icons/#ic_accessibility</li>
* </ul>
*
* ### Localization
*
* Because an `md-icon` element's text content is not intended to translated, it is recommended to declare the text
* content for an `md-icon` element in its start tag. Instead of using the HTML text content, consider using `ng-bind`
* with a scope variable or literal string.
*
* Examples:
*
* <ul>
* <li>`<md-icon ng-bind="myIconVariable"></md-icon>`</li>
* <li>`<md-icon ng-bind="'menu'"></md-icon>`
* </ul>
*
* <h2 id="material_design_icons">Material Design Icons</h2>
* Using the Material Design Icon-Selector, developers can easily and quickly search for a Material Design font-icon and
* determine its textual name and character reference code. Click on any icon to see the slide-up information
* panel with details regarding a SVG download or information on the font-icon usage.
*
* <a href="https://www.google.com/design/icons/#ic_accessibility" target="_blank" style="border-bottom:none;">
* <img src="https://cloud.githubusercontent.com/assets/210413/7902490/fe8dd14c-0780-11e5-98fb-c821cc6475e6.png"
* aria-label="Material Design Icon-Selector" style="max-width:75%;padding-left:10%">
* </a>
*
* <span class="image_caption">
* Click on the image above to link to the
* <a href="https://design.google.com/icons/#ic_accessibility" target="_blank">Material Design Icon-Selector</a>.
* </span>
*
* @param {string} md-font-icon String name of CSS icon associated with the font-face will be used
* to render the icon. Requires the fonts and the named CSS styles to be preloaded.
* @param {string} md-font-set CSS style name associated with the font library; which will be assigned as
* the class for the font-icon ligature. This value may also be an alias that is used to lookup the classname;
* internally use `$mdIconProvider.fontSet(<alias>)` to determine the style name.
* @param {string} md-svg-src String URL (or expression) used to load, cache, and display an
* external SVG.
* @param {string} md-svg-icon md-svg-icon String name used for lookup of the icon from the internal cache;
* interpolated strings or expressions may also be used. Specific set names can be used with
* the syntax `<set name>:<icon name>`.<br/><br/>
* To use icon sets, developers are required to pre-register the sets using the `$mdIconProvider` service.
* @param {string=} aria-label Labels icon for accessibility. If an empty string is provided, icon
* will be hidden from accessibility layer with `aria-hidden="true"`. If there's no aria-label on the icon
* nor a label on the parent element, a warning will be logged to the console.
* @param {string=} alt Labels icon for accessibility. If an empty string is provided, icon
* will be hidden from accessibility layer with `aria-hidden="true"`. If there's no alt on the icon
* nor a label on the parent element, a warning will be logged to the console.
*
* @usage
* When using SVGs:
* <hljs lang="html">
*
* <!-- Icon ID; may contain optional icon set prefix; icons must registered using $mdIconProvider -->
* <md-icon md-svg-icon="social:android" aria-label="android " ></md-icon>
*
* <!-- Icon urls; may be preloaded in templateCache -->
* <md-icon md-svg-src="/android.svg" aria-label="android " ></md-icon>
* <md-icon md-svg-src="{{ getAndroid() }}" aria-label="android " ></md-icon>
*
* </hljs>
*
* Use the <code>$mdIconProvider</code> to configure your application with
* svg iconsets.
*
* <hljs lang="js">
* angular.module('appSvgIconSets', ['ngMaterial'])
* .controller('DemoCtrl', function($scope) {})
* .config(function($mdIconProvider) {
* $mdIconProvider
* .iconSet('social', 'img/icons/sets/social-icons.svg', 24)
* .defaultIconSet('img/icons/sets/core-icons.svg', 24);
* });
* </hljs>
*
*
* When using Font Icons with classnames:
* <hljs lang="html">
*
* <md-icon md-font-icon="android" aria-label="android" ></md-icon>
* <md-icon class="icon_home" aria-label="Home" ></md-icon>
*
* </hljs>
*
* When using Material Font Icons with ligatures:
* <hljs lang="html">
* <!--
* For Material Design Icons
* The class '.material-icons' is auto-added if a style has NOT been specified
* since `material-icons` is the default fontset. So your markup:
* -->
* <md-icon> face </md-icon>
* <!-- becomes this at runtime: -->
* <md-icon md-font-set="material-icons"> face </md-icon>
* <!-- If the fontset does not support ligature names, then we need to use the ligature unicode.-->
* <md-icon> &#xE87C; </md-icon>
* <!-- The class '.material-icons' must be manually added if other styles are also specified-->
* <md-icon class="material-icons md-light md-48"> face </md-icon>
* </hljs>
*
* When using other Font-Icon libraries:
*
* <hljs lang="js">
* // Specify a font-icon style alias
* angular.config(function($mdIconProvider) {
* $mdIconProvider.fontSet('md', 'material-icons');
* });
* </hljs>
*
* <hljs lang="html">
* <md-icon md-font-set="md">favorite</md-icon>
* </hljs>
*
*/
function mdIconDirective($mdIcon, $mdTheming, $mdAria, $sce) {
return {
restrict: 'E',
link : postLink
};
/**
* Directive postLink
* Supports embedded SVGs, font-icons, & external SVGs
*/
function postLink(scope, element, attr) {
$mdTheming(element);
var lastFontIcon = attr.mdFontIcon;
var lastFontSet = $mdIcon.fontSet(attr.mdFontSet);
prepareForFontIcon();
attr.$observe('mdFontIcon', fontIconChanged);
attr.$observe('mdFontSet', fontIconChanged);
// Keep track of the content of the svg src so we can compare against it later to see if the
// attribute is static (and thus safe).
var originalSvgSrc = element[0].getAttribute(attr.$attr.mdSvgSrc);
// If using a font-icon, then the textual name of the icon itself
// provides the aria-label.
var attrName = attr.$normalize(attr.$attr.mdSvgIcon || attr.$attr.mdSvgSrc || '');
/* Provide a default accessibility role of img */
if (!attr.role) {
$mdAria.expect(element, 'role', 'img');
/* manually update attr variable */
attr.role = 'img';
}
/* Don't process ARIA if already valid */
if ( attr.role === "img" && !attr.ariaHidden && !$mdAria.hasAriaLabel(element) ) {
var iconName;
if (attr.alt) {
/* Use alt text by default if available */
$mdAria.expect(element, 'aria-label', attr.alt);
} else if ($mdAria.parentHasAriaLabel(element, 2)) {
/* Parent has ARIA so we will assume it will describe the image */
$mdAria.expect(element, 'aria-hidden', 'true');
} else if (iconName = (attr.mdFontIcon || attr.mdSvgIcon || element.text())) {
/* Use icon name as aria-label */
$mdAria.expect(element, 'aria-label', iconName);
} else {
/* No label found */
$mdAria.expect(element, 'aria-hidden', 'true');
}
}
if (attrName) {
// Use either pre-configured SVG or URL source, respectively.
attr.$observe(attrName, function(attrVal) {
element.empty();
if (attrVal) {
$mdIcon(attrVal)
.then(function(svg) {
element.empty();
element.append(svg);
});
}
});
}
function prepareForFontIcon() {
if (!attr.mdSvgIcon && !attr.mdSvgSrc) {
if (attr.mdFontIcon) {
element.addClass('md-font ' + attr.mdFontIcon);
}
element.addClass(lastFontSet);
}
}
function fontIconChanged() {
if (!attr.mdSvgIcon && !attr.mdSvgSrc) {
if (attr.mdFontIcon) {
element.removeClass(lastFontIcon);
element.addClass(attr.mdFontIcon);
lastFontIcon = attr.mdFontIcon;
}
var fontSet = $mdIcon.fontSet(attr.mdFontSet);
if (lastFontSet !== fontSet) {
element.removeClass(lastFontSet);
element.addClass(fontSet);
lastFontSet = fontSet;
}
}
}
}
}
MdIconService['$inject'] = ["config", "$templateRequest", "$q", "$log", "$mdUtil", "$sce"];angular
.module('material.components.icon')
.constant('$$mdSvgRegistry', {
'mdTabsArrow': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwb2x5Z29uIHBvaW50cz0iMTUuNCw3LjQgMTQsNiA4LDEyIDE0LDE4IDE1LjQsMTYuNiAxMC44LDEyICIvPjwvZz48L3N2Zz4=',
'mdClose': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik0xOSA2LjQxbC0xLjQxLTEuNDEtNS41OSA1LjU5LTUuNTktNS41OS0xLjQxIDEuNDEgNS41OSA1LjU5LTUuNTkgNS41OSAxLjQxIDEuNDEgNS41OS01LjU5IDUuNTkgNS41OSAxLjQxLTEuNDEtNS41OS01LjU5eiIvPjwvZz48L3N2Zz4=',
'mdCancel': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik0xMiAyYy01LjUzIDAtMTAgNC40Ny0xMCAxMHM0LjQ3IDEwIDEwIDEwIDEwLTQuNDcgMTAtMTAtNC40Ny0xMC0xMC0xMHptNSAxMy41OWwtMS40MSAxLjQxLTMuNTktMy41OS0zLjU5IDMuNTktMS40MS0xLjQxIDMuNTktMy41OS0zLjU5LTMuNTkgMS40MS0xLjQxIDMuNTkgMy41OSAzLjU5LTMuNTkgMS40MSAxLjQxLTMuNTkgMy41OSAzLjU5IDMuNTl6Ii8+PC9nPjwvc3ZnPg==',
'mdMenu': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0zLDZIMjFWOEgzVjZNMywxMUgyMVYxM0gzVjExTTMsMTZIMjFWMThIM1YxNloiIC8+PC9zdmc+',
'mdToggleArrow': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgNDggNDgiPjxwYXRoIGQ9Ik0yNCAxNmwtMTIgMTIgMi44MyAyLjgzIDkuMTctOS4xNyA5LjE3IDkuMTcgMi44My0yLjgzeiIvPjxwYXRoIGQ9Ik0wIDBoNDh2NDhoLTQ4eiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==',
'mdCalendar': 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTkgM2gtMVYxaC0ydjJIOFYxSDZ2Mkg1Yy0xLjExIDAtMS45OS45LTEuOTkgMkwzIDE5YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjVjMC0xLjEtLjktMi0yLTJ6bTAgMTZINVY4aDE0djExek03IDEwaDV2NUg3eiIvPjwvc3ZnPg==',
'mdChecked': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz48L2c+PC9zdmc+'
})
.provider('$mdIcon', MdIconProvider);
/**
* @ngdoc service
* @name $mdIconProvider
* @module material.components.icon
*
* @description
* `$mdIconProvider` is used only to register icon IDs with URLs. These configuration features allow
* icons and icon sets to be pre-registered and associated with source URLs **before** the `<md-icon />`
* directives are compiled.
*
* If using font-icons, the developer is responsible for loading the fonts.
*
* If using SVGs, loading of the actual svg files are deferred to on-demand requests and are loaded
* internally by the `$mdIcon` service using the `$templateRequest` service. When an SVG is
* requested by name/ID, the `$mdIcon` service searches its registry for the associated source URL;
* that URL is used to on-demand load and parse the SVG dynamically.
*
* The `$templateRequest` service expects the icons source to be loaded over trusted URLs.<br/>
* This means, when loading icons from an external URL, you have to trust the URL in the `$sceDelegateProvider`.
*
* <hljs lang="js">
* app.config(function($sceDelegateProvider) {
* $sceDelegateProvider.resourceUrlWhitelist([
* // Adding 'self' to the whitelist, will allow requests from the current origin.
* 'self',
* // Using double asterisks here, will allow all URLs to load.
* // We recommend to only specify the given domain you want to allow.
* '**'
* ]);
* });
* </hljs>
*
* Read more about the [$sceDelegateProvider](https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider).
*
* **Notice:** Most font-icons libraries do not support ligatures (for example `fontawesome`).<br/>
* In such cases you are not able to use the icon's ligature name - Like so:
*
* <hljs lang="html">
* <md-icon md-font-set="fa">fa-bell</md-icon>
* </hljs>
*
* You should instead use the given unicode, instead of the ligature name.
*
* <p ng-hide="true"> ##// Notice we can't use a hljs element here, because the characters will be escaped.</p>
* ```html
* <md-icon md-font-set="fa">&#xf0f3</md-icon>
* ```
*
* All unicode ligatures are prefixed with the `&#x` string.
*
* @usage
* <hljs lang="js">
* app.config(function($mdIconProvider) {
*
* // Configure URLs for icons specified by [set:]id.
*
* $mdIconProvider
* .defaultFontSet( 'fa' ) // This sets our default fontset className.
* .defaultIconSet('my/app/icons.svg') // Register a default set of SVG icons
* .iconSet('social', 'my/app/social.svg') // Register a named icon set of SVGs
* .icon('android', 'my/app/android.svg') // Register a specific icon (by name)
* .icon('work:chair', 'my/app/chair.svg'); // Register icon in a specific set
* });
* </hljs>
*
* SVG icons and icon sets can be easily pre-loaded and cached using either (a) a build process or (b) a runtime
* **startup** process (shown below):
*
* <hljs lang="js">
* app.config(function($mdIconProvider) {
*
* // Register a default set of SVG icon definitions
* $mdIconProvider.defaultIconSet('my/app/icons.svg')
*
* })
* .run(function($templateRequest){
*
* // Pre-fetch icons sources by URL and cache in the $templateCache...
* // subsequent $templateRequest calls will look there first.
*
* var urls = [ 'imy/app/icons.svg', 'img/icons/android.svg'];
*
* angular.forEach(urls, function(url) {
* $templateRequest(url);
* });
*
* });
*
* </hljs>
*
* > <b>Note:</b> The loaded SVG data is subsequently cached internally for future requests.
*
*/
/**
* @ngdoc method
* @name $mdIconProvider#icon
*
* @description
* Register a source URL for a specific icon name; the name may include optional 'icon set' name prefix.
* These icons will later be retrieved from the cache using `$mdIcon( <icon name> )`
*
* @param {string} id Icon name/id used to register the icon
* @param {string} url specifies the external location for the data file. Used internally by
* `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
* was configured.
* @param {number=} viewBoxSize Sets the width and height the icon's viewBox.
* It is ignored for icons with an existing viewBox. Default size is 24.
*
* @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
*
* @usage
* <hljs lang="js">
* app.config(function($mdIconProvider) {
*
* // Configure URLs for icons specified by [set:]id.
*
* $mdIconProvider
* .icon('android', 'my/app/android.svg') // Register a specific icon (by name)
* .icon('work:chair', 'my/app/chair.svg'); // Register icon in a specific set
* });
* </hljs>
*
*/
/**
* @ngdoc method
* @name $mdIconProvider#iconSet
*
* @description
* Register a source URL for a 'named' set of icons; group of SVG definitions where each definition
* has an icon id. Individual icons can be subsequently retrieved from this cached set using
* `$mdIcon(<icon set name>:<icon name>)`
*
* @param {string} id Icon name/id used to register the iconset
* @param {string} url specifies the external location for the data file. Used internally by
* `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
* was configured.
* @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set.
* It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size.
* Default value is 24.
*
* @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
*
*
* @usage
* <hljs lang="js">
* app.config(function($mdIconProvider) {
*
* // Configure URLs for icons specified by [set:]id.
*
* $mdIconProvider
* .iconSet('social', 'my/app/social.svg') // Register a named icon set
* });
* </hljs>
*
*/
/**
* @ngdoc method
* @name $mdIconProvider#defaultIconSet
*
* @description
* Register a source URL for the default 'named' set of icons. Unless explicitly registered,
* subsequent lookups of icons will failover to search this 'default' icon set.
* Icon can be retrieved from this cached, default set using `$mdIcon(<name>)`
*
* @param {string} url specifies the external location for the data file. Used internally by
* `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
* was configured.
* @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set.
* It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size.
* Default value is 24.
*
* @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
*
* @usage
* <hljs lang="js">
* app.config(function($mdIconProvider) {
*
* // Configure URLs for icons specified by [set:]id.
*
* $mdIconProvider
* .defaultIconSet( 'my/app/social.svg' ) // Register a default icon set
* });
* </hljs>
*
*/
/**
* @ngdoc method
* @name $mdIconProvider#defaultFontSet
*
* @description
* When using Font-Icons, AngularJS Material assumes the the Material Design icons will be used and automatically
* configures the default font-set == 'material-icons'. Note that the font-set references the font-icon library
* class style that should be applied to the `<md-icon>`.
*
* Configuring the default means that the attributes
* `md-font-set="material-icons"` or `class="material-icons"` do not need to be explicitly declared on the
* `<md-icon>` markup. For example:
*
* `<md-icon> face </md-icon>`
* will render as
* `<span class="material-icons"> face </span>`, and
*
* `<md-icon md-font-set="fa"> face </md-icon>`
* will render as
* `<span class="fa"> face </span>`
*
* @param {string} name of the font-library style that should be applied to the md-icon DOM element
*
* @usage
* <hljs lang="js">
* app.config(function($mdIconProvider) {
* $mdIconProvider.defaultFontSet( 'fa' );
* });
* </hljs>
*
*/
/**
* @ngdoc method
* @name $mdIconProvider#fontSet
*
* @description
* When using a font set for `<md-icon>` you must specify the correct font classname in the `md-font-set`
* attribute. If the fonset className is really long, your markup may become cluttered... an easy
* solution is to define an `alias` for your fontset:
*
* @param {string} alias of the specified fontset.
* @param {string} className of the fontset.
*
* @usage
* <hljs lang="js">
* app.config(function($mdIconProvider) {
* // In this case, we set an alias for the `material-icons` fontset.
* $mdIconProvider.fontSet('md', 'material-icons');
* });
* </hljs>
*
*/
/**
* @ngdoc method
* @name $mdIconProvider#defaultViewBoxSize
*
* @description
* While `<md-icon />` markup can also be style with sizing CSS, this method configures
* the default width **and** height used for all icons; unless overridden by specific CSS.
* The default sizing is (24px, 24px).
* @param {number=} viewBoxSize Sets the width and height of the viewBox for an icon or an icon set.
* All icons in a set should be the same size. The default value is 24.
*
* @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
*
* @usage
* <hljs lang="js">
* app.config(function($mdIconProvider) {
*
* // Configure URLs for icons specified by [set:]id.
*
* $mdIconProvider
* .defaultViewBoxSize(36) // Register a default icon size (width == height)
* });
* </hljs>
*
*/
var config = {
defaultViewBoxSize: 24,
defaultFontSet: 'material-icons',
fontSets: []
};
function MdIconProvider() {
}
MdIconProvider.prototype = {
icon: function(id, url, viewBoxSize) {
if (id.indexOf(':') == -1) id = '$default:' + id;
config[id] = new ConfigurationItem(url, viewBoxSize);
return this;
},
iconSet: function(id, url, viewBoxSize) {
config[id] = new ConfigurationItem(url, viewBoxSize);
return this;
},
defaultIconSet: function(url, viewBoxSize) {
var setName = '$default';
if (!config[setName]) {
config[setName] = new ConfigurationItem(url, viewBoxSize);
}
config[setName].viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
return this;
},
defaultViewBoxSize: function(viewBoxSize) {
config.defaultViewBoxSize = viewBoxSize;
return this;
},
/**
* Register an alias name associated with a font-icon library style ;
*/
fontSet: function fontSet(alias, className) {
config.fontSets.push({
alias: alias,
fontSet: className || alias
});
return this;
},
/**
* Specify a default style name associated with a font-icon library
* fallback to Material Icons.
*
*/
defaultFontSet: function defaultFontSet(className) {
config.defaultFontSet = !className ? '' : className;
return this;
},
defaultIconSize: function defaultIconSize(iconSize) {
config.defaultIconSize = iconSize;
return this;
},
$get: ['$templateRequest', '$q', '$log', '$mdUtil', '$sce', function($templateRequest, $q, $log, $mdUtil, $sce) {
return MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce);
}]
};
/**
* Configuration item stored in the Icon registry; used for lookups
* to load if not already cached in the `loaded` cache
*/
function ConfigurationItem(url, viewBoxSize) {
this.url = url;
this.viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
}
/**
* @ngdoc service
* @name $mdIcon
* @module material.components.icon
*
* @description
* The `$mdIcon` service is a function used to lookup SVG icons.
*
* @param {string} id Query value for a unique Id or URL. If the argument is a URL, then the service will retrieve the icon element
* from its internal cache or load the icon and cache it first. If the value is not a URL-type string, then an ID lookup is
* performed. The Id may be a unique icon ID or may include an iconSet ID prefix.
*
* For the **id** query to work properly, this means that all id-to-URL mappings must have been previously configured
* using the `$mdIconProvider`.
*
* @returns {angular.$q.Promise} A promise that gets resolved to a clone of the initial SVG DOM element; which was
* created from the SVG markup in the SVG data file. If an error occurs (e.g. the icon cannot be found) the promise
* will get rejected.
*
* @usage
* <hljs lang="js">
* function SomeDirective($mdIcon) {
*
* // See if the icon has already been loaded, if not
* // then lookup the icon from the registry cache, load and cache
* // it for future requests.
* // NOTE: ID queries require configuration with $mdIconProvider
*
* $mdIcon('android').then(function(iconEl) { element.append(iconEl); });
* $mdIcon('work:chair').then(function(iconEl) { element.append(iconEl); });
*
* // Load and cache the external SVG using a URL
*
* $mdIcon('img/icons/android.svg').then(function(iconEl) {
* element.append(iconEl);
* });
* };
* </hljs>
*
* > <b>Note:</b> The `<md-icon>` directive internally uses the `$mdIcon` service to query, loaded,
* and instantiate SVG DOM elements.
*/
/* ngInject */
function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) {
var iconCache = {};
var svgCache = {};
var urlRegex = /[-\w@:%\+.~#?&//=]{2,}\.[a-z]{2,4}\b(\/[-\w@:%\+.~#?&//=]*)?/i;
var dataUrlRegex = /^data:image\/svg\+xml[\s*;\w\-\=]*?(base64)?,(.*)$/i;
Icon.prototype = {clone: cloneSVG, prepare: prepareAndStyle};
getIcon.fontSet = findRegisteredFontSet;
// Publish service...
return getIcon;
/**
* Actual $mdIcon service is essentially a lookup function
*/
function getIcon(id) {
id = id || '';
// If the "id" provided is not a string, the only other valid value is a $sce trust wrapper
// over a URL string. If the value is not trusted, this will intentionally throw an error
// because the user is attempted to use an unsafe URL, potentially opening themselves up
// to an XSS attack.
if (!angular.isString(id)) {
id = $sce.getTrustedUrl(id);
}
// If already loaded and cached, use a clone of the cached icon.
// Otherwise either load by URL, or lookup in the registry and then load by URL, and cache.
if (iconCache[id]) {
return $q.when(transformClone(iconCache[id]));
}
if (urlRegex.test(id) || dataUrlRegex.test(id)) {
return loadByURL(id).then(cacheIcon(id));
}
if (id.indexOf(':') == -1) {
id = '$default:' + id;
}
var load = config[id] ? loadByID : loadFromIconSet;
return load(id)
.then(cacheIcon(id));
}
/**
* Lookup registered fontSet style using its alias...
* If not found,
*/
function findRegisteredFontSet(alias) {
var useDefault = angular.isUndefined(alias) || !(alias && alias.length);
if (useDefault) return config.defaultFontSet;
var result = alias;
angular.forEach(config.fontSets, function(it) {
if (it.alias == alias) result = it.fontSet || result;
});
return result;
}
function transformClone(cacheElement) {
var clone = cacheElement.clone();
var cacheSuffix = '_cache' + $mdUtil.nextUid();
// We need to modify for each cached icon the id attributes.
// This is needed because SVG id's are treated as normal DOM ids
// and should not have a duplicated id.
if (clone.id) clone.id += cacheSuffix;
angular.forEach(clone.querySelectorAll('[id]'), function(item) {
item.id += cacheSuffix;
});
return clone;
}
/**
* Prepare and cache the loaded icon for the specified `id`
*/
function cacheIcon(id) {
return function updateCache(icon) {
iconCache[id] = isIcon(icon) ? icon : new Icon(icon, config[id]);
return iconCache[id].clone();
};
}
/**
* Lookup the configuration in the registry, if !registered throw an error
* otherwise load the icon [on-demand] using the registered URL.
*
*/
function loadByID(id) {
var iconConfig = config[id];
return loadByURL(iconConfig.url).then(function(icon) {
return new Icon(icon, iconConfig);
});
}
/**
* Loads the file as XML and uses querySelector( <id> ) to find
* the desired node...
*/
function loadFromIconSet(id) {
var setName = id.substring(0, id.lastIndexOf(':')) || '$default';
var iconSetConfig = config[setName];
return !iconSetConfig ? announceIdNotFound(id) : loadByURL(iconSetConfig.url).then(extractFromSet);
function extractFromSet(set) {
var iconName = id.slice(id.lastIndexOf(':') + 1);
var icon = set.querySelector('#' + iconName);
return icon ? new Icon(icon, iconSetConfig) : announceIdNotFound(id);
}
function announceIdNotFound(id) {
var msg = 'icon ' + id + ' not found';
$log.warn(msg);
return $q.reject(msg || id);
}
}
/**
* Load the icon by URL (may use the $templateCache).
* Extract the data for later conversion to Icon
*/
function loadByURL(url) {
/* Load the icon from embedded data URL. */
function loadByDataUrl(url) {
var results = dataUrlRegex.exec(url);
var isBase64 = /base64/i.test(url);
var data = isBase64 ? window.atob(results[2]) : results[2];
return $q.when(angular.element(data)[0]);
}
/* Load the icon by URL using HTTP. */
function loadByHttpUrl(url) {
return $q(function(resolve, reject) {
// Catch HTTP or generic errors not related to incorrect icon IDs.
var announceAndReject = function(err) {
var msg = angular.isString(err) ? err : (err.message || err.data || err.statusText);
$log.warn(msg);
reject(err);
},
extractSvg = function(response) {
if (!svgCache[url]) {
svgCache[url] = angular.element('<div>').append(response)[0].querySelector('svg');
}
resolve(svgCache[url]);
};
$templateRequest(url, true).then(extractSvg, announceAndReject);
});
}
return dataUrlRegex.test(url)
? loadByDataUrl(url)
: loadByHttpUrl(url);
}
/**
* Check target signature to see if it is an Icon instance.
*/
function isIcon(target) {
return angular.isDefined(target.element) && angular.isDefined(target.config);
}
/**
* Define the Icon class
*/
function Icon(el, config) {
if (el && el.tagName != 'svg') {
el = angular.element('<svg xmlns="http://www.w3.org/2000/svg">').append(el.cloneNode(true))[0];
}
// Inject the namespace if not available...
if (!el.getAttribute('xmlns')) {
el.setAttribute('xmlns', "http://www.w3.org/2000/svg");
}
this.element = el;
this.config = config;
this.prepare();
}
/**
* Prepare the DOM element that will be cached in the
* loaded iconCache store.
*/
function prepareAndStyle() {
var viewBoxSize = this.config ? this.config.viewBoxSize : config.defaultViewBoxSize;
angular.forEach({
'fit': '',
'height': '100%',
'width': '100%',
'preserveAspectRatio': 'xMidYMid meet',
'viewBox': this.element.getAttribute('viewBox') || ('0 0 ' + viewBoxSize + ' ' + viewBoxSize),
'focusable': false // Disable IE11s default behavior to make SVGs focusable
}, function(val, attr) {
this.element.setAttribute(attr, val);
}, this);
}
/**
* Clone the Icon DOM element.
*/
function cloneSVG() {
// If the element or any of its children have a style attribute, then a CSP policy without
// 'unsafe-inline' in the style-src directive, will result in a violation.
return this.element.cloneNode(true);
}
}
ngmaterial.components.icon = angular.module("material.components.icon");

View File

@ -0,0 +1,92 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-input-container.md-THEME_NAME-theme .md-input {
color: '{{foreground-1}}';
border-color: '{{foreground-4}}'; }
md-input-container.md-THEME_NAME-theme .md-input::-webkit-input-placeholder {
color: '{{foreground-3}}'; }
md-input-container.md-THEME_NAME-theme .md-input:-moz-placeholder {
color: '{{foreground-3}}'; }
md-input-container.md-THEME_NAME-theme .md-input::-moz-placeholder {
color: '{{foreground-3}}'; }
md-input-container.md-THEME_NAME-theme .md-input:-ms-input-placeholder {
color: '{{foreground-3}}'; }
md-input-container.md-THEME_NAME-theme .md-input::-webkit-input-placeholder {
color: '{{foreground-3}}'; }
md-input-container.md-THEME_NAME-theme > md-icon {
color: '{{foreground-1}}'; }
md-input-container.md-THEME_NAME-theme label,
md-input-container.md-THEME_NAME-theme .md-placeholder {
color: '{{foreground-3}}'; }
md-input-container.md-THEME_NAME-theme label.md-required:after {
color: '{{warn-A700}}'; }
md-input-container.md-THEME_NAME-theme:not(.md-input-focused):not(.md-input-invalid) label.md-required:after {
color: '{{foreground-2}}'; }
md-input-container.md-THEME_NAME-theme .md-input-messages-animation, md-input-container.md-THEME_NAME-theme .md-input-message-animation {
color: '{{warn-A700}}'; }
md-input-container.md-THEME_NAME-theme .md-input-messages-animation .md-char-counter, md-input-container.md-THEME_NAME-theme .md-input-message-animation .md-char-counter {
color: '{{foreground-1}}'; }
md-input-container.md-THEME_NAME-theme.md-input-focused .md-input::-webkit-input-placeholder {
color: '{{foreground-2}}'; }
md-input-container.md-THEME_NAME-theme.md-input-focused .md-input:-moz-placeholder {
color: '{{foreground-2}}'; }
md-input-container.md-THEME_NAME-theme.md-input-focused .md-input::-moz-placeholder {
color: '{{foreground-2}}'; }
md-input-container.md-THEME_NAME-theme.md-input-focused .md-input:-ms-input-placeholder {
color: '{{foreground-2}}'; }
md-input-container.md-THEME_NAME-theme.md-input-focused .md-input::-webkit-input-placeholder {
color: '{{foreground-2}}'; }
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-has-value label {
color: '{{foreground-2}}'; }
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused .md-input, md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-resized .md-input {
border-color: '{{primary-color}}'; }
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused label,
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused md-icon {
color: '{{primary-color}}'; }
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-accent .md-input {
border-color: '{{accent-color}}'; }
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-accent label,
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-accent md-icon {
color: '{{accent-color}}'; }
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-warn .md-input {
border-color: '{{warn-A700}}'; }
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-warn label,
md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-warn md-icon {
color: '{{warn-A700}}'; }
md-input-container.md-THEME_NAME-theme.md-input-invalid .md-input {
border-color: '{{warn-A700}}'; }
md-input-container.md-THEME_NAME-theme.md-input-invalid label,
md-input-container.md-THEME_NAME-theme.md-input-invalid .md-input-message-animation,
md-input-container.md-THEME_NAME-theme.md-input-invalid .md-char-counter {
color: '{{warn-A700}}'; }
md-input-container.md-THEME_NAME-theme .md-input[disabled],
[disabled] md-input-container.md-THEME_NAME-theme .md-input {
border-bottom-color: transparent;
color: '{{foreground-3}}';
background-image: -webkit-linear-gradient(left, "{{foreground-3}}" 0%, "{{foreground-3}}" 33%, transparent 0%);
background-image: linear-gradient(to right, "{{foreground-3}}" 0%, "{{foreground-3}}" 33%, transparent 0%);
background-image: -ms-linear-gradient(left, transparent 0%, "{{foreground-3}}" 100%); }

View File

@ -0,0 +1,313 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-input-container {
display: inline-block;
position: relative;
padding: 2px;
margin: 18px 0;
vertical-align: middle;
/*
* The .md-input class is added to the input/textarea
*/ }
md-input-container:after {
content: '';
display: table;
clear: both; }
md-input-container.md-block {
display: block; }
md-input-container .md-errors-spacer {
float: right;
min-height: 24px;
min-width: 1px; }
[dir=rtl] md-input-container .md-errors-spacer {
float: left; }
md-input-container > md-icon {
position: absolute;
top: 8px;
left: 2px;
right: auto; }
[dir=rtl] md-input-container > md-icon {
left: auto; }
[dir=rtl] md-input-container > md-icon {
right: 2px; }
md-input-container textarea,
md-input-container input[type="text"],
md-input-container input[type="password"],
md-input-container input[type="datetime"],
md-input-container input[type="datetime-local"],
md-input-container input[type="date"],
md-input-container input[type="month"],
md-input-container input[type="time"],
md-input-container input[type="week"],
md-input-container input[type="number"],
md-input-container input[type="email"],
md-input-container input[type="url"],
md-input-container input[type="search"],
md-input-container input[type="tel"],
md-input-container input[type="color"] {
/* remove default appearance from all input/textarea */
-moz-appearance: none;
-webkit-appearance: none; }
md-input-container input[type="date"],
md-input-container input[type="datetime-local"],
md-input-container input[type="month"],
md-input-container input[type="time"],
md-input-container input[type="week"] {
min-height: 26px; }
md-input-container textarea {
resize: none;
overflow: hidden; }
md-input-container textarea.md-input {
min-height: 26px;
-ms-flex-preferred-size: auto; }
md-input-container textarea[md-no-autogrow] {
height: auto;
overflow: auto; }
md-input-container label:not(.md-container-ignore) {
position: absolute;
bottom: 100%;
left: 0;
right: auto; }
[dir=rtl] md-input-container label:not(.md-container-ignore) {
left: auto; }
[dir=rtl] md-input-container label:not(.md-container-ignore) {
right: 0; }
md-input-container label:not(.md-container-ignore).md-required:after {
content: ' *';
font-size: 13px;
vertical-align: top; }
md-input-container label:not(.md-no-float):not(.md-container-ignore),
md-input-container .md-placeholder {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
order: 1;
pointer-events: none;
-webkit-font-smoothing: antialiased;
padding-left: 3px;
padding-right: 0;
z-index: 1;
-webkit-transform: translate3d(0, 28px, 0) scale(1);
transform: translate3d(0, 28px, 0) scale(1);
-webkit-transition: -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
max-width: 100%;
-webkit-transform-origin: left top;
transform-origin: left top; }
[dir=rtl] md-input-container label:not(.md-no-float):not(.md-container-ignore), [dir=rtl]
md-input-container .md-placeholder {
padding-left: 0; }
[dir=rtl] md-input-container label:not(.md-no-float):not(.md-container-ignore), [dir=rtl]
md-input-container .md-placeholder {
padding-right: 3px; }
[dir=rtl] md-input-container label:not(.md-no-float):not(.md-container-ignore), [dir=rtl]
md-input-container .md-placeholder {
-webkit-transform-origin: right top;
transform-origin: right top; }
md-input-container .md-placeholder {
position: absolute;
top: 0;
opacity: 0;
-webkit-transition-property: opacity, -webkit-transform;
transition-property: opacity, -webkit-transform;
transition-property: opacity, transform;
transition-property: opacity, transform, -webkit-transform;
-webkit-transform: translate3d(0, 30px, 0);
transform: translate3d(0, 30px, 0); }
md-input-container.md-input-focused .md-placeholder {
opacity: 1;
-webkit-transform: translate3d(0, 24px, 0);
transform: translate3d(0, 24px, 0); }
md-input-container.md-input-has-value .md-placeholder {
-webkit-transition: none;
transition: none;
opacity: 0; }
md-input-container:not(.md-input-has-value) input:not(:focus),
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-ampm-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-day-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-hour-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-millisecond-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-minute-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-month-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-second-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-week-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-year-field,
md-input-container:not(.md-input-has-value) input:not(:focus)::-webkit-datetime-edit-text {
color: transparent; }
md-input-container .md-input {
-webkit-box-ordinal-group: 3;
-webkit-order: 2;
order: 2;
display: block;
margin-top: 0;
background: none;
padding-top: 2px;
padding-bottom: 1px;
padding-left: 2px;
padding-right: 2px;
border-width: 0 0 1px 0;
line-height: 26px;
height: 30px;
-ms-flex-preferred-size: 26px;
border-radius: 0;
border-style: solid;
width: 100%;
box-sizing: border-box;
float: left; }
[dir=rtl] md-input-container .md-input {
float: right; }
md-input-container .md-input:focus {
outline: none; }
md-input-container .md-input:invalid {
outline: none;
box-shadow: none; }
md-input-container .md-input.md-no-flex {
-webkit-box-flex: 0 !important;
-webkit-flex: none !important;
flex: none !important; }
md-input-container .md-char-counter {
text-align: right;
padding-right: 2px;
padding-left: 0; }
[dir=rtl] md-input-container .md-char-counter {
text-align: left; }
[dir=rtl] md-input-container .md-char-counter {
padding-right: 0; }
[dir=rtl] md-input-container .md-char-counter {
padding-left: 2px; }
md-input-container .md-input-messages-animation {
position: relative;
-webkit-box-ordinal-group: 5;
-webkit-order: 4;
order: 4;
overflow: hidden;
clear: left; }
[dir=rtl] md-input-container .md-input-messages-animation {
clear: right; }
md-input-container .md-input-message-animation, md-input-container .md-char-counter {
font-size: 12px;
line-height: 14px;
overflow: hidden;
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
opacity: 1;
margin-top: 0;
padding-top: 5px; }
md-input-container .md-input-message-animation:not(.md-char-counter), md-input-container .md-char-counter:not(.md-char-counter) {
padding-right: 5px;
padding-left: 0; }
[dir=rtl] md-input-container .md-input-message-animation:not(.md-char-counter), [dir=rtl] md-input-container .md-char-counter:not(.md-char-counter) {
padding-right: 0; }
[dir=rtl] md-input-container .md-input-message-animation:not(.md-char-counter), [dir=rtl] md-input-container .md-char-counter:not(.md-char-counter) {
padding-left: 5px; }
md-input-container:not(.md-input-invalid) .md-auto-hide .md-input-message-animation {
opacity: 0;
margin-top: -100px; }
md-input-container .md-input-message-animation.ng-enter-prepare {
opacity: 0;
margin-top: -100px; }
md-input-container .md-input-message-animation.ng-enter:not(.ng-enter-active) {
opacity: 0;
margin-top: -100px; }
md-input-container.md-input-focused label:not(.md-no-float), md-input-container.md-input-has-placeholder label:not(.md-no-float), md-input-container.md-input-has-value label:not(.md-no-float) {
-webkit-transform: translate3d(0, 6px, 0) scale(0.75);
transform: translate3d(0, 6px, 0) scale(0.75);
-webkit-transition: width cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s, -webkit-transform cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s;
transition: width cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s, -webkit-transform cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s;
transition: transform cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s, width cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s;
transition: transform cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s, width cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s, -webkit-transform cubic-bezier(0.25, 0.8, 0.25, 1) 0.4s; }
md-input-container.md-input-has-value label {
-webkit-transition: none;
transition: none; }
md-input-container.md-input-focused .md-input,
md-input-container .md-input.ng-invalid.ng-dirty,
md-input-container.md-input-resized .md-input {
padding-bottom: 0;
border-width: 0 0 2px 0; }
md-input-container .md-input[disabled],
[disabled] md-input-container .md-input {
background-position: bottom -1px left 0;
background-size: 4px 1px;
background-repeat: repeat-x; }
md-input-container.md-icon-float {
-webkit-transition: margin-top 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: margin-top 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); }
md-input-container.md-icon-float > label {
pointer-events: none;
position: absolute; }
md-input-container.md-icon-float > md-icon {
top: 8px;
left: 2px;
right: auto; }
[dir=rtl] md-input-container.md-icon-float > md-icon {
left: auto; }
[dir=rtl] md-input-container.md-icon-float > md-icon {
right: 2px; }
md-input-container.md-icon-left > label:not(.md-no-float):not(.md-container-ignore),
md-input-container.md-icon-left > label .md-placeholder, md-input-container.md-icon-right > label:not(.md-no-float):not(.md-container-ignore),
md-input-container.md-icon-right > label .md-placeholder {
width: calc(100% - 36px - 18px); }
md-input-container.md-icon-left {
padding-left: 36px;
padding-right: 0; }
[dir=rtl] md-input-container.md-icon-left {
padding-left: 0; }
[dir=rtl] md-input-container.md-icon-left {
padding-right: 36px; }
md-input-container.md-icon-left > label {
left: 36px;
right: auto; }
[dir=rtl] md-input-container.md-icon-left > label {
left: auto; }
[dir=rtl] md-input-container.md-icon-left > label {
right: 36px; }
md-input-container.md-icon-right {
padding-left: 0;
padding-right: 36px; }
[dir=rtl] md-input-container.md-icon-right {
padding-left: 36px; }
[dir=rtl] md-input-container.md-icon-right {
padding-right: 0; }
md-input-container.md-icon-right > md-icon:last-of-type {
margin: 0;
right: 2px;
left: auto; }
[dir=rtl] md-input-container.md-icon-right > md-icon:last-of-type {
right: auto; }
[dir=rtl] md-input-container.md-icon-right > md-icon:last-of-type {
left: 2px; }
md-input-container.md-icon-left.md-icon-right {
padding-left: 36px;
padding-right: 36px; }
md-input-container.md-icon-left.md-icon-right > label:not(.md-no-float):not(.md-container-ignore),
md-input-container.md-icon-left.md-icon-right > label .md-placeholder {
width: calc(100% - (36px * 2)); }
.md-resize-wrapper {
position: relative; }
.md-resize-wrapper:after {
content: '';
display: table;
clear: both; }
.md-resize-handle {
position: absolute;
bottom: -5px;
left: 0;
height: 10px;
background: transparent;
width: 100%;
cursor: ns-resize; }
@media screen and (-ms-high-contrast: active) {
md-input-container.md-default-theme > md-icon {
fill: #fff; } }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-list.md-THEME_NAME-theme md-list-item.md-2-line .md-list-item-text h3, md-list.md-THEME_NAME-theme md-list-item.md-2-line .md-list-item-text h4,
md-list.md-THEME_NAME-theme md-list-item.md-3-line .md-list-item-text h3,
md-list.md-THEME_NAME-theme md-list-item.md-3-line .md-list-item-text h4 {
color: '{{foreground-1}}'; }
md-list.md-THEME_NAME-theme md-list-item.md-2-line .md-list-item-text p,
md-list.md-THEME_NAME-theme md-list-item.md-3-line .md-list-item-text p {
color: '{{foreground-2}}'; }
md-list.md-THEME_NAME-theme .md-proxy-focus.md-focused div.md-no-style {
background-color: '{{background-100}}'; }
md-list.md-THEME_NAME-theme md-list-item .md-avatar-icon {
background-color: '{{foreground-3}}';
color: '{{background-color}}'; }
md-list.md-THEME_NAME-theme md-list-item > md-icon {
color: '{{foreground-2}}'; }
md-list.md-THEME_NAME-theme md-list-item > md-icon.md-highlight {
color: '{{primary-color}}'; }
md-list.md-THEME_NAME-theme md-list-item > md-icon.md-highlight.md-accent {
color: '{{accent-color}}'; }

View File

@ -0,0 +1,401 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-list {
display: block;
padding: 8px 0px 8px 0px; }
md-list .md-subheader {
font-size: 14px;
font-weight: 500;
letter-spacing: 0.010em;
line-height: 1.2em; }
md-list.md-dense md-list-item,
md-list.md-dense md-list-item .md-list-item-inner {
min-height: 48px; }
md-list.md-dense md-list-item::before,
md-list.md-dense md-list-item .md-list-item-inner::before {
content: '';
min-height: 48px;
visibility: hidden;
display: inline-block; }
md-list.md-dense md-list-item md-icon:first-child,
md-list.md-dense md-list-item .md-list-item-inner md-icon:first-child {
width: 20px;
height: 20px; }
md-list.md-dense md-list-item > md-icon:first-child:not(.md-avatar-icon),
md-list.md-dense md-list-item .md-list-item-inner > md-icon:first-child:not(.md-avatar-icon) {
margin-right: 36px; }
[dir=rtl] md-list.md-dense md-list-item > md-icon:first-child:not(.md-avatar-icon), [dir=rtl]
md-list.md-dense md-list-item .md-list-item-inner > md-icon:first-child:not(.md-avatar-icon) {
margin-right: auto;
margin-left: 36px; }
md-list.md-dense md-list-item .md-avatar, md-list.md-dense md-list-item .md-avatar-icon,
md-list.md-dense md-list-item .md-list-item-inner .md-avatar,
md-list.md-dense md-list-item .md-list-item-inner .md-avatar-icon {
margin-right: 20px; }
[dir=rtl] md-list.md-dense md-list-item .md-avatar, [dir=rtl] md-list.md-dense md-list-item .md-avatar-icon, [dir=rtl]
md-list.md-dense md-list-item .md-list-item-inner .md-avatar, [dir=rtl]
md-list.md-dense md-list-item .md-list-item-inner .md-avatar-icon {
margin-right: auto;
margin-left: 20px; }
md-list.md-dense md-list-item .md-avatar,
md-list.md-dense md-list-item .md-list-item-inner .md-avatar {
-webkit-box-flex: 0;
-webkit-flex: none;
flex: none;
width: 36px;
height: 36px; }
md-list.md-dense md-list-item.md-2-line .md-list-item-text.md-offset, md-list.md-dense md-list-item.md-2-line > .md-no-style .md-list-item-text.md-offset, md-list.md-dense md-list-item.md-3-line .md-list-item-text.md-offset, md-list.md-dense md-list-item.md-3-line > .md-no-style .md-list-item-text.md-offset {
margin-left: 56px; }
[dir=rtl] md-list.md-dense md-list-item.md-2-line .md-list-item-text.md-offset, [dir=rtl] md-list.md-dense md-list-item.md-2-line > .md-no-style .md-list-item-text.md-offset, [dir=rtl] md-list.md-dense md-list-item.md-3-line .md-list-item-text.md-offset, [dir=rtl] md-list.md-dense md-list-item.md-3-line > .md-no-style .md-list-item-text.md-offset {
margin-left: auto;
margin-right: 56px; }
md-list.md-dense md-list-item.md-2-line .md-list-item-text h3,
md-list.md-dense md-list-item.md-2-line .md-list-item-text h4,
md-list.md-dense md-list-item.md-2-line .md-list-item-text p, md-list.md-dense md-list-item.md-2-line > .md-no-style .md-list-item-text h3,
md-list.md-dense md-list-item.md-2-line > .md-no-style .md-list-item-text h4,
md-list.md-dense md-list-item.md-2-line > .md-no-style .md-list-item-text p, md-list.md-dense md-list-item.md-3-line .md-list-item-text h3,
md-list.md-dense md-list-item.md-3-line .md-list-item-text h4,
md-list.md-dense md-list-item.md-3-line .md-list-item-text p, md-list.md-dense md-list-item.md-3-line > .md-no-style .md-list-item-text h3,
md-list.md-dense md-list-item.md-3-line > .md-no-style .md-list-item-text h4,
md-list.md-dense md-list-item.md-3-line > .md-no-style .md-list-item-text p {
line-height: 1.05;
font-size: 12px; }
md-list.md-dense md-list-item.md-2-line .md-list-item-text h3, md-list.md-dense md-list-item.md-2-line > .md-no-style .md-list-item-text h3, md-list.md-dense md-list-item.md-3-line .md-list-item-text h3, md-list.md-dense md-list-item.md-3-line > .md-no-style .md-list-item-text h3 {
font-size: 13px; }
md-list.md-dense md-list-item.md-2-line, md-list.md-dense md-list-item.md-2-line > .md-no-style {
min-height: 60px; }
md-list.md-dense md-list-item.md-2-line::before, md-list.md-dense md-list-item.md-2-line > .md-no-style::before {
content: '';
min-height: 60px;
visibility: hidden;
display: inline-block; }
md-list.md-dense md-list-item.md-2-line > .md-avatar, md-list.md-dense md-list-item.md-2-line .md-avatar-icon, md-list.md-dense md-list-item.md-2-line > .md-no-style > .md-avatar, md-list.md-dense md-list-item.md-2-line > .md-no-style .md-avatar-icon {
margin-top: 12px; }
md-list.md-dense md-list-item.md-3-line, md-list.md-dense md-list-item.md-3-line > .md-no-style {
min-height: 76px; }
md-list.md-dense md-list-item.md-3-line::before, md-list.md-dense md-list-item.md-3-line > .md-no-style::before {
content: '';
min-height: 76px;
visibility: hidden;
display: inline-block; }
md-list.md-dense md-list-item.md-3-line > md-icon:first-child,
md-list.md-dense md-list-item.md-3-line > .md-avatar, md-list.md-dense md-list-item.md-3-line > .md-no-style > md-icon:first-child,
md-list.md-dense md-list-item.md-3-line > .md-no-style > .md-avatar {
margin-top: 16px; }
md-list-item {
position: relative; }
md-list-item.md-proxy-focus.md-focused .md-no-style {
-webkit-transition: background-color 0.15s linear;
transition: background-color 0.15s linear; }
md-list-item._md-button-wrap {
position: relative; }
md-list-item._md-button-wrap > div.md-button:first-child {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
padding: 0 16px;
margin: 0;
font-weight: 400;
text-align: left;
border: medium none; }
[dir=rtl] md-list-item._md-button-wrap > div.md-button:first-child {
text-align: right; }
md-list-item._md-button-wrap > div.md-button:first-child > .md-button:first-child {
position: absolute;
top: 0;
left: 0;
height: 100%;
margin: 0;
padding: 0; }
md-list-item._md-button-wrap > div.md-button:first-child .md-list-item-inner {
width: 100%;
min-height: inherit; }
md-list-item.md-no-proxy,
md-list-item .md-no-style {
position: relative;
padding: 0px 16px;
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
flex: 1 1 auto; }
md-list-item.md-no-proxy.md-button,
md-list-item .md-no-style.md-button {
font-size: inherit;
height: inherit;
text-align: left;
text-transform: none;
width: 100%;
white-space: normal;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: inherit;
flex-direction: inherit;
-webkit-box-align: inherit;
-webkit-align-items: inherit;
align-items: inherit;
border-radius: 0;
margin: 0; }
[dir=rtl] md-list-item.md-no-proxy.md-button, [dir=rtl]
md-list-item .md-no-style.md-button {
text-align: right; }
md-list-item.md-no-proxy.md-button > .md-ripple-container,
md-list-item .md-no-style.md-button > .md-ripple-container {
border-radius: 0; }
md-list-item.md-no-proxy:focus,
md-list-item .md-no-style:focus {
outline: none; }
md-list-item.md-clickable:hover {
cursor: pointer; }
md-list-item md-divider {
position: absolute;
bottom: 0;
left: 0;
width: 100%; }
[dir=rtl] md-list-item md-divider {
left: auto;
right: 0; }
md-list-item md-divider[md-inset] {
left: 72px;
width: calc(100% - 72px);
margin: 0 !important; }
[dir=rtl] md-list-item md-divider[md-inset] {
left: auto;
right: 72px; }
md-list-item,
md-list-item .md-list-item-inner {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
min-height: 48px;
height: auto; }
md-list-item::before,
md-list-item .md-list-item-inner::before {
content: '';
min-height: 48px;
visibility: hidden;
display: inline-block; }
md-list-item > div.md-primary > md-icon:not(.md-avatar-icon),
md-list-item > div.md-secondary > md-icon:not(.md-avatar-icon),
md-list-item > md-icon:first-child:not(.md-avatar-icon),
md-list-item > md-icon.md-secondary:not(.md-avatar-icon),
md-list-item .md-list-item-inner > div.md-primary > md-icon:not(.md-avatar-icon),
md-list-item .md-list-item-inner > div.md-secondary > md-icon:not(.md-avatar-icon),
md-list-item .md-list-item-inner > md-icon:first-child:not(.md-avatar-icon),
md-list-item .md-list-item-inner > md-icon.md-secondary:not(.md-avatar-icon) {
width: 24px;
margin-top: 16px;
margin-bottom: 12px;
box-sizing: content-box; }
md-list-item > div.md-primary > md-checkbox,
md-list-item > div.md-secondary > md-checkbox,
md-list-item > md-checkbox,
md-list-item md-checkbox.md-secondary,
md-list-item .md-list-item-inner > div.md-primary > md-checkbox,
md-list-item .md-list-item-inner > div.md-secondary > md-checkbox,
md-list-item .md-list-item-inner > md-checkbox,
md-list-item .md-list-item-inner md-checkbox.md-secondary {
-webkit-align-self: center;
-ms-grid-row-align: center;
align-self: center; }
md-list-item > div.md-primary > md-checkbox .md-label,
md-list-item > div.md-secondary > md-checkbox .md-label,
md-list-item > md-checkbox .md-label,
md-list-item md-checkbox.md-secondary .md-label,
md-list-item .md-list-item-inner > div.md-primary > md-checkbox .md-label,
md-list-item .md-list-item-inner > div.md-secondary > md-checkbox .md-label,
md-list-item .md-list-item-inner > md-checkbox .md-label,
md-list-item .md-list-item-inner md-checkbox.md-secondary .md-label {
display: none; }
md-list-item > md-icon:first-child:not(.md-avatar-icon),
md-list-item .md-list-item-inner > md-icon:first-child:not(.md-avatar-icon) {
margin-right: 32px; }
[dir=rtl] md-list-item > md-icon:first-child:not(.md-avatar-icon), [dir=rtl]
md-list-item .md-list-item-inner > md-icon:first-child:not(.md-avatar-icon) {
margin-right: auto;
margin-left: 32px; }
md-list-item .md-avatar, md-list-item .md-avatar-icon,
md-list-item .md-list-item-inner .md-avatar,
md-list-item .md-list-item-inner .md-avatar-icon {
margin-top: 8px;
margin-bottom: 8px;
margin-right: 16px;
border-radius: 50%;
box-sizing: content-box; }
[dir=rtl] md-list-item .md-avatar, [dir=rtl] md-list-item .md-avatar-icon, [dir=rtl]
md-list-item .md-list-item-inner .md-avatar, [dir=rtl]
md-list-item .md-list-item-inner .md-avatar-icon {
margin-right: auto;
margin-left: 16px; }
md-list-item .md-avatar,
md-list-item .md-list-item-inner .md-avatar {
-webkit-box-flex: 0;
-webkit-flex: none;
flex: none;
width: 40px;
height: 40px; }
md-list-item .md-avatar-icon,
md-list-item .md-list-item-inner .md-avatar-icon {
padding: 8px; }
md-list-item .md-avatar-icon svg,
md-list-item .md-list-item-inner .md-avatar-icon svg {
width: 24px;
height: 24px; }
md-list-item > md-checkbox,
md-list-item .md-list-item-inner > md-checkbox {
width: 24px;
margin-left: 3px;
margin-right: 29px;
margin-top: 16px; }
[dir=rtl] md-list-item > md-checkbox, [dir=rtl]
md-list-item .md-list-item-inner > md-checkbox {
margin-left: 29px; }
[dir=rtl] md-list-item > md-checkbox, [dir=rtl]
md-list-item .md-list-item-inner > md-checkbox {
margin-right: 3px; }
md-list-item .md-secondary-container,
md-list-item .md-list-item-inner .md-secondary-container {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-flex-shrink: 0;
flex-shrink: 0;
margin: auto;
margin-right: 0;
margin-left: auto; }
[dir=rtl] md-list-item .md-secondary-container, [dir=rtl]
md-list-item .md-list-item-inner .md-secondary-container {
margin-right: auto; }
[dir=rtl] md-list-item .md-secondary-container, [dir=rtl]
md-list-item .md-list-item-inner .md-secondary-container {
margin-left: 0; }
md-list-item .md-secondary-container .md-button:last-of-type, md-list-item .md-secondary-container .md-icon-button:last-of-type,
md-list-item .md-list-item-inner .md-secondary-container .md-button:last-of-type,
md-list-item .md-list-item-inner .md-secondary-container .md-icon-button:last-of-type {
margin-right: 0; }
[dir=rtl] md-list-item .md-secondary-container .md-button:last-of-type, [dir=rtl] md-list-item .md-secondary-container .md-icon-button:last-of-type, [dir=rtl]
md-list-item .md-list-item-inner .md-secondary-container .md-button:last-of-type, [dir=rtl]
md-list-item .md-list-item-inner .md-secondary-container .md-icon-button:last-of-type {
margin-right: auto;
margin-left: 0; }
md-list-item .md-secondary-container md-checkbox,
md-list-item .md-list-item-inner .md-secondary-container md-checkbox {
margin-top: 0;
margin-bottom: 0; }
md-list-item .md-secondary-container md-checkbox:last-child,
md-list-item .md-list-item-inner .md-secondary-container md-checkbox:last-child {
width: 24px;
margin-right: 0; }
[dir=rtl] md-list-item .md-secondary-container md-checkbox:last-child, [dir=rtl]
md-list-item .md-list-item-inner .md-secondary-container md-checkbox:last-child {
margin-right: auto;
margin-left: 0; }
md-list-item .md-secondary-container md-switch,
md-list-item .md-list-item-inner .md-secondary-container md-switch {
margin-top: 0;
margin-bottom: 0;
margin-right: -6px; }
[dir=rtl] md-list-item .md-secondary-container md-switch, [dir=rtl]
md-list-item .md-list-item-inner .md-secondary-container md-switch {
margin-right: auto;
margin-left: -6px; }
md-list-item > p, md-list-item > .md-list-item-inner > p,
md-list-item .md-list-item-inner > p,
md-list-item .md-list-item-inner > .md-list-item-inner > p {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
margin: 0; }
md-list-item.md-2-line, md-list-item.md-2-line > .md-no-style, md-list-item.md-3-line, md-list-item.md-3-line > .md-no-style {
-webkit-box-align: start;
-webkit-align-items: flex-start;
align-items: flex-start;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center; }
md-list-item.md-2-line.md-long-text, md-list-item.md-2-line > .md-no-style.md-long-text, md-list-item.md-3-line.md-long-text, md-list-item.md-3-line > .md-no-style.md-long-text {
margin-top: 8px;
margin-bottom: 8px; }
md-list-item.md-2-line .md-list-item-text, md-list-item.md-2-line > .md-no-style .md-list-item-text, md-list-item.md-3-line .md-list-item-text, md-list-item.md-3-line > .md-no-style .md-list-item-text {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
margin: auto;
text-overflow: ellipsis;
overflow: hidden; }
md-list-item.md-2-line .md-list-item-text.md-offset, md-list-item.md-2-line > .md-no-style .md-list-item-text.md-offset, md-list-item.md-3-line .md-list-item-text.md-offset, md-list-item.md-3-line > .md-no-style .md-list-item-text.md-offset {
margin-left: 56px; }
[dir=rtl] md-list-item.md-2-line .md-list-item-text.md-offset, [dir=rtl] md-list-item.md-2-line > .md-no-style .md-list-item-text.md-offset, [dir=rtl] md-list-item.md-3-line .md-list-item-text.md-offset, [dir=rtl] md-list-item.md-3-line > .md-no-style .md-list-item-text.md-offset {
margin-left: auto;
margin-right: 56px; }
md-list-item.md-2-line .md-list-item-text h3, md-list-item.md-2-line > .md-no-style .md-list-item-text h3, md-list-item.md-3-line .md-list-item-text h3, md-list-item.md-3-line > .md-no-style .md-list-item-text h3 {
font-size: 16px;
font-weight: 400;
letter-spacing: 0.010em;
margin: 0 0 0px 0;
line-height: 1.2em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis; }
md-list-item.md-2-line .md-list-item-text h4, md-list-item.md-2-line > .md-no-style .md-list-item-text h4, md-list-item.md-3-line .md-list-item-text h4, md-list-item.md-3-line > .md-no-style .md-list-item-text h4 {
font-size: 14px;
letter-spacing: 0.010em;
margin: 3px 0 1px 0;
font-weight: 400;
line-height: 1.2em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis; }
md-list-item.md-2-line .md-list-item-text p, md-list-item.md-2-line > .md-no-style .md-list-item-text p, md-list-item.md-3-line .md-list-item-text p, md-list-item.md-3-line > .md-no-style .md-list-item-text p {
font-size: 14px;
font-weight: 500;
letter-spacing: 0.010em;
margin: 0 0 0 0;
line-height: 1.6em; }
md-list-item.md-2-line, md-list-item.md-2-line > .md-no-style {
height: auto;
min-height: 72px; }
md-list-item.md-2-line::before, md-list-item.md-2-line > .md-no-style::before {
content: '';
min-height: 72px;
visibility: hidden;
display: inline-block; }
md-list-item.md-2-line > .md-avatar, md-list-item.md-2-line .md-avatar-icon, md-list-item.md-2-line > .md-no-style > .md-avatar, md-list-item.md-2-line > .md-no-style .md-avatar-icon {
margin-top: 12px; }
md-list-item.md-2-line > md-icon:first-child, md-list-item.md-2-line > .md-no-style > md-icon:first-child {
-webkit-align-self: flex-start;
align-self: flex-start; }
md-list-item.md-2-line .md-list-item-text, md-list-item.md-2-line > .md-no-style .md-list-item-text {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
flex: 1 1 auto; }
md-list-item.md-3-line, md-list-item.md-3-line > .md-no-style {
height: auto;
min-height: 88px; }
md-list-item.md-3-line::before, md-list-item.md-3-line > .md-no-style::before {
content: '';
min-height: 88px;
visibility: hidden;
display: inline-block; }
md-list-item.md-3-line > md-icon:first-child,
md-list-item.md-3-line > .md-avatar, md-list-item.md-3-line > .md-no-style > md-icon:first-child,
md-list-item.md-3-line > .md-no-style > .md-avatar {
margin-top: 16px; }

View File

@ -0,0 +1,600 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.list');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.list
* @description
* List module
*/
MdListController['$inject'] = ["$scope", "$element", "$mdListInkRipple"];
mdListDirective['$inject'] = ["$mdTheming"];
mdListItemDirective['$inject'] = ["$mdAria", "$mdConstant", "$mdUtil", "$timeout"];
angular.module('material.components.list', [
'material.core'
])
.controller('MdListController', MdListController)
.directive('mdList', mdListDirective)
.directive('mdListItem', mdListItemDirective);
/**
* @ngdoc directive
* @name mdList
* @module material.components.list
*
* @restrict E
*
* @description
* The `<md-list>` directive is a list container for 1..n `<md-list-item>` tags.
*
* @usage
* <hljs lang="html">
* <md-list>
* <md-list-item class="md-2-line" ng-repeat="item in todos">
* <md-checkbox ng-model="item.done"></md-checkbox>
* <div class="md-list-item-text">
* <h3>{{item.title}}</h3>
* <p>{{item.description}}</p>
* </div>
* </md-list-item>
* </md-list>
* </hljs>
*/
function mdListDirective($mdTheming) {
return {
restrict: 'E',
compile: function(tEl) {
tEl[0].setAttribute('role', 'list');
return $mdTheming;
}
};
}
/**
* @ngdoc directive
* @name mdListItem
* @module material.components.list
*
* @restrict E
*
* @description
* A `md-list-item` element can be used to represent some information in a row.<br/>
*
* @usage
* ### Single Row Item
* <hljs lang="html">
* <md-list-item>
* <span>Single Row Item</span>
* </md-list-item>
* </hljs>
*
* ### Multiple Lines
* By using the following markup, you will be able to have two lines inside of one `md-list-item`.
*
* <hljs lang="html">
* <md-list-item class="md-2-line">
* <div class="md-list-item-text" layout="column">
* <p>First Line</p>
* <p>Second Line</p>
* </div>
* </md-list-item>
* </hljs>
*
* It is also possible to have three lines inside of one list item.
*
* <hljs lang="html">
* <md-list-item class="md-3-line">
* <div class="md-list-item-text" layout="column">
* <p>First Line</p>
* <p>Second Line</p>
* <p>Third Line</p>
* </div>
* </md-list-item>
* </hljs>
*
* ### Secondary Items
* Secondary items are elements which will be aligned at the end of the `md-list-item`.
*
* <hljs lang="html">
* <md-list-item>
* <span>Single Row Item</span>
* <md-button class="md-secondary">
* Secondary Button
* </md-button>
* </md-list-item>
* </hljs>
*
* It also possible to have multiple secondary items inside of one `md-list-item`.
*
* <hljs lang="html">
* <md-list-item>
* <span>Single Row Item</span>
* <md-button class="md-secondary">First Button</md-button>
* <md-button class="md-secondary">Second Button</md-button>
* </md-list-item>
* </hljs>
*
* ### Proxy Item
* Proxies are elements, which will execute their specific action on click<br/>
* Currently supported proxy items are
* - `md-checkbox` (Toggle)
* - `md-switch` (Toggle)
* - `md-menu` (Open)
*
* This means, when using a supported proxy item inside of `md-list-item`, the list item will
* automatically become clickable and executes the associated action of the proxy element on click.
*
* It is possible to disable this behavior by applying the `md-no-proxy` class to the list item.
*
* <hljs lang="html">
* <md-list-item class="md-no-proxy">
* <span>No Proxy List</span>
* <md-checkbox class="md-secondary"></md-checkbox>
* </md-list-item>
* </hljs>
*
* Here are a few examples of proxy elements inside of a list item.
*
* <hljs lang="html">
* <md-list-item>
* <span>First Line</span>
* <md-checkbox class="md-secondary"></md-checkbox>
* </md-list-item>
* </hljs>
*
* The `md-checkbox` element will be automatically detected as a proxy element and will toggle on click.
*
* <hljs lang="html">
* <md-list-item>
* <span>First Line</span>
* <md-switch class="md-secondary"></md-switch>
* </md-list-item>
* </hljs>
*
* The recognized `md-switch` will toggle its state, when the user clicks on the `md-list-item`.
*
* It is also possible to have a `md-menu` inside of a `md-list-item`.
* <hljs lang="html">
* <md-list-item>
* <p>Click anywhere to fire the secondary action</p>
* <md-menu class="md-secondary">
* <md-button class="md-icon-button">
* <md-icon md-svg-icon="communication:message"></md-icon>
* </md-button>
* <md-menu-content width="4">
* <md-menu-item>
* <md-button>
* Redial
* </md-button>
* </md-menu-item>
* <md-menu-item>
* <md-button>
* Check voicemail
* </md-button>
* </md-menu-item>
* <md-menu-divider></md-menu-divider>
* <md-menu-item>
* <md-button>
* Notifications
* </md-button>
* </md-menu-item>
* </md-menu-content>
* </md-menu>
* </md-list-item>
* </hljs>
*
* The menu will automatically open, when the users clicks on the `md-list-item`.<br/>
*
* If the developer didn't specify any position mode on the menu, the `md-list-item` will automatically detect the
* position mode and applies it to the `md-menu`.
*
* ### Avatars
* Sometimes you may want to have some avatars inside of the `md-list-item `.<br/>
* You are able to create a optimized icon for the list item, by applying the `.md-avatar` class on the `<img>` element.
*
* <hljs lang="html">
* <md-list-item>
* <img src="my-avatar.png" class="md-avatar">
* <span>Alan Turing</span>
* </hljs>
*
* When using `<md-icon>` for an avatar, you have to use the `.md-avatar-icon` class.
* <hljs lang="html">
* <md-list-item>
* <md-icon class="md-avatar-icon" md-svg-icon="avatars:timothy"></md-icon>
* <span>Timothy Kopra</span>
* </md-list-item>
* </hljs>
*
* In cases, you have a `md-list-item`, which doesn't have any avatar,
* but you want to align it with the other avatar items, you have to use the `.md-offset` class.
*
* <hljs lang="html">
* <md-list-item class="md-offset">
* <span>Jon Doe</span>
* </md-list-item>
* </hljs>
*
* ### DOM modification
* The `md-list-item` component automatically detects if the list item should be clickable.
*
* ---
* If the `md-list-item` is clickable, we wrap all content inside of a `<div>` and create
* an overlaying button, which will will execute the given actions (like `ng-href`, `ng-click`)
*
* We create an overlaying button, instead of wrapping all content inside of the button,
* because otherwise some elements may not be clickable inside of the button.
*
* ---
* When using a secondary item inside of your list item, the `md-list-item` component will automatically create
* a secondary container at the end of the `md-list-item`, which contains all secondary items.
*
* The secondary item container is not static, because otherwise the overflow will not work properly on the
* list item.
*
*/
function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
var proxiedTypes = ['md-checkbox', 'md-switch', 'md-menu'];
return {
restrict: 'E',
controller: 'MdListController',
compile: function(tEl, tAttrs) {
// Check for proxy controls (no ng-click on parent, and a control inside)
var secondaryItems = tEl[0].querySelectorAll('.md-secondary');
var hasProxiedElement;
var proxyElement;
var itemContainer = tEl;
tEl[0].setAttribute('role', 'listitem');
if (tAttrs.ngClick || tAttrs.ngDblclick || tAttrs.ngHref || tAttrs.href || tAttrs.uiSref || tAttrs.ngAttrUiSref) {
wrapIn('button');
} else if (!tEl.hasClass('md-no-proxy')) {
for (var i = 0, type; type = proxiedTypes[i]; ++i) {
if (proxyElement = tEl[0].querySelector(type)) {
hasProxiedElement = true;
break;
}
}
if (hasProxiedElement) {
wrapIn('div');
} else {
tEl.addClass('md-no-proxy');
}
}
wrapSecondaryItems();
setupToggleAria();
if (hasProxiedElement && proxyElement.nodeName === "MD-MENU") {
setupProxiedMenu();
}
function setupToggleAria() {
var toggleTypes = ['md-switch', 'md-checkbox'];
var toggle;
for (var i = 0, toggleType; toggleType = toggleTypes[i]; ++i) {
if (toggle = tEl.find(toggleType)[0]) {
if (!toggle.hasAttribute('aria-label')) {
var p = tEl.find('p')[0];
if (!p) return;
toggle.setAttribute('aria-label', 'Toggle ' + p.textContent);
}
}
}
}
function setupProxiedMenu() {
var menuEl = angular.element(proxyElement);
var isEndAligned = menuEl.parent().hasClass('md-secondary-container') ||
proxyElement.parentNode.firstElementChild !== proxyElement;
var xAxisPosition = 'left';
if (isEndAligned) {
// When the proxy item is aligned at the end of the list, we have to set the origin to the end.
xAxisPosition = 'right';
}
// Set the position mode / origin of the proxied menu.
if (!menuEl.attr('md-position-mode')) {
menuEl.attr('md-position-mode', xAxisPosition + ' target');
}
// Apply menu open binding to menu button
var menuOpenButton = menuEl.children().eq(0);
if (!hasClickEvent(menuOpenButton[0])) {
menuOpenButton.attr('ng-click', '$mdMenu.open($event)');
}
if (!menuOpenButton.attr('aria-label')) {
menuOpenButton.attr('aria-label', 'Open List Menu');
}
}
function wrapIn(type) {
if (type == 'div') {
itemContainer = angular.element('<div class="md-no-style md-list-item-inner">');
itemContainer.append(tEl.contents());
tEl.addClass('md-proxy-focus');
} else {
// Element which holds the default list-item content.
itemContainer = angular.element(
'<div class="md-button md-no-style">'+
' <div class="md-list-item-inner"></div>'+
'</div>'
);
// Button which shows ripple and executes primary action.
var buttonWrap = angular.element(
'<md-button class="md-no-style"></md-button>'
);
copyAttributes(tEl[0], buttonWrap[0]);
// If there is no aria-label set on the button (previously copied over if present)
// we determine the label from the content and copy it to the button.
if (!buttonWrap.attr('aria-label')) {
buttonWrap.attr('aria-label', $mdAria.getText(tEl));
}
// We allow developers to specify the `md-no-focus` class, to disable the focus style
// on the button executor. Once more classes should be forwarded, we should probably make the
// class forward more generic.
if (tEl.hasClass('md-no-focus')) {
buttonWrap.addClass('md-no-focus');
}
// Append the button wrap before our list-item content, because it will overlay in relative.
itemContainer.prepend(buttonWrap);
itemContainer.children().eq(1).append(tEl.contents());
tEl.addClass('_md-button-wrap');
}
tEl[0].setAttribute('tabindex', '-1');
tEl.append(itemContainer);
}
function wrapSecondaryItems() {
var secondaryItemsWrapper = angular.element('<div class="md-secondary-container">');
angular.forEach(secondaryItems, function(secondaryItem) {
wrapSecondaryItem(secondaryItem, secondaryItemsWrapper);
});
itemContainer.append(secondaryItemsWrapper);
}
function wrapSecondaryItem(secondaryItem, container) {
// If the current secondary item is not a button, but contains a ng-click attribute,
// the secondary item will be automatically wrapped inside of a button.
if (secondaryItem && !isButton(secondaryItem) && secondaryItem.hasAttribute('ng-click')) {
$mdAria.expect(secondaryItem, 'aria-label');
var buttonWrapper = angular.element('<md-button class="md-secondary md-icon-button">');
// Copy the attributes from the secondary item to the generated button.
// We also support some additional attributes from the secondary item,
// because some developers may use a ngIf, ngHide, ngShow on their item.
copyAttributes(secondaryItem, buttonWrapper[0], ['ng-if', 'ng-hide', 'ng-show']);
secondaryItem.setAttribute('tabindex', '-1');
buttonWrapper.append(secondaryItem);
secondaryItem = buttonWrapper[0];
}
if (secondaryItem && (!hasClickEvent(secondaryItem) || (!tAttrs.ngClick && isProxiedElement(secondaryItem)))) {
// In this case we remove the secondary class, so we can identify it later, when we searching for the
// proxy items.
angular.element(secondaryItem).removeClass('md-secondary');
}
tEl.addClass('md-with-secondary');
container.append(secondaryItem);
}
/**
* Copies attributes from a source element to the destination element
* By default the function will copy the most necessary attributes, supported
* by the button executor for clickable list items.
* @param source Element with the specified attributes
* @param destination Element which will retrieve the attributes
* @param extraAttrs Additional attributes, which will be copied over.
*/
function copyAttributes(source, destination, extraAttrs) {
var copiedAttrs = $mdUtil.prefixer([
'ng-if', 'ng-click', 'ng-dblclick', 'aria-label', 'ng-disabled', 'ui-sref',
'href', 'ng-href', 'rel', 'target', 'ng-attr-ui-sref', 'ui-sref-opts'
]);
if (extraAttrs) {
copiedAttrs = copiedAttrs.concat($mdUtil.prefixer(extraAttrs));
}
angular.forEach(copiedAttrs, function(attr) {
if (source.hasAttribute(attr)) {
destination.setAttribute(attr, source.getAttribute(attr));
source.removeAttribute(attr);
}
});
}
function isProxiedElement(el) {
return proxiedTypes.indexOf(el.nodeName.toLowerCase()) != -1;
}
function isButton(el) {
var nodeName = el.nodeName.toUpperCase();
return nodeName == "MD-BUTTON" || nodeName == "BUTTON";
}
function hasClickEvent (element) {
var attr = element.attributes;
for (var i = 0; i < attr.length; i++) {
if (tAttrs.$normalize(attr[i].name) === 'ngClick') return true;
}
return false;
}
return postLink;
function postLink($scope, $element, $attr, ctrl) {
$element.addClass('_md'); // private md component indicator for styling
var proxies = [],
firstElement = $element[0].firstElementChild,
isButtonWrap = $element.hasClass('_md-button-wrap'),
clickChild = isButtonWrap ? firstElement.firstElementChild : firstElement,
hasClick = clickChild && hasClickEvent(clickChild),
noProxies = $element.hasClass('md-no-proxy');
computeProxies();
computeClickable();
if (proxies.length) {
angular.forEach(proxies, function(proxy) {
proxy = angular.element(proxy);
$scope.mouseActive = false;
proxy.on('mousedown', function() {
$scope.mouseActive = true;
$timeout(function(){
$scope.mouseActive = false;
}, 100);
})
.on('focus', function() {
if ($scope.mouseActive === false) { $element.addClass('md-focused'); }
proxy.on('blur', function proxyOnBlur() {
$element.removeClass('md-focused');
proxy.off('blur', proxyOnBlur);
});
});
});
}
function computeProxies() {
if (firstElement && firstElement.children && !hasClick && !noProxies) {
angular.forEach(proxiedTypes, function(type) {
// All elements which are not capable for being used a proxy have the .md-secondary class
// applied. These items had been sorted out in the secondary wrap function.
angular.forEach(firstElement.querySelectorAll(type + ':not(.md-secondary)'), function(child) {
proxies.push(child);
});
});
}
}
function computeClickable() {
if (proxies.length == 1 || hasClick) {
$element.addClass('md-clickable');
if (!hasClick) {
ctrl.attachRipple($scope, angular.element($element[0].querySelector('.md-no-style')));
}
}
}
function isEventFromControl(event) {
var forbiddenControls = ['md-slider'];
// If there is no path property in the event, then we can assume that the event was not bubbled.
if (!event.path) {
return forbiddenControls.indexOf(event.target.tagName.toLowerCase()) !== -1;
}
// We iterate the event path up and check for a possible component.
// Our maximum index to search, is the list item root.
var maxPath = event.path.indexOf($element.children()[0]);
for (var i = 0; i < maxPath; i++) {
if (forbiddenControls.indexOf(event.path[i].tagName.toLowerCase()) !== -1) {
return true;
}
}
}
var clickChildKeypressListener = function(e) {
if (e.target.nodeName != 'INPUT' && e.target.nodeName != 'TEXTAREA' && !e.target.isContentEditable) {
var keyCode = e.which || e.keyCode;
if (keyCode == $mdConstant.KEY_CODE.SPACE) {
if (clickChild) {
clickChild.click();
e.preventDefault();
e.stopPropagation();
}
}
}
};
if (!hasClick && !proxies.length) {
clickChild && clickChild.addEventListener('keypress', clickChildKeypressListener);
}
$element.off('click');
$element.off('keypress');
if (proxies.length == 1 && clickChild) {
$element.children().eq(0).on('click', function(e) {
// When the event is coming from an control and it should not trigger the proxied element
// then we are skipping.
if (isEventFromControl(e)) return;
var parentButton = $mdUtil.getClosest(e.target, 'BUTTON');
if (!parentButton && clickChild.contains(e.target)) {
angular.forEach(proxies, function(proxy) {
if (e.target !== proxy && !proxy.contains(e.target)) {
if (proxy.nodeName === 'MD-MENU') {
proxy = proxy.children[0];
}
angular.element(proxy).triggerHandler('click');
}
});
}
});
}
$scope.$on('$destroy', function () {
clickChild && clickChild.removeEventListener('keypress', clickChildKeypressListener);
});
}
}
};
}
/*
* @private
* @ngdoc controller
* @name MdListController
* @module material.components.list
*
*/
function MdListController($scope, $element, $mdListInkRipple) {
var ctrl = this;
ctrl.attachRipple = attachRipple;
function attachRipple (scope, element) {
var options = {};
$mdListInkRipple.attach(scope, element, options);
}
}
ngmaterial.components.list = angular.module("material.components.list");

View File

@ -0,0 +1,18 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-menu-content.md-THEME_NAME-theme {
background-color: '{{background-A100}}'; }
md-menu-content.md-THEME_NAME-theme md-menu-item {
color: '{{background-A200-0.87}}'; }
md-menu-content.md-THEME_NAME-theme md-menu-item md-icon {
color: '{{background-A200-0.54}}'; }
md-menu-content.md-THEME_NAME-theme md-menu-item .md-button[disabled] {
color: '{{background-A200-0.25}}'; }
md-menu-content.md-THEME_NAME-theme md-menu-item .md-button[disabled] md-icon {
color: '{{background-A200-0.25}}'; }
md-menu-content.md-THEME_NAME-theme md-menu-divider {
background-color: '{{background-A200-0.11}}'; }

View File

@ -0,0 +1,153 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
.md-open-menu-container {
position: fixed;
left: 0;
top: 0;
z-index: 100;
opacity: 0;
border-radius: 2px;
max-height: calc(100vh - 10px);
overflow: auto; }
.md-open-menu-container md-menu-divider {
margin-top: 4px;
margin-bottom: 4px;
height: 1px;
min-height: 1px;
max-height: 1px;
width: 100%; }
.md-open-menu-container md-menu-content > * {
opacity: 0; }
.md-open-menu-container:not(.md-clickable) {
pointer-events: none; }
.md-open-menu-container.md-active {
opacity: 1;
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transition-duration: 200ms;
transition-duration: 200ms; }
.md-open-menu-container.md-active > md-menu-content > * {
opacity: 1;
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
-webkit-transition-duration: 200ms;
transition-duration: 200ms;
-webkit-transition-delay: 100ms;
transition-delay: 100ms; }
.md-open-menu-container.md-leave {
opacity: 0;
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
-webkit-transition-duration: 250ms;
transition-duration: 250ms; }
md-menu-content {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
padding: 8px 0;
max-height: 304px;
overflow-y: auto; }
md-menu-content.md-dense {
max-height: 208px; }
md-menu-content.md-dense md-menu-item {
height: 32px;
min-height: 0px; }
md-menu-item {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
min-height: 48px;
height: 48px;
-webkit-align-content: center;
align-content: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
/*
* We cannot use flex on <button> elements due to a bug in Firefox, so we also can't use it on
* <a> elements. Add some top padding to fix alignment since buttons automatically align their
* text vertically.
*/ }
md-menu-item > * {
width: 100%;
margin: auto 0;
padding-left: 16px;
padding-right: 16px; }
md-menu-item > a.md-button {
padding-top: 5px; }
md-menu-item > .md-button {
text-align: left;
display: inline-block;
border-radius: 0;
margin: auto 0;
font-size: 15px;
text-transform: none;
font-weight: 400;
height: 100%;
padding-left: 16px;
padding-right: 16px;
width: 100%; }
md-menu-item > .md-button::-moz-focus-inner {
padding: 0;
border: 0; }
[dir=rtl] md-menu-item > .md-button {
text-align: right; }
md-menu-item > .md-button md-icon {
margin: auto 16px auto 0; }
[dir=rtl] md-menu-item > .md-button md-icon {
margin: auto 0 auto 16px; }
md-menu-item > .md-button p {
display: inline-block;
margin: auto; }
md-menu-item > .md-button span {
margin-top: auto;
margin-bottom: auto; }
md-menu-item > .md-button .md-ripple-container {
border-radius: inherit; }
md-toolbar .md-menu {
height: auto;
margin: auto;
padding: 0; }
@media (max-width: 959px) {
md-menu-content {
min-width: 112px; }
md-menu-content[width="3"] {
min-width: 168px; }
md-menu-content[width="4"] {
min-width: 224px; }
md-menu-content[width="5"] {
min-width: 280px; }
md-menu-content[width="6"] {
min-width: 336px; }
md-menu-content[width="7"] {
min-width: 392px; } }
@media (min-width: 960px) {
md-menu-content {
min-width: 96px; }
md-menu-content[width="3"] {
min-width: 192px; }
md-menu-content[width="4"] {
min-width: 256px; }
md-menu-content[width="5"] {
min-width: 320px; }
md-menu-content[width="6"] {
min-width: 384px; }
md-menu-content[width="7"] {
min-width: 448px; } }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-menu-bar.md-THEME_NAME-theme > button.md-button {
color: '{{foreground-2}}';
border-radius: 2px; }
md-menu-bar.md-THEME_NAME-theme md-menu.md-open > button, md-menu-bar.md-THEME_NAME-theme md-menu > button:focus {
outline: none;
background: '{{background-200}}'; }
md-menu-bar.md-THEME_NAME-theme.md-open:not(.md-keyboard-mode) md-menu:hover > button {
background-color: '{{ background-500-0.2}}'; }
md-menu-bar.md-THEME_NAME-theme:not(.md-keyboard-mode):not(.md-open) md-menu button:hover,
md-menu-bar.md-THEME_NAME-theme:not(.md-keyboard-mode):not(.md-open) md-menu button:focus {
background: transparent; }
md-menu-content.md-THEME_NAME-theme .md-menu > .md-button:after {
color: '{{background-A200-0.54}}'; }
md-menu-content.md-THEME_NAME-theme .md-menu.md-open > .md-button {
background-color: '{{ background-500-0.2}}'; }
md-toolbar.md-THEME_NAME-theme.md-menu-toolbar {
background-color: '{{background-A100}}';
color: '{{background-A200}}'; }
md-toolbar.md-THEME_NAME-theme.md-menu-toolbar md-toolbar-filler {
background-color: '{{primary-color}}';
color: '{{background-A100-0.87}}'; }
md-toolbar.md-THEME_NAME-theme.md-menu-toolbar md-toolbar-filler md-icon {
color: '{{background-A100-0.87}}'; }

View File

@ -0,0 +1,99 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-toolbar.md-menu-toolbar h2.md-toolbar-tools {
line-height: 1rem;
height: auto;
padding: 28px;
padding-bottom: 12px; }
md-toolbar.md-has-open-menu {
position: relative;
z-index: 100; }
md-menu-bar {
padding: 0 20px;
display: block;
position: relative;
z-index: 2; }
md-menu-bar .md-menu {
display: inline-block;
padding: 0;
position: relative; }
md-menu-bar button {
font-size: 14px;
padding: 0 10px;
margin: 0;
border: 0;
background-color: transparent;
height: 40px; }
md-menu-bar md-backdrop.md-menu-backdrop {
z-index: -2; }
md-menu-content.md-menu-bar-menu.md-dense {
max-height: none;
padding: 16px 0; }
md-menu-content.md-menu-bar-menu.md-dense md-menu-item.md-indent {
position: relative; }
md-menu-content.md-menu-bar-menu.md-dense md-menu-item.md-indent > md-icon {
position: absolute;
padding: 0;
width: 24px;
top: 6px;
left: 24px; }
[dir=rtl] md-menu-content.md-menu-bar-menu.md-dense md-menu-item.md-indent > md-icon {
left: auto;
right: 24px; }
md-menu-content.md-menu-bar-menu.md-dense md-menu-item.md-indent > .md-button, md-menu-content.md-menu-bar-menu.md-dense md-menu-item.md-indent .md-menu > .md-button {
padding: 0 32px 0 64px; }
[dir=rtl] md-menu-content.md-menu-bar-menu.md-dense md-menu-item.md-indent > .md-button, [dir=rtl] md-menu-content.md-menu-bar-menu.md-dense md-menu-item.md-indent .md-menu > .md-button {
padding: 0 64px 0 32px; }
md-menu-content.md-menu-bar-menu.md-dense .md-button {
min-height: 0;
height: 32px; }
md-menu-content.md-menu-bar-menu.md-dense .md-button span {
float: left; }
[dir=rtl] md-menu-content.md-menu-bar-menu.md-dense .md-button span {
float: right; }
md-menu-content.md-menu-bar-menu.md-dense .md-button span.md-alt-text {
float: right;
margin: 0 8px; }
[dir=rtl] md-menu-content.md-menu-bar-menu.md-dense .md-button span.md-alt-text {
float: left; }
md-menu-content.md-menu-bar-menu.md-dense md-menu-divider {
margin: 8px 0; }
md-menu-content.md-menu-bar-menu.md-dense md-menu-item > .md-button, md-menu-content.md-menu-bar-menu.md-dense .md-menu > .md-button {
text-align: left; }
[dir=rtl] md-menu-content.md-menu-bar-menu.md-dense md-menu-item > .md-button, [dir=rtl] md-menu-content.md-menu-bar-menu.md-dense .md-menu > .md-button {
text-align: right; }
md-menu-content.md-menu-bar-menu.md-dense .md-menu {
padding: 0; }
md-menu-content.md-menu-bar-menu.md-dense .md-menu > .md-button {
position: relative;
margin: 0;
width: 100%;
text-transform: none;
font-weight: normal;
border-radius: 0px;
padding-left: 16px; }
[dir=rtl] md-menu-content.md-menu-bar-menu.md-dense .md-menu > .md-button {
padding-left: 0;
padding-right: 16px; }
md-menu-content.md-menu-bar-menu.md-dense .md-menu > .md-button:after {
display: block;
content: '\25BC';
position: absolute;
top: 0px;
speak: none;
-webkit-transform: rotate(270deg) scaleY(0.45) scaleX(0.9);
transform: rotate(270deg) scaleY(0.45) scaleX(0.9);
right: 28px; }
[dir=rtl] md-menu-content.md-menu-bar-menu.md-dense .md-menu > .md-button:after {
-webkit-transform: rotate(90deg) scaleY(0.45) scaleX(0.9);
transform: rotate(90deg) scaleY(0.45) scaleX(0.9); }
[dir=rtl] md-menu-content.md-menu-bar-menu.md-dense .md-menu > .md-button:after {
right: auto;
left: 28px; }

View File

@ -0,0 +1,616 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.menuBar');
goog.require('ngmaterial.components.icon');
goog.require('ngmaterial.components.menu');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.menuBar
*/
angular.module('material.components.menuBar', [
'material.core',
'material.components.icon',
'material.components.menu'
]);
MenuBarController['$inject'] = ["$scope", "$rootScope", "$element", "$attrs", "$mdConstant", "$document", "$mdUtil", "$timeout"];
angular
.module('material.components.menuBar')
.controller('MenuBarController', MenuBarController);
var BOUND_MENU_METHODS = ['handleKeyDown', 'handleMenuHover', 'scheduleOpenHoveredMenu', 'cancelScheduledOpen'];
/**
* ngInject
*/
function MenuBarController($scope, $rootScope, $element, $attrs, $mdConstant, $document, $mdUtil, $timeout) {
this.$element = $element;
this.$attrs = $attrs;
this.$mdConstant = $mdConstant;
this.$mdUtil = $mdUtil;
this.$document = $document;
this.$scope = $scope;
this.$rootScope = $rootScope;
this.$timeout = $timeout;
var self = this;
angular.forEach(BOUND_MENU_METHODS, function(methodName) {
self[methodName] = angular.bind(self, self[methodName]);
});
}
MenuBarController.prototype.init = function() {
var $element = this.$element;
var $mdUtil = this.$mdUtil;
var $scope = this.$scope;
var self = this;
var deregisterFns = [];
$element.on('keydown', this.handleKeyDown);
this.parentToolbar = $mdUtil.getClosest($element, 'MD-TOOLBAR');
deregisterFns.push(this.$rootScope.$on('$mdMenuOpen', function(event, el) {
if (self.getMenus().indexOf(el[0]) != -1) {
$element[0].classList.add('md-open');
el[0].classList.add('md-open');
self.currentlyOpenMenu = el.controller('mdMenu');
self.currentlyOpenMenu.registerContainerProxy(self.handleKeyDown);
self.enableOpenOnHover();
}
}));
deregisterFns.push(this.$rootScope.$on('$mdMenuClose', function(event, el, opts) {
var rootMenus = self.getMenus();
if (rootMenus.indexOf(el[0]) != -1) {
$element[0].classList.remove('md-open');
el[0].classList.remove('md-open');
}
if ($element[0].contains(el[0])) {
var parentMenu = el[0];
while (parentMenu && rootMenus.indexOf(parentMenu) == -1) {
parentMenu = $mdUtil.getClosest(parentMenu, 'MD-MENU', true);
}
if (parentMenu) {
if (!opts.skipFocus) parentMenu.querySelector('button:not([disabled])').focus();
self.currentlyOpenMenu = undefined;
self.disableOpenOnHover();
self.setKeyboardMode(true);
}
}
}));
$scope.$on('$destroy', function() {
self.disableOpenOnHover();
while (deregisterFns.length) {
deregisterFns.shift()();
}
});
this.setKeyboardMode(true);
};
MenuBarController.prototype.setKeyboardMode = function(enabled) {
if (enabled) this.$element[0].classList.add('md-keyboard-mode');
else this.$element[0].classList.remove('md-keyboard-mode');
};
MenuBarController.prototype.enableOpenOnHover = function() {
if (this.openOnHoverEnabled) return;
var self = this;
self.openOnHoverEnabled = true;
if (self.parentToolbar) {
self.parentToolbar.classList.add('md-has-open-menu');
// Needs to be on the next tick so it doesn't close immediately.
self.$mdUtil.nextTick(function() {
angular.element(self.parentToolbar).on('click', self.handleParentClick);
}, false);
}
angular
.element(self.getMenus())
.on('mouseenter', self.handleMenuHover);
};
MenuBarController.prototype.handleMenuHover = function(e) {
this.setKeyboardMode(false);
if (this.openOnHoverEnabled) {
this.scheduleOpenHoveredMenu(e);
}
};
MenuBarController.prototype.disableOpenOnHover = function() {
if (!this.openOnHoverEnabled) return;
this.openOnHoverEnabled = false;
if (this.parentToolbar) {
this.parentToolbar.classList.remove('md-has-open-menu');
angular.element(this.parentToolbar).off('click', this.handleParentClick);
}
angular
.element(this.getMenus())
.off('mouseenter', this.handleMenuHover);
};
MenuBarController.prototype.scheduleOpenHoveredMenu = function(e) {
var menuEl = angular.element(e.currentTarget);
var menuCtrl = menuEl.controller('mdMenu');
this.setKeyboardMode(false);
this.scheduleOpenMenu(menuCtrl);
};
MenuBarController.prototype.scheduleOpenMenu = function(menuCtrl) {
var self = this;
var $timeout = this.$timeout;
if (menuCtrl != self.currentlyOpenMenu) {
$timeout.cancel(self.pendingMenuOpen);
self.pendingMenuOpen = $timeout(function() {
self.pendingMenuOpen = undefined;
if (self.currentlyOpenMenu) {
self.currentlyOpenMenu.close(true, { closeAll: true });
}
menuCtrl.open();
}, 200, false);
}
};
MenuBarController.prototype.handleKeyDown = function(e) {
var keyCodes = this.$mdConstant.KEY_CODE;
var currentMenu = this.currentlyOpenMenu;
var wasOpen = currentMenu && currentMenu.isOpen;
this.setKeyboardMode(true);
var handled, newMenu, newMenuCtrl;
switch (e.keyCode) {
case keyCodes.DOWN_ARROW:
if (currentMenu) {
currentMenu.focusMenuContainer();
} else {
this.openFocusedMenu();
}
handled = true;
break;
case keyCodes.UP_ARROW:
currentMenu && currentMenu.close();
handled = true;
break;
case keyCodes.LEFT_ARROW:
newMenu = this.focusMenu(-1);
if (wasOpen) {
newMenuCtrl = angular.element(newMenu).controller('mdMenu');
this.scheduleOpenMenu(newMenuCtrl);
}
handled = true;
break;
case keyCodes.RIGHT_ARROW:
newMenu = this.focusMenu(+1);
if (wasOpen) {
newMenuCtrl = angular.element(newMenu).controller('mdMenu');
this.scheduleOpenMenu(newMenuCtrl);
}
handled = true;
break;
}
if (handled) {
e && e.preventDefault && e.preventDefault();
e && e.stopImmediatePropagation && e.stopImmediatePropagation();
}
};
MenuBarController.prototype.focusMenu = function(direction) {
var menus = this.getMenus();
var focusedIndex = this.getFocusedMenuIndex();
if (focusedIndex == -1) { focusedIndex = this.getOpenMenuIndex(); }
var changed = false;
if (focusedIndex == -1) { focusedIndex = 0; changed = true; }
else if (
direction < 0 && focusedIndex > 0 ||
direction > 0 && focusedIndex < menus.length - direction
) {
focusedIndex += direction;
changed = true;
}
if (changed) {
menus[focusedIndex].querySelector('button').focus();
return menus[focusedIndex];
}
};
MenuBarController.prototype.openFocusedMenu = function() {
var menu = this.getFocusedMenu();
menu && angular.element(menu).controller('mdMenu').open();
};
MenuBarController.prototype.getMenus = function() {
var $element = this.$element;
return this.$mdUtil.nodesToArray($element[0].children)
.filter(function(el) { return el.nodeName == 'MD-MENU'; });
};
MenuBarController.prototype.getFocusedMenu = function() {
return this.getMenus()[this.getFocusedMenuIndex()];
};
MenuBarController.prototype.getFocusedMenuIndex = function() {
var $mdUtil = this.$mdUtil;
var focusedEl = $mdUtil.getClosest(
this.$document[0].activeElement,
'MD-MENU'
);
if (!focusedEl) return -1;
var focusedIndex = this.getMenus().indexOf(focusedEl);
return focusedIndex;
};
MenuBarController.prototype.getOpenMenuIndex = function() {
var menus = this.getMenus();
for (var i = 0; i < menus.length; ++i) {
if (menus[i].classList.contains('md-open')) return i;
}
return -1;
};
MenuBarController.prototype.handleParentClick = function(event) {
var openMenu = this.querySelector('md-menu.md-open');
if (openMenu && !openMenu.contains(event.target)) {
angular.element(openMenu).controller('mdMenu').close(true, {
closeAll: true
});
}
};
/**
* @ngdoc directive
* @name mdMenuBar
* @module material.components.menuBar
* @restrict E
* @description
*
* Menu bars are containers that hold multiple menus. They change the behavior and appearence
* of the `md-menu` directive to behave similar to an operating system provided menu.
*
* @usage
* <hljs lang="html">
* <md-menu-bar>
* <md-menu>
* <button ng-click="$mdMenu.open()">
* File
* </button>
* <md-menu-content>
* <md-menu-item>
* <md-button ng-click="ctrl.sampleAction('share', $event)">
* Share...
* </md-button>
* </md-menu-item>
* <md-menu-divider></md-menu-divider>
* <md-menu-item>
* <md-menu-item>
* <md-menu>
* <md-button ng-click="$mdMenu.open()">New</md-button>
* <md-menu-content>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Document', $event)">Document</md-button></md-menu-item>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Spreadsheet', $event)">Spreadsheet</md-button></md-menu-item>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Presentation', $event)">Presentation</md-button></md-menu-item>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Form', $event)">Form</md-button></md-menu-item>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Drawing', $event)">Drawing</md-button></md-menu-item>
* </md-menu-content>
* </md-menu>
* </md-menu-item>
* </md-menu-content>
* </md-menu>
* </md-menu-bar>
* </hljs>
*
* ## Menu Bar Controls
*
* You may place `md-menu-items` that function as controls within menu bars.
* There are two modes that are exposed via the `type` attribute of the `md-menu-item`.
* `type="checkbox"` will function as a boolean control for the `ng-model` attribute of the
* `md-menu-item`. `type="radio"` will function like a radio button, setting the `ngModel`
* to the `string` value of the `value` attribute. If you need non-string values, you can use
* `ng-value` to provide an expression (this is similar to how angular's native `input[type=radio]` works.
*
* <hljs lang="html">
* <md-menu-bar>
* <md-menu>
* <button ng-click="$mdMenu.open()">
* Sample Menu
* </button>
* <md-menu-content>
* <md-menu-item type="checkbox" ng-model="settings.allowChanges">Allow changes</md-menu-item>
* <md-menu-divider></md-menu-divider>
* <md-menu-item type="radio" ng-model="settings.mode" ng-value="1">Mode 1</md-menu-item>
* <md-menu-item type="radio" ng-model="settings.mode" ng-value="1">Mode 2</md-menu-item>
* <md-menu-item type="radio" ng-model="settings.mode" ng-value="1">Mode 3</md-menu-item>
* </md-menu-content>
* </md-menu>
* </md-menu-bar>
* </hljs>
*
*
* ### Nesting Menus
*
* Menus may be nested within menu bars. This is commonly called cascading menus.
* To nest a menu place the nested menu inside the content of the `md-menu-item`.
* <hljs lang="html">
* <md-menu-item>
* <md-menu>
* <button ng-click="$mdMenu.open()">New</md-button>
* <md-menu-content>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Document', $event)">Document</md-button></md-menu-item>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Spreadsheet', $event)">Spreadsheet</md-button></md-menu-item>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Presentation', $event)">Presentation</md-button></md-menu-item>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Form', $event)">Form</md-button></md-menu-item>
* <md-menu-item><md-button ng-click="ctrl.sampleAction('New Drawing', $event)">Drawing</md-button></md-menu-item>
* </md-menu-content>
* </md-menu>
* </md-menu-item>
* </hljs>
*
*/
MenuBarDirective['$inject'] = ["$mdUtil", "$mdTheming"];
angular
.module('material.components.menuBar')
.directive('mdMenuBar', MenuBarDirective);
/* ngInject */
function MenuBarDirective($mdUtil, $mdTheming) {
return {
restrict: 'E',
require: 'mdMenuBar',
controller: 'MenuBarController',
compile: function compile(templateEl, templateAttrs) {
if (!templateAttrs.ariaRole) {
templateEl[0].setAttribute('role', 'menubar');
}
angular.forEach(templateEl[0].children, function(menuEl) {
if (menuEl.nodeName == 'MD-MENU') {
if (!menuEl.hasAttribute('md-position-mode')) {
menuEl.setAttribute('md-position-mode', 'left bottom');
// Since we're in the compile function and actual `md-buttons` are not compiled yet,
// we need to query for possible `md-buttons` as well.
menuEl.querySelector('button, a, md-button').setAttribute('role', 'menuitem');
}
var contentEls = $mdUtil.nodesToArray(menuEl.querySelectorAll('md-menu-content'));
angular.forEach(contentEls, function(contentEl) {
contentEl.classList.add('md-menu-bar-menu');
contentEl.classList.add('md-dense');
if (!contentEl.hasAttribute('width')) {
contentEl.setAttribute('width', 5);
}
});
}
});
// Mark the child menu items that they're inside a menu bar. This is necessary,
// because mnMenuItem has special behaviour during compilation, depending on
// whether it is inside a mdMenuBar. We can usually figure this out via the DOM,
// however if a directive that uses documentFragment is applied to the child (e.g. ngRepeat),
// the element won't have a parent and won't compile properly.
templateEl.find('md-menu-item').addClass('md-in-menu-bar');
return function postLink(scope, el, attr, ctrl) {
el.addClass('_md'); // private md component indicator for styling
$mdTheming(scope, el);
ctrl.init();
};
}
};
}
angular
.module('material.components.menuBar')
.directive('mdMenuDivider', MenuDividerDirective);
function MenuDividerDirective() {
return {
restrict: 'E',
compile: function(templateEl, templateAttrs) {
if (!templateAttrs.role) {
templateEl[0].setAttribute('role', 'separator');
}
}
};
}
MenuItemController['$inject'] = ["$scope", "$element", "$attrs"];
angular
.module('material.components.menuBar')
.controller('MenuItemController', MenuItemController);
/**
* ngInject
*/
function MenuItemController($scope, $element, $attrs) {
this.$element = $element;
this.$attrs = $attrs;
this.$scope = $scope;
}
MenuItemController.prototype.init = function(ngModel) {
var $element = this.$element;
var $attrs = this.$attrs;
this.ngModel = ngModel;
if ($attrs.type == 'checkbox' || $attrs.type == 'radio') {
this.mode = $attrs.type;
this.iconEl = $element[0].children[0];
this.buttonEl = $element[0].children[1];
if (ngModel) {
// Clear ngAria set attributes
this.initClickListeners();
}
}
};
// ngAria auto sets attributes on a menu-item with a ngModel.
// We don't want this because our content (buttons) get the focus
// and set their own aria attributes appropritately. Having both
// breaks NVDA / JAWS. This undeoes ngAria's attrs.
MenuItemController.prototype.clearNgAria = function() {
var el = this.$element[0];
var clearAttrs = ['role', 'tabindex', 'aria-invalid', 'aria-checked'];
angular.forEach(clearAttrs, function(attr) {
el.removeAttribute(attr);
});
};
MenuItemController.prototype.initClickListeners = function() {
var self = this;
var ngModel = this.ngModel;
var $scope = this.$scope;
var $attrs = this.$attrs;
var $element = this.$element;
var mode = this.mode;
this.handleClick = angular.bind(this, this.handleClick);
var icon = this.iconEl;
var button = angular.element(this.buttonEl);
var handleClick = this.handleClick;
$attrs.$observe('disabled', setDisabled);
setDisabled($attrs.disabled);
ngModel.$render = function render() {
self.clearNgAria();
if (isSelected()) {
icon.style.display = '';
button.attr('aria-checked', 'true');
} else {
icon.style.display = 'none';
button.attr('aria-checked', 'false');
}
};
$scope.$$postDigest(ngModel.$render);
function isSelected() {
if (mode == 'radio') {
var val = $attrs.ngValue ? $scope.$eval($attrs.ngValue) : $attrs.value;
return ngModel.$modelValue == val;
} else {
return ngModel.$modelValue;
}
}
function setDisabled(disabled) {
if (disabled) {
button.off('click', handleClick);
} else {
button.on('click', handleClick);
}
}
};
MenuItemController.prototype.handleClick = function(e) {
var mode = this.mode;
var ngModel = this.ngModel;
var $attrs = this.$attrs;
var newVal;
if (mode == 'checkbox') {
newVal = !ngModel.$modelValue;
} else if (mode == 'radio') {
newVal = $attrs.ngValue ? this.$scope.$eval($attrs.ngValue) : $attrs.value;
}
ngModel.$setViewValue(newVal);
ngModel.$render();
};
MenuItemDirective['$inject'] = ["$mdUtil", "$mdConstant", "$$mdSvgRegistry"];
angular
.module('material.components.menuBar')
.directive('mdMenuItem', MenuItemDirective);
/* ngInject */
function MenuItemDirective($mdUtil, $mdConstant, $$mdSvgRegistry) {
return {
controller: 'MenuItemController',
require: ['mdMenuItem', '?ngModel'],
priority: $mdConstant.BEFORE_NG_ARIA,
compile: function(templateEl, templateAttrs) {
var type = templateAttrs.type;
var inMenuBarClass = 'md-in-menu-bar';
// Note: This allows us to show the `check` icon for the md-menu-bar items.
// The `md-in-menu-bar` class is set by the mdMenuBar directive.
if ((type == 'checkbox' || type == 'radio') && templateEl.hasClass(inMenuBarClass)) {
var text = templateEl[0].textContent;
var buttonEl = angular.element('<md-button type="button"></md-button>');
var iconTemplate = '<md-icon md-svg-src="' + $$mdSvgRegistry.mdChecked + '"></md-icon>';
buttonEl.html(text);
buttonEl.attr('tabindex', '0');
templateEl.html('');
templateEl.append(angular.element(iconTemplate));
templateEl.append(buttonEl);
templateEl.addClass('md-indent').removeClass(inMenuBarClass);
setDefault('role', type == 'checkbox' ? 'menuitemcheckbox' : 'menuitemradio', buttonEl);
moveAttrToButton('ng-disabled');
} else {
setDefault('role', 'menuitem', templateEl[0].querySelector('md-button, button, a'));
}
return function(scope, el, attrs, ctrls) {
var ctrl = ctrls[0];
var ngModel = ctrls[1];
ctrl.init(ngModel);
};
function setDefault(attr, val, el) {
el = el || templateEl;
if (el instanceof angular.element) {
el = el[0];
}
if (!el.hasAttribute(attr)) {
el.setAttribute(attr, val);
}
}
function moveAttrToButton(attribute) {
var attributes = $mdUtil.prefixer(attribute);
angular.forEach(attributes, function(attr) {
if (templateEl[0].hasAttribute(attr)) {
var val = templateEl[0].getAttribute(attr);
buttonEl[0].setAttribute(attr, val);
templateEl[0].removeAttribute(attr);
}
});
}
}
};
}
ngmaterial.components.menuBar = angular.module("material.components.menuBar");

View File

@ -0,0 +1,76 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-nav-bar.md-THEME_NAME-theme .md-nav-bar {
background-color: transparent;
border-color: '{{foreground-4}}'; }
md-nav-bar.md-THEME_NAME-theme .md-button._md-nav-button.md-unselected {
color: '{{foreground-2}}'; }
md-nav-bar.md-THEME_NAME-theme md-nav-ink-bar {
color: '{{accent-color}}';
background: '{{accent-color}}'; }
md-nav-bar.md-THEME_NAME-theme.md-accent > .md-nav-bar {
background-color: '{{accent-color}}'; }
md-nav-bar.md-THEME_NAME-theme.md-accent > .md-nav-bar .md-button._md-nav-button {
color: '{{accent-A100}}'; }
md-nav-bar.md-THEME_NAME-theme.md-accent > .md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-THEME_NAME-theme.md-accent > .md-nav-bar .md-button._md-nav-button.md-focused {
color: '{{accent-contrast}}'; }
md-nav-bar.md-THEME_NAME-theme.md-accent > .md-nav-bar .md-button._md-nav-button.md-focused {
background: '{{accent-contrast-0.1}}'; }
md-nav-bar.md-THEME_NAME-theme.md-accent > .md-nav-bar md-nav-ink-bar {
color: '{{primary-600-1}}';
background: '{{primary-600-1}}'; }
md-nav-bar.md-THEME_NAME-theme.md-warn > .md-nav-bar {
background-color: '{{warn-color}}'; }
md-nav-bar.md-THEME_NAME-theme.md-warn > .md-nav-bar .md-button._md-nav-button {
color: '{{warn-100}}'; }
md-nav-bar.md-THEME_NAME-theme.md-warn > .md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-THEME_NAME-theme.md-warn > .md-nav-bar .md-button._md-nav-button.md-focused {
color: '{{warn-contrast}}'; }
md-nav-bar.md-THEME_NAME-theme.md-warn > .md-nav-bar .md-button._md-nav-button.md-focused {
background: '{{warn-contrast-0.1}}'; }
md-nav-bar.md-THEME_NAME-theme.md-primary > .md-nav-bar {
background-color: '{{primary-color}}'; }
md-nav-bar.md-THEME_NAME-theme.md-primary > .md-nav-bar .md-button._md-nav-button {
color: '{{primary-100}}'; }
md-nav-bar.md-THEME_NAME-theme.md-primary > .md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-THEME_NAME-theme.md-primary > .md-nav-bar .md-button._md-nav-button.md-focused {
color: '{{primary-contrast}}'; }
md-nav-bar.md-THEME_NAME-theme.md-primary > .md-nav-bar .md-button._md-nav-button.md-focused {
background: '{{primary-contrast-0.1}}'; }
md-toolbar > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar {
background-color: '{{primary-color}}'; }
md-toolbar > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button {
color: '{{primary-100}}'; }
md-toolbar > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-active, md-toolbar > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-focused {
color: '{{primary-contrast}}'; }
md-toolbar > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-focused {
background: '{{primary-contrast-0.1}}'; }
md-toolbar.md-accent > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar {
background-color: '{{accent-color}}'; }
md-toolbar.md-accent > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button {
color: '{{accent-A100}}'; }
md-toolbar.md-accent > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-accent > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-focused {
color: '{{accent-contrast}}'; }
md-toolbar.md-accent > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-focused {
background: '{{accent-contrast-0.1}}'; }
md-toolbar.md-accent > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar md-nav-ink-bar {
color: '{{primary-600-1}}';
background: '{{primary-600-1}}'; }
md-toolbar.md-warn > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar {
background-color: '{{warn-color}}'; }
md-toolbar.md-warn > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button {
color: '{{warn-100}}'; }
md-toolbar.md-warn > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-warn > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-focused {
color: '{{warn-contrast}}'; }
md-toolbar.md-warn > md-nav-bar.md-THEME_NAME-theme > .md-nav-bar .md-button._md-nav-button.md-focused {
background: '{{warn-contrast-0.1}}'; }

View File

@ -0,0 +1,61 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
/** Matches "md-tabs md-tabs-wrapper" style. */
.md-nav-bar {
border-style: solid;
border-width: 0 0 1px;
height: 48px;
position: relative; }
._md-nav-bar-list {
outline: none;
list-style: none;
margin: 0;
padding: 0;
box-sizing: border-box;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
.md-nav-item:first-of-type {
margin-left: 8px; }
.md-button._md-nav-button {
line-height: 24px;
margin: 0 4px;
padding: 12px 16px;
-webkit-transition: background-color 0.35s cubic-bezier(0.35, 0, 0.25, 1);
transition: background-color 0.35s cubic-bezier(0.35, 0, 0.25, 1); }
.md-button._md-nav-button:focus {
outline: none; }
.md-button._md-nav-button:hover {
background-color: inherit; }
md-nav-ink-bar {
bottom: 0;
height: 2px;
left: auto;
position: absolute;
right: auto;
background-color: black; }
md-nav-ink-bar._md-left {
-webkit-transition: left 0.125s cubic-bezier(0.35, 0, 0.25, 1), right 0.25s cubic-bezier(0.35, 0, 0.25, 1);
transition: left 0.125s cubic-bezier(0.35, 0, 0.25, 1), right 0.25s cubic-bezier(0.35, 0, 0.25, 1); }
md-nav-ink-bar._md-right {
-webkit-transition: left 0.25s cubic-bezier(0.35, 0, 0.25, 1), right 0.125s cubic-bezier(0.35, 0, 0.25, 1);
transition: left 0.25s cubic-bezier(0.35, 0, 0.25, 1), right 0.125s cubic-bezier(0.35, 0, 0.25, 1); }
md-nav-ink-bar.ng-animate {
-webkit-transition: none;
transition: none; }
md-nav-extra-content {
min-height: 48px;
padding-right: 12px; }

View File

@ -0,0 +1,588 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.navBar');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.navBar
*/
MdNavBarController['$inject'] = ["$element", "$scope", "$timeout", "$mdConstant"];
MdNavItem['$inject'] = ["$mdAria", "$$rAF"];
MdNavItemController['$inject'] = ["$element"];
MdNavBar['$inject'] = ["$mdAria", "$mdTheming"];
angular.module('material.components.navBar', ['material.core'])
.controller('MdNavBarController', MdNavBarController)
.directive('mdNavBar', MdNavBar)
.controller('MdNavItemController', MdNavItemController)
.directive('mdNavItem', MdNavItem);
/*****************************************************************************
* PUBLIC DOCUMENTATION *
*****************************************************************************/
/**
* @ngdoc directive
* @name mdNavBar
* @module material.components.navBar
*
* @restrict E
*
* @description
* The `<md-nav-bar>` directive renders a list of material tabs that can be used
* for top-level page navigation. Unlike `<md-tabs>`, it has no concept of a tab
* body and no bar pagination.
*
* Because it deals with page navigation, certain routing concepts are built-in.
* Route changes via via ng-href, ui-sref, or ng-click events are supported.
* Alternatively, the user could simply watch currentNavItem for changes.
*
* Accessibility functionality is implemented as a site navigator with a
* listbox, according to
* https://www.w3.org/TR/wai-aria-practices/#Site_Navigator_Tabbed_Style
*
* @param {string=} mdSelectedNavItem The name of the current tab; this must
* match the name attribute of `<md-nav-item>`
* @param {boolean=} mdNoInkBar If set to true, the ink bar will be hidden.
* @param {string=} navBarAriaLabel An aria-label for the nav-bar
*
* @usage
* <hljs lang="html">
* <md-nav-bar md-selected-nav-item="currentNavItem">
* <md-nav-item md-nav-click="goto('page1')" name="page1">
* Page One
* </md-nav-item>
* <md-nav-item md-nav-href="#page2" name="page3">Page Two</md-nav-item>
* <md-nav-item md-nav-sref="page3" name="page2">Page Three</md-nav-item>
* <md-nav-item
* md-nav-sref="app.page4"
* sref-opts="{reload: true, notify: true}"
* name="page4">
* Page Four
* </md-nav-item>
* </md-nav-bar>
*</hljs>
* <hljs lang="js">
* (function() {
* 'use strict';
*
* $rootScope.$on('$routeChangeSuccess', function(event, current) {
* $scope.currentLink = getCurrentLinkFromRoute(current);
* });
* });
* </hljs>
*/
/*****************************************************************************
* mdNavItem
*****************************************************************************/
/**
* @ngdoc directive
* @name mdNavItem
* @module material.components.navBar
*
* @restrict E
*
* @description
* `<md-nav-item>` describes a page navigation link within the `<md-nav-bar>`
* component. It renders an md-button as the actual link.
*
* Exactly one of the mdNavClick, mdNavHref, mdNavSref attributes are required
* to be specified.
*
* @param {Function=} mdNavClick Function which will be called when the
* link is clicked to change the page. Renders as an `ng-click`.
* @param {string=} mdNavHref url to transition to when this link is clicked.
* Renders as an `ng-href`.
* @param {string=} mdNavSref Ui-router state to transition to when this link is
* clicked. Renders as a `ui-sref`.
* @param {!Object=} srefOpts Ui-router options that are passed to the
* `$state.go()` function. See the [Ui-router documentation for details]
* (https://ui-router.github.io/docs/latest/interfaces/transition.transitionoptions.html).
* @param {string=} name The name of this link. Used by the nav bar to know
* which link is currently selected.
* @param {string=} aria-label Adds alternative text for accessibility
*
* @usage
* See `<md-nav-bar>` for usage.
*/
/*****************************************************************************
* IMPLEMENTATION *
*****************************************************************************/
function MdNavBar($mdAria, $mdTheming) {
return {
restrict: 'E',
transclude: true,
controller: MdNavBarController,
controllerAs: 'ctrl',
bindToController: true,
scope: {
'mdSelectedNavItem': '=?',
'mdNoInkBar': '=?',
'navBarAriaLabel': '@?',
},
template:
'<div class="md-nav-bar">' +
'<nav role="navigation">' +
'<ul class="_md-nav-bar-list" ng-transclude role="listbox"' +
'tabindex="0"' +
'ng-focus="ctrl.onFocus()"' +
'ng-keydown="ctrl.onKeydown($event)"' +
'aria-label="{{ctrl.navBarAriaLabel}}">' +
'</ul>' +
'</nav>' +
'<md-nav-ink-bar ng-hide="ctrl.mdNoInkBar"></md-nav-ink-bar>' +
'</div>',
link: function(scope, element, attrs, ctrl) {
$mdTheming(element);
if (!ctrl.navBarAriaLabel) {
$mdAria.expectAsync(element, 'aria-label', angular.noop);
}
},
};
}
/**
* Controller for the nav-bar component.
*
* Accessibility functionality is implemented as a site navigator with a
* listbox, according to
* https://www.w3.org/TR/wai-aria-practices/#Site_Navigator_Tabbed_Style
* @param {!angular.JQLite} $element
* @param {!angular.Scope} $scope
* @param {!angular.Timeout} $timeout
* @param {!Object} $mdConstant
* @constructor
* @final
* ngInject
*/
function MdNavBarController($element, $scope, $timeout, $mdConstant) {
// Injected variables
/** @private @const {!angular.Timeout} */
this._$timeout = $timeout;
/** @private @const {!angular.Scope} */
this._$scope = $scope;
/** @private @const {!Object} */
this._$mdConstant = $mdConstant;
// Data-bound variables.
/** @type {string} */
this.mdSelectedNavItem;
/** @type {string} */
this.navBarAriaLabel;
// State variables.
/** @type {?angular.JQLite} */
this._navBarEl = $element[0];
/** @type {?angular.JQLite} */
this._inkbar;
var self = this;
// need to wait for transcluded content to be available
var deregisterTabWatch = this._$scope.$watch(function() {
return self._navBarEl.querySelectorAll('._md-nav-button').length;
},
function(newLength) {
if (newLength > 0) {
self._initTabs();
deregisterTabWatch();
}
});
}
/**
* Initializes the tab components once they exist.
* @private
*/
MdNavBarController.prototype._initTabs = function() {
this._inkbar = angular.element(this._navBarEl.querySelector('md-nav-ink-bar'));
var self = this;
this._$timeout(function() {
self._updateTabs(self.mdSelectedNavItem, undefined);
});
this._$scope.$watch('ctrl.mdSelectedNavItem', function(newValue, oldValue) {
// Wait a digest before update tabs for products doing
// anything dynamic in the template.
self._$timeout(function() {
self._updateTabs(newValue, oldValue);
});
});
};
/**
* Set the current tab to be selected.
* @param {string|undefined} newValue New current tab name.
* @param {string|undefined} oldValue Previous tab name.
* @private
*/
MdNavBarController.prototype._updateTabs = function(newValue, oldValue) {
var self = this;
var tabs = this._getTabs();
// this._getTabs can return null if nav-bar has not yet been initialized
if(!tabs)
return;
var oldIndex = -1;
var newIndex = -1;
var newTab = this._getTabByName(newValue);
var oldTab = this._getTabByName(oldValue);
if (oldTab) {
oldTab.setSelected(false);
oldIndex = tabs.indexOf(oldTab);
}
if (newTab) {
newTab.setSelected(true);
newIndex = tabs.indexOf(newTab);
}
this._$timeout(function() {
self._updateInkBarStyles(newTab, newIndex, oldIndex);
});
};
/**
* Repositions the ink bar to the selected tab.
* @private
*/
MdNavBarController.prototype._updateInkBarStyles = function(tab, newIndex, oldIndex) {
this._inkbar.toggleClass('_md-left', newIndex < oldIndex)
.toggleClass('_md-right', newIndex > oldIndex);
this._inkbar.css({display: newIndex < 0 ? 'none' : ''});
if (tab) {
var tabEl = tab.getButtonEl();
var left = tabEl.offsetLeft;
this._inkbar.css({left: left + 'px', width: tabEl.offsetWidth + 'px'});
}
};
/**
* Returns an array of the current tabs.
* @return {!Array<!NavItemController>}
* @private
*/
MdNavBarController.prototype._getTabs = function() {
var controllers = Array.prototype.slice.call(
this._navBarEl.querySelectorAll('.md-nav-item'))
.map(function(el) {
return angular.element(el).controller('mdNavItem')
});
return controllers.indexOf(undefined) ? controllers : null;
};
/**
* Returns the tab with the specified name.
* @param {string} name The name of the tab, found in its name attribute.
* @return {!NavItemController|undefined}
* @private
*/
MdNavBarController.prototype._getTabByName = function(name) {
return this._findTab(function(tab) {
return tab.getName() == name;
});
};
/**
* Returns the selected tab.
* @return {!NavItemController|undefined}
* @private
*/
MdNavBarController.prototype._getSelectedTab = function() {
return this._findTab(function(tab) {
return tab.isSelected();
});
};
/**
* Returns the focused tab.
* @return {!NavItemController|undefined}
*/
MdNavBarController.prototype.getFocusedTab = function() {
return this._findTab(function(tab) {
return tab.hasFocus();
});
};
/**
* Find a tab that matches the specified function.
* @private
*/
MdNavBarController.prototype._findTab = function(fn) {
var tabs = this._getTabs();
for (var i = 0; i < tabs.length; i++) {
if (fn(tabs[i])) {
return tabs[i];
}
}
return null;
};
/**
* Direct focus to the selected tab when focus enters the nav bar.
*/
MdNavBarController.prototype.onFocus = function() {
var tab = this._getSelectedTab();
if (tab) {
tab.setFocused(true);
}
};
/**
* Move focus from oldTab to newTab.
* @param {!NavItemController} oldTab
* @param {!NavItemController} newTab
* @private
*/
MdNavBarController.prototype._moveFocus = function(oldTab, newTab) {
oldTab.setFocused(false);
newTab.setFocused(true);
};
/**
* Responds to keypress events.
* @param {!Event} e
*/
MdNavBarController.prototype.onKeydown = function(e) {
var keyCodes = this._$mdConstant.KEY_CODE;
var tabs = this._getTabs();
var focusedTab = this.getFocusedTab();
if (!focusedTab) return;
var focusedTabIndex = tabs.indexOf(focusedTab);
// use arrow keys to navigate between tabs
switch (e.keyCode) {
case keyCodes.UP_ARROW:
case keyCodes.LEFT_ARROW:
if (focusedTabIndex > 0) {
this._moveFocus(focusedTab, tabs[focusedTabIndex - 1]);
}
break;
case keyCodes.DOWN_ARROW:
case keyCodes.RIGHT_ARROW:
if (focusedTabIndex < tabs.length - 1) {
this._moveFocus(focusedTab, tabs[focusedTabIndex + 1]);
}
break;
case keyCodes.SPACE:
case keyCodes.ENTER:
// timeout to avoid a "digest already in progress" console error
this._$timeout(function() {
focusedTab.getButtonEl().click();
});
break;
}
};
/**
* ngInject
*/
function MdNavItem($mdAria, $$rAF) {
return {
restrict: 'E',
require: ['mdNavItem', '^mdNavBar'],
controller: MdNavItemController,
bindToController: true,
controllerAs: 'ctrl',
replace: true,
transclude: true,
template: function(tElement, tAttrs) {
var hasNavClick = tAttrs.mdNavClick;
var hasNavHref = tAttrs.mdNavHref;
var hasNavSref = tAttrs.mdNavSref;
var hasSrefOpts = tAttrs.srefOpts;
var navigationAttribute;
var navigationOptions;
var buttonTemplate;
// Cannot specify more than one nav attribute
if ((hasNavClick ? 1:0) + (hasNavHref ? 1:0) + (hasNavSref ? 1:0) > 1) {
throw Error(
'Must not specify more than one of the md-nav-click, md-nav-href, ' +
'or md-nav-sref attributes per nav-item directive.'
);
}
if (hasNavClick) {
navigationAttribute = 'ng-click="ctrl.mdNavClick()"';
} else if (hasNavHref) {
navigationAttribute = 'ng-href="{{ctrl.mdNavHref}}"';
} else if (hasNavSref) {
navigationAttribute = 'ui-sref="{{ctrl.mdNavSref}}"';
}
navigationOptions = hasSrefOpts ? 'ui-sref-opts="{{ctrl.srefOpts}}" ' : '';
if (navigationAttribute) {
buttonTemplate = '' +
'<md-button class="_md-nav-button md-accent" ' +
'ng-class="ctrl.getNgClassMap()" ' +
'ng-blur="ctrl.setFocused(false)" ' +
'tabindex="-1" ' +
navigationOptions +
navigationAttribute + '>' +
'<span ng-transclude class="_md-nav-button-text"></span>' +
'</md-button>';
}
return '' +
'<li class="md-nav-item" ' +
'role="option" ' +
'aria-selected="{{ctrl.isSelected()}}">' +
(buttonTemplate || '') +
'</li>';
},
scope: {
'mdNavClick': '&?',
'mdNavHref': '@?',
'mdNavSref': '@?',
'srefOpts': '=?',
'name': '@',
},
link: function(scope, element, attrs, controllers) {
// When accessing the element's contents synchronously, they
// may not be defined yet because of transclusion. There is a higher
// chance that it will be accessible if we wait one frame.
$$rAF(function() {
var mdNavItem = controllers[0];
var mdNavBar = controllers[1];
var navButton = angular.element(element[0].querySelector('._md-nav-button'));
if (!mdNavItem.name) {
mdNavItem.name = angular.element(element[0]
.querySelector('._md-nav-button-text')).text().trim();
}
navButton.on('click', function() {
mdNavBar.mdSelectedNavItem = mdNavItem.name;
scope.$apply();
});
$mdAria.expectWithText(element, 'aria-label');
});
}
};
}
/**
* Controller for the nav-item component.
* @param {!angular.JQLite} $element
* @constructor
* @final
* ngInject
*/
function MdNavItemController($element) {
/** @private @const {!angular.JQLite} */
this._$element = $element;
// Data-bound variables
/** @const {?Function} */
this.mdNavClick;
/** @const {?string} */
this.mdNavHref;
/** @const {?string} */
this.mdNavSref;
/** @const {?Object} */
this.srefOpts;
/** @const {?string} */
this.name;
// State variables
/** @private {boolean} */
this._selected = false;
/** @private {boolean} */
this._focused = false;
}
/**
* Returns a map of class names and values for use by ng-class.
* @return {!Object<string,boolean>}
*/
MdNavItemController.prototype.getNgClassMap = function() {
return {
'md-active': this._selected,
'md-primary': this._selected,
'md-unselected': !this._selected,
'md-focused': this._focused,
};
};
/**
* Get the name attribute of the tab.
* @return {string}
*/
MdNavItemController.prototype.getName = function() {
return this.name;
};
/**
* Get the button element associated with the tab.
* @return {!Element}
*/
MdNavItemController.prototype.getButtonEl = function() {
return this._$element[0].querySelector('._md-nav-button');
};
/**
* Set the selected state of the tab.
* @param {boolean} isSelected
*/
MdNavItemController.prototype.setSelected = function(isSelected) {
this._selected = isSelected;
};
/**
* @return {boolean}
*/
MdNavItemController.prototype.isSelected = function() {
return this._selected;
};
/**
* Set the focused state of the tab.
* @param {boolean} isFocused
*/
MdNavItemController.prototype.setFocused = function(isFocused) {
this._focused = isFocused;
if (isFocused) {
this.getButtonEl().focus();
}
};
/**
* @return {boolean}
*/
MdNavItemController.prototype.hasFocus = function() {
return this._focused;
};
ngmaterial.components.navBar = angular.module("material.components.navBar");

View File

@ -0,0 +1,8 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
._md-panel-backdrop.md-THEME_NAME-theme {
background-color: '{{background-900-1.0}}'; }

View File

@ -0,0 +1,60 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
.md-panel-outer-wrapper {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%; }
._md-panel-hidden {
display: none; }
._md-panel-offscreen {
left: -9999px; }
._md-panel-fullscreen {
border-radius: 0;
left: 0;
min-height: 100%;
min-width: 100%;
position: fixed;
top: 0; }
._md-panel-shown .md-panel {
opacity: 1;
-webkit-transition: none;
transition: none; }
.md-panel {
opacity: 0;
position: fixed; }
.md-panel._md-panel-shown {
opacity: 1;
-webkit-transition: none;
transition: none; }
.md-panel._md-panel-animate-enter {
opacity: 1;
-webkit-transition: all 0.3s cubic-bezier(0, 0, 0.2, 1);
transition: all 0.3s cubic-bezier(0, 0, 0.2, 1); }
.md-panel._md-panel-animate-leave {
opacity: 1;
-webkit-transition: all 0.3s cubic-bezier(0.4, 0, 1, 1);
transition: all 0.3s cubic-bezier(0.4, 0, 1, 1); }
.md-panel._md-panel-animate-scale-out, .md-panel._md-panel-animate-fade-out {
opacity: 0; }
.md-panel._md-panel-backdrop {
height: 100%;
position: absolute;
width: 100%; }
.md-panel._md-opaque-enter {
opacity: .48;
-webkit-transition: opacity 0.3s cubic-bezier(0, 0, 0.2, 1);
transition: opacity 0.3s cubic-bezier(0, 0, 0.2, 1); }
.md-panel._md-opaque-leave {
-webkit-transition: opacity 0.3s cubic-bezier(0.4, 0, 1, 1);
transition: opacity 0.3s cubic-bezier(0.4, 0, 1, 1); }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-progress-circular.md-THEME_NAME-theme path {
stroke: '{{primary-color}}'; }
md-progress-circular.md-THEME_NAME-theme.md-warn path {
stroke: '{{warn-color}}'; }
md-progress-circular.md-THEME_NAME-theme.md-accent path {
stroke: '{{accent-color}}'; }

View File

@ -0,0 +1,35 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
@-webkit-keyframes indeterminate-rotate {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg); }
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg); } }
@keyframes indeterminate-rotate {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg); }
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg); } }
md-progress-circular {
position: relative;
display: block; }
md-progress-circular._md-progress-circular-disabled {
visibility: hidden; }
md-progress-circular.md-mode-indeterminate svg {
-webkit-animation: indeterminate-rotate 1568.63ms linear infinite;
animation: indeterminate-rotate 1568.63ms linear infinite; }
md-progress-circular svg {
position: absolute;
overflow: visible;
top: 0;
left: 0; }

View File

@ -0,0 +1,459 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.progressCircular');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.progressCircular
* @description Module for a circular progressbar
*/
angular.module('material.components.progressCircular', ['material.core']);
/**
* @ngdoc directive
* @name mdProgressCircular
* @module material.components.progressCircular
* @restrict E
*
* @description
* The circular progress directive is used to make loading content in your app as delightful and
* painless as possible by minimizing the amount of visual change a user sees before they can view
* and interact with content.
*
* For operations where the percentage of the operation completed can be determined, use a
* determinate indicator. They give users a quick sense of how long an operation will take.
*
* For operations where the user is asked to wait a moment while something finishes up, and its
* not necessary to expose what's happening behind the scenes and how long it will take, use an
* indeterminate indicator.
*
* @param {string} md-mode Select from one of two modes: **'determinate'** and **'indeterminate'**.
*
* Note: if the `md-mode` value is set as undefined or specified as not 1 of the two (2) valid modes, then **'indeterminate'**
* will be auto-applied as the mode.
*
* Note: if not configured, the `md-mode="indeterminate"` will be auto injected as an attribute.
* If `value=""` is also specified, however, then `md-mode="determinate"` would be auto-injected instead.
* @param {number=} value In determinate mode, this number represents the percentage of the
* circular progress. Default: 0
* @param {number=} md-diameter This specifies the diameter of the circular progress. The value
* should be a pixel-size value (eg '100'). If this attribute is
* not present then a default value of '50px' is assumed.
*
* @param {boolean=} ng-disabled Determines whether to disable the progress element.
*
* @usage
* <hljs lang="html">
* <md-progress-circular md-mode="determinate" value="..."></md-progress-circular>
*
* <md-progress-circular md-mode="determinate" ng-value="..."></md-progress-circular>
*
* <md-progress-circular md-mode="determinate" value="..." md-diameter="100"></md-progress-circular>
*
* <md-progress-circular md-mode="indeterminate"></md-progress-circular>
* </hljs>
*/
MdProgressCircularDirective['$inject'] = ["$window", "$mdProgressCircular", "$mdTheming", "$mdUtil", "$interval", "$log"];
angular
.module('material.components.progressCircular')
.directive('mdProgressCircular', MdProgressCircularDirective);
/* ngInject */
function MdProgressCircularDirective($window, $mdProgressCircular, $mdTheming,
$mdUtil, $interval, $log) {
// Note that this shouldn't use use $$rAF, because it can cause an infinite loop
// in any tests that call $animate.flush.
var rAF = $window.requestAnimationFrame ||
$window.webkitRequestAnimationFrame ||
angular.noop;
var cAF = $window.cancelAnimationFrame ||
$window.webkitCancelAnimationFrame ||
$window.webkitCancelRequestAnimationFrame ||
angular.noop;
var MODE_DETERMINATE = 'determinate';
var MODE_INDETERMINATE = 'indeterminate';
var DISABLED_CLASS = '_md-progress-circular-disabled';
var INDETERMINATE_CLASS = 'md-mode-indeterminate';
return {
restrict: 'E',
scope: {
value: '@',
mdDiameter: '@',
mdMode: '@'
},
template:
'<svg xmlns="http://www.w3.org/2000/svg">' +
'<path fill="none"/>' +
'</svg>',
compile: function(element, attrs) {
element.attr({
'aria-valuemin': 0,
'aria-valuemax': 100,
'role': 'progressbar'
});
if (angular.isUndefined(attrs.mdMode)) {
var mode = attrs.hasOwnProperty('value') ? MODE_DETERMINATE : MODE_INDETERMINATE;
attrs.$set('mdMode', mode);
} else {
attrs.$set('mdMode', attrs.mdMode.trim());
}
return MdProgressCircularLink;
}
};
function MdProgressCircularLink(scope, element, attrs) {
var node = element[0];
var svg = angular.element(node.querySelector('svg'));
var path = angular.element(node.querySelector('path'));
var startIndeterminate = $mdProgressCircular.startIndeterminate;
var endIndeterminate = $mdProgressCircular.endIndeterminate;
var iterationCount = 0;
var lastAnimationId = 0;
var lastDrawFrame;
var interval;
$mdTheming(element);
element.toggleClass(DISABLED_CLASS, attrs.hasOwnProperty('disabled'));
// If the mode is indeterminate, it doesn't need to
// wait for the next digest. It can start right away.
if(scope.mdMode === MODE_INDETERMINATE){
startIndeterminateAnimation();
}
scope.$on('$destroy', function(){
cleanupIndeterminateAnimation();
if (lastDrawFrame) {
cAF(lastDrawFrame);
}
});
scope.$watchGroup(['value', 'mdMode', function() {
var isDisabled = node.disabled;
// Sometimes the browser doesn't return a boolean, in
// which case we should check whether the attribute is
// present.
if (isDisabled === true || isDisabled === false){
return isDisabled;
}
return angular.isDefined(element.attr('disabled'));
}], function(newValues, oldValues) {
var mode = newValues[1];
var isDisabled = newValues[2];
var wasDisabled = oldValues[2];
if (isDisabled !== wasDisabled) {
element.toggleClass(DISABLED_CLASS, !!isDisabled);
}
if (isDisabled) {
cleanupIndeterminateAnimation();
} else {
if (mode !== MODE_DETERMINATE && mode !== MODE_INDETERMINATE) {
mode = MODE_INDETERMINATE;
attrs.$set('mdMode', mode);
}
if (mode === MODE_INDETERMINATE) {
startIndeterminateAnimation();
} else {
var newValue = clamp(newValues[0]);
cleanupIndeterminateAnimation();
element.attr('aria-valuenow', newValue);
renderCircle(clamp(oldValues[0]), newValue);
}
}
});
// This is in a separate watch in order to avoid layout, unless
// the value has actually changed.
scope.$watch('mdDiameter', function(newValue) {
var diameter = getSize(newValue);
var strokeWidth = getStroke(diameter);
var value = clamp(scope.value);
var transformOrigin = (diameter / 2) + 'px';
var dimensions = {
width: diameter + 'px',
height: diameter + 'px'
};
// The viewBox has to be applied via setAttribute, because it is
// case-sensitive. If jQuery is included in the page, `.attr` lowercases
// all attribute names.
svg[0].setAttribute('viewBox', '0 0 ' + diameter + ' ' + diameter);
// Usually viewBox sets the dimensions for the SVG, however that doesn't
// seem to be the case on IE10.
// Important! The transform origin has to be set from here and it has to
// be in the format of "Ypx Ypx Ypx", otherwise the rotation wobbles in
// IE and Edge, because they don't account for the stroke width when
// rotating. Also "center" doesn't help in this case, it has to be a
// precise value.
svg
.css(dimensions)
.css('transform-origin', transformOrigin + ' ' + transformOrigin + ' ' + transformOrigin);
element.css(dimensions);
path.attr('stroke-width', strokeWidth);
path.attr('stroke-linecap', 'square');
if (scope.mdMode == MODE_INDETERMINATE) {
path.attr('d', getSvgArc(diameter, strokeWidth, true));
path.attr('stroke-dasharray', (diameter - strokeWidth) * $window.Math.PI * 0.75);
path.attr('stroke-dashoffset', getDashLength(diameter, strokeWidth, 1, 75));
} else {
path.attr('d', getSvgArc(diameter, strokeWidth, false));
path.attr('stroke-dasharray', (diameter - strokeWidth) * $window.Math.PI);
path.attr('stroke-dashoffset', getDashLength(diameter, strokeWidth, 0, 100));
renderCircle(value, value);
}
});
function renderCircle(animateFrom, animateTo, easing, duration, iterationCount, maxValue) {
var id = ++lastAnimationId;
var startTime = $mdUtil.now();
var changeInValue = animateTo - animateFrom;
var diameter = getSize(scope.mdDiameter);
var strokeWidth = getStroke(diameter);
var ease = easing || $mdProgressCircular.easeFn;
var animationDuration = duration || $mdProgressCircular.duration;
var rotation = -90 * (iterationCount || 0);
var dashLimit = maxValue || 100;
// No need to animate it if the values are the same
if (animateTo === animateFrom) {
renderFrame(animateTo);
} else {
lastDrawFrame = rAF(function animation() {
var currentTime = $window.Math.max(0, $window.Math.min($mdUtil.now() - startTime, animationDuration));
renderFrame(ease(currentTime, animateFrom, changeInValue, animationDuration));
// Do not allow overlapping animations
if (id === lastAnimationId && currentTime < animationDuration) {
lastDrawFrame = rAF(animation);
}
});
}
function renderFrame(value) {
path.attr('stroke-dashoffset', getDashLength(diameter, strokeWidth, value, dashLimit));
path.attr('transform','rotate(' + (rotation) + ' ' + diameter/2 + ' ' + diameter/2 + ')');
}
}
function animateIndeterminate() {
renderCircle(
startIndeterminate,
endIndeterminate,
$mdProgressCircular.easeFnIndeterminate,
$mdProgressCircular.durationIndeterminate,
iterationCount,
75
);
// The %4 technically isn't necessary, but it keeps the rotation
// under 360, instead of becoming a crazy large number.
iterationCount = ++iterationCount % 4;
}
function startIndeterminateAnimation() {
if (!interval) {
// Note that this interval isn't supposed to trigger a digest.
interval = $interval(
animateIndeterminate,
$mdProgressCircular.durationIndeterminate,
0,
false
);
animateIndeterminate();
element
.addClass(INDETERMINATE_CLASS)
.removeAttr('aria-valuenow');
}
}
function cleanupIndeterminateAnimation() {
if (interval) {
$interval.cancel(interval);
interval = null;
element.removeClass(INDETERMINATE_CLASS);
}
}
}
/**
* Returns SVG path data for progress circle
* Syntax spec: https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
*
* @param {number} diameter Diameter of the container.
* @param {number} strokeWidth Stroke width to be used when drawing circle
* @param {boolean} indeterminate Use if progress circle will be used for indeterminate
*
* @returns {string} String representation of an SVG arc.
*/
function getSvgArc(diameter, strokeWidth, indeterminate) {
var radius = diameter / 2;
var offset = strokeWidth / 2;
var start = radius + ',' + offset; // ie: (25, 2.5) or 12 o'clock
var end = offset + ',' + radius; // ie: (2.5, 25) or 9 o'clock
var arcRadius = radius - offset;
return 'M' + start
+ 'A' + arcRadius + ',' + arcRadius + ' 0 1 1 ' + end // 75% circle
+ (indeterminate ? '' : 'A' + arcRadius + ',' + arcRadius + ' 0 0 1 ' + start); // loop to start
}
/**
* Return stroke length for progress circle
*
* @param {number} diameter Diameter of the container.
* @param {number} strokeWidth Stroke width to be used when drawing circle
* @param {number} value Percentage of circle (between 0 and 100)
* @param {number} limit Max percentage for circle
*
* @returns {number} Stroke length for progres circle
*/
function getDashLength(diameter, strokeWidth, value, limit) {
return (diameter - strokeWidth) * $window.Math.PI * ( (3 * (limit || 100) / 100) - (value/100) );
}
/**
* Limits a value between 0 and 100.
*/
function clamp(value) {
return $window.Math.max(0, $window.Math.min(value || 0, 100));
}
/**
* Determines the size of a progress circle, based on the provided
* value in the following formats: `X`, `Ypx`, `Z%`.
*/
function getSize(value) {
var defaultValue = $mdProgressCircular.progressSize;
if (value) {
var parsed = parseFloat(value);
if (value.lastIndexOf('%') === value.length - 1) {
parsed = (parsed / 100) * defaultValue;
}
return parsed;
}
return defaultValue;
}
/**
* Determines the circle's stroke width, based on
* the provided diameter.
*/
function getStroke(diameter) {
return $mdProgressCircular.strokeWidth / 100 * diameter;
}
}
/**
* @ngdoc service
* @name $mdProgressCircular
* @module material.components.progressCircular
*
* @description
* Allows the user to specify the default options for the `progressCircular` directive.
*
* @property {number} progressSize Diameter of the progress circle in pixels.
* @property {number} strokeWidth Width of the circle's stroke as a percentage of the circle's size.
* @property {number} duration Length of the circle animation in milliseconds.
* @property {function} easeFn Default easing animation function.
* @property {object} easingPresets Collection of pre-defined easing functions.
*
* @property {number} durationIndeterminate Duration of the indeterminate animation.
* @property {number} startIndeterminate Indeterminate animation start point.
* @property {number} endIndeterminate Indeterminate animation end point.
* @property {function} easeFnIndeterminate Easing function to be used when animating
* between the indeterminate values.
*
* @property {(function(object): object)} configure Used to modify the default options.
*
* @usage
* <hljs lang="js">
* myAppModule.config(function($mdProgressCircularProvider) {
*
* // Example of changing the default progress options.
* $mdProgressCircularProvider.configure({
* progressSize: 100,
* strokeWidth: 20,
* duration: 800
* });
* });
* </hljs>
*
*/
angular
.module('material.components.progressCircular')
.provider("$mdProgressCircular", MdProgressCircularProvider);
function MdProgressCircularProvider() {
var progressConfig = {
progressSize: 50,
strokeWidth: 10,
duration: 100,
easeFn: linearEase,
durationIndeterminate: 1333,
startIndeterminate: 1,
endIndeterminate: 149,
easeFnIndeterminate: materialEase,
easingPresets: {
linearEase: linearEase,
materialEase: materialEase
}
};
return {
configure: function(options) {
progressConfig = angular.extend(progressConfig, options || {});
return progressConfig;
},
$get: function() { return progressConfig; }
};
function linearEase(t, b, c, d) {
return c * t / d + b;
}
function materialEase(t, b, c, d) {
// via http://www.timotheegroleau.com/Flash/experiments/easing_function_generator.htm
// with settings of [0, 0, 1, 1]
var ts = (t /= d) * t;
var tc = ts * t;
return b + c * (6 * tc * ts + -15 * ts * ts + 10 * tc);
}
}
ngmaterial.components.progressCircular = angular.module("material.components.progressCircular");

View File

@ -0,0 +1,44 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-progress-linear.md-THEME_NAME-theme .md-container {
background-color: '{{primary-100}}'; }
md-progress-linear.md-THEME_NAME-theme .md-bar {
background-color: '{{primary-color}}'; }
md-progress-linear.md-THEME_NAME-theme.md-warn .md-container {
background-color: '{{warn-100}}'; }
md-progress-linear.md-THEME_NAME-theme.md-warn .md-bar {
background-color: '{{warn-color}}'; }
md-progress-linear.md-THEME_NAME-theme.md-accent .md-container {
background-color: '{{accent-100}}'; }
md-progress-linear.md-THEME_NAME-theme.md-accent .md-bar {
background-color: '{{accent-color}}'; }
md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-primary .md-bar1 {
background-color: '{{primary-100}}'; }
md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-primary .md-dashed:before {
background: -webkit-radial-gradient("{{primary-100}}" 0%, "{{primary-100}}" 16%, transparent 42%);
background: radial-gradient("{{primary-100}}" 0%, "{{primary-100}}" 16%, transparent 42%); }
md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-warn .md-bar1 {
background-color: '{{warn-100}}'; }
md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-warn .md-dashed:before {
background: -webkit-radial-gradient("{{warn-100}}" 0%, "{{warn-100}}" 16%, transparent 42%);
background: radial-gradient("{{warn-100}}" 0%, "{{warn-100}}" 16%, transparent 42%); }
md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-accent .md-bar1 {
background-color: '{{accent-100}}'; }
md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-accent .md-dashed:before {
background: -webkit-radial-gradient("{{accent-100}}" 0%, "{{accent-100}}" 16%, transparent 42%);
background: radial-gradient("{{accent-100}}" 0%, "{{accent-100}}" 16%, transparent 42%); }

View File

@ -0,0 +1,261 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-progress-linear {
display: block;
position: relative;
width: 100%;
height: 5px;
padding-top: 0 !important;
margin-bottom: 0 !important; }
md-progress-linear._md-progress-linear-disabled {
visibility: hidden; }
md-progress-linear .md-container {
display: block;
position: relative;
overflow: hidden;
width: 100%;
height: 5px;
-webkit-transform: translate(0, 0) scale(1, 1);
transform: translate(0, 0) scale(1, 1); }
md-progress-linear .md-container .md-bar {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 100%;
height: 5px; }
md-progress-linear .md-container .md-dashed:before {
content: "";
display: none;
position: absolute;
margin-top: 0;
height: 5px;
width: 100%;
background-color: transparent;
background-size: 10px 10px !important;
background-position: 0px -23px; }
md-progress-linear .md-container .md-bar1, md-progress-linear .md-container .md-bar2 {
-webkit-transition: -webkit-transform 0.2s linear;
transition: -webkit-transform 0.2s linear;
transition: transform 0.2s linear;
transition: transform 0.2s linear, -webkit-transform 0.2s linear; }
md-progress-linear .md-container.md-mode-query .md-bar1 {
display: none; }
md-progress-linear .md-container.md-mode-query .md-bar2 {
-webkit-transition: all 0.2s linear;
transition: all 0.2s linear;
-webkit-animation: query 0.8s infinite cubic-bezier(0.39, 0.575, 0.565, 1);
animation: query 0.8s infinite cubic-bezier(0.39, 0.575, 0.565, 1); }
md-progress-linear .md-container.md-mode-determinate .md-bar1 {
display: none; }
md-progress-linear .md-container.md-mode-indeterminate .md-bar1 {
-webkit-animation: md-progress-linear-indeterminate-scale-1 4s infinite, md-progress-linear-indeterminate-1 4s infinite;
animation: md-progress-linear-indeterminate-scale-1 4s infinite, md-progress-linear-indeterminate-1 4s infinite; }
md-progress-linear .md-container.md-mode-indeterminate .md-bar2 {
-webkit-animation: md-progress-linear-indeterminate-scale-2 4s infinite, md-progress-linear-indeterminate-2 4s infinite;
animation: md-progress-linear-indeterminate-scale-2 4s infinite, md-progress-linear-indeterminate-2 4s infinite; }
md-progress-linear .md-container.ng-hide ._md-progress-linear-disabled md-progress-linear .md-container {
-webkit-animation: none;
animation: none; }
md-progress-linear .md-container.ng-hide ._md-progress-linear-disabled md-progress-linear .md-container .md-bar1 {
-webkit-animation-name: none;
animation-name: none; }
md-progress-linear .md-container.ng-hide ._md-progress-linear-disabled md-progress-linear .md-container .md-bar2 {
-webkit-animation-name: none;
animation-name: none; }
md-progress-linear .md-container.md-mode-buffer {
background-color: transparent !important;
-webkit-transition: all 0.2s linear;
transition: all 0.2s linear; }
md-progress-linear .md-container.md-mode-buffer .md-dashed:before {
display: block;
-webkit-animation: buffer 3s infinite linear;
animation: buffer 3s infinite linear; }
@-webkit-keyframes query {
0% {
opacity: 1;
-webkit-transform: translateX(35%) scale(0.3, 1);
transform: translateX(35%) scale(0.3, 1); }
100% {
opacity: 0;
-webkit-transform: translateX(-50%) scale(0, 1);
transform: translateX(-50%) scale(0, 1); } }
@keyframes query {
0% {
opacity: 1;
-webkit-transform: translateX(35%) scale(0.3, 1);
transform: translateX(35%) scale(0.3, 1); }
100% {
opacity: 0;
-webkit-transform: translateX(-50%) scale(0, 1);
transform: translateX(-50%) scale(0, 1); } }
@-webkit-keyframes buffer {
0% {
opacity: 1;
background-position: 0px -23px; }
50% {
opacity: 0; }
100% {
opacity: 1;
background-position: -200px -23px; } }
@keyframes buffer {
0% {
opacity: 1;
background-position: 0px -23px; }
50% {
opacity: 0; }
100% {
opacity: 1;
background-position: -200px -23px; } }
@-webkit-keyframes md-progress-linear-indeterminate-scale-1 {
0% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1);
-webkit-animation-timing-function: linear;
animation-timing-function: linear; }
36.6% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1);
-webkit-animation-timing-function: cubic-bezier(0.33473, 0.12482, 0.78584, 1);
animation-timing-function: cubic-bezier(0.33473, 0.12482, 0.78584, 1); }
69.15% {
-webkit-transform: scaleX(0.83);
transform: scaleX(0.83);
-webkit-animation-timing-function: cubic-bezier(0.22573, 0, 0.23365, 1.37098);
animation-timing-function: cubic-bezier(0.22573, 0, 0.23365, 1.37098); }
100% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1); } }
@keyframes md-progress-linear-indeterminate-scale-1 {
0% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1);
-webkit-animation-timing-function: linear;
animation-timing-function: linear; }
36.6% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1);
-webkit-animation-timing-function: cubic-bezier(0.33473, 0.12482, 0.78584, 1);
animation-timing-function: cubic-bezier(0.33473, 0.12482, 0.78584, 1); }
69.15% {
-webkit-transform: scaleX(0.83);
transform: scaleX(0.83);
-webkit-animation-timing-function: cubic-bezier(0.22573, 0, 0.23365, 1.37098);
animation-timing-function: cubic-bezier(0.22573, 0, 0.23365, 1.37098); }
100% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1); } }
@-webkit-keyframes md-progress-linear-indeterminate-1 {
0% {
left: -105.16667%;
-webkit-animation-timing-function: linear;
animation-timing-function: linear; }
20% {
left: -105.16667%;
-webkit-animation-timing-function: cubic-bezier(0.5, 0, 0.70173, 0.49582);
animation-timing-function: cubic-bezier(0.5, 0, 0.70173, 0.49582); }
69.15% {
left: 21.5%;
-webkit-animation-timing-function: cubic-bezier(0.30244, 0.38135, 0.55, 0.95635);
animation-timing-function: cubic-bezier(0.30244, 0.38135, 0.55, 0.95635); }
100% {
left: 95.44444%; } }
@keyframes md-progress-linear-indeterminate-1 {
0% {
left: -105.16667%;
-webkit-animation-timing-function: linear;
animation-timing-function: linear; }
20% {
left: -105.16667%;
-webkit-animation-timing-function: cubic-bezier(0.5, 0, 0.70173, 0.49582);
animation-timing-function: cubic-bezier(0.5, 0, 0.70173, 0.49582); }
69.15% {
left: 21.5%;
-webkit-animation-timing-function: cubic-bezier(0.30244, 0.38135, 0.55, 0.95635);
animation-timing-function: cubic-bezier(0.30244, 0.38135, 0.55, 0.95635); }
100% {
left: 95.44444%; } }
@-webkit-keyframes md-progress-linear-indeterminate-scale-2 {
0% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1);
-webkit-animation-timing-function: cubic-bezier(0.20503, 0.05705, 0.57661, 0.45397);
animation-timing-function: cubic-bezier(0.20503, 0.05705, 0.57661, 0.45397); }
19.15% {
-webkit-transform: scaleX(0.57);
transform: scaleX(0.57);
-webkit-animation-timing-function: cubic-bezier(0.15231, 0.19643, 0.64837, 1.00432);
animation-timing-function: cubic-bezier(0.15231, 0.19643, 0.64837, 1.00432); }
44.15% {
-webkit-transform: scaleX(0.91);
transform: scaleX(0.91);
-webkit-animation-timing-function: cubic-bezier(0.25776, -0.00316, 0.21176, 1.38179);
animation-timing-function: cubic-bezier(0.25776, -0.00316, 0.21176, 1.38179); }
100% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1); } }
@keyframes md-progress-linear-indeterminate-scale-2 {
0% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1);
-webkit-animation-timing-function: cubic-bezier(0.20503, 0.05705, 0.57661, 0.45397);
animation-timing-function: cubic-bezier(0.20503, 0.05705, 0.57661, 0.45397); }
19.15% {
-webkit-transform: scaleX(0.57);
transform: scaleX(0.57);
-webkit-animation-timing-function: cubic-bezier(0.15231, 0.19643, 0.64837, 1.00432);
animation-timing-function: cubic-bezier(0.15231, 0.19643, 0.64837, 1.00432); }
44.15% {
-webkit-transform: scaleX(0.91);
transform: scaleX(0.91);
-webkit-animation-timing-function: cubic-bezier(0.25776, -0.00316, 0.21176, 1.38179);
animation-timing-function: cubic-bezier(0.25776, -0.00316, 0.21176, 1.38179); }
100% {
-webkit-transform: scaleX(0.1);
transform: scaleX(0.1); } }
@-webkit-keyframes md-progress-linear-indeterminate-2 {
0% {
left: -54.88889%;
-webkit-animation-timing-function: cubic-bezier(0.15, 0, 0.51506, 0.40968);
animation-timing-function: cubic-bezier(0.15, 0, 0.51506, 0.40968); }
25% {
left: -17.25%;
-webkit-animation-timing-function: cubic-bezier(0.31033, 0.28406, 0.8, 0.73372);
animation-timing-function: cubic-bezier(0.31033, 0.28406, 0.8, 0.73372); }
48.35% {
left: 29.5%;
-webkit-animation-timing-function: cubic-bezier(0.4, 0.62703, 0.6, 0.90203);
animation-timing-function: cubic-bezier(0.4, 0.62703, 0.6, 0.90203); }
100% {
left: 117.38889%; } }
@keyframes md-progress-linear-indeterminate-2 {
0% {
left: -54.88889%;
-webkit-animation-timing-function: cubic-bezier(0.15, 0, 0.51506, 0.40968);
animation-timing-function: cubic-bezier(0.15, 0, 0.51506, 0.40968); }
25% {
left: -17.25%;
-webkit-animation-timing-function: cubic-bezier(0.31033, 0.28406, 0.8, 0.73372);
animation-timing-function: cubic-bezier(0.31033, 0.28406, 0.8, 0.73372); }
48.35% {
left: 29.5%;
-webkit-animation-timing-function: cubic-bezier(0.4, 0.62703, 0.6, 0.90203);
animation-timing-function: cubic-bezier(0.4, 0.62703, 0.6, 0.90203); }
100% {
left: 117.38889%; } }

View File

@ -0,0 +1,213 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.progressLinear');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.progressLinear
* @description Linear Progress module!
*/
MdProgressLinearDirective['$inject'] = ["$mdTheming", "$mdUtil", "$log"];
angular.module('material.components.progressLinear', [
'material.core'
])
.directive('mdProgressLinear', MdProgressLinearDirective);
/**
* @ngdoc directive
* @name mdProgressLinear
* @module material.components.progressLinear
* @restrict E
*
* @description
* The linear progress directive is used to make loading content
* in your app as delightful and painless as possible by minimizing
* the amount of visual change a user sees before they can view
* and interact with content.
*
* Each operation should only be represented by one activity indicator
* For example: one refresh operation should not display both a
* refresh bar and an activity circle.
*
* For operations where the percentage of the operation completed
* can be determined, use a determinate indicator. They give users
* a quick sense of how long an operation will take.
*
* For operations where the user is asked to wait a moment while
* something finishes up, and its not necessary to expose what's
* happening behind the scenes and how long it will take, use an
* indeterminate indicator.
*
* @param {string} md-mode Select from one of four modes: determinate, indeterminate, buffer or query.
*
* Note: if the `md-mode` value is set as undefined or specified as 1 of the four (4) valid modes, then `indeterminate`
* will be auto-applied as the mode.
*
* Note: if not configured, the `md-mode="indeterminate"` will be auto injected as an attribute. If `value=""` is also specified, however,
* then `md-mode="determinate"` would be auto-injected instead.
* @param {number=} value In determinate and buffer modes, this number represents the percentage of the primary progress bar. Default: 0
* @param {number=} md-buffer-value In the buffer mode, this number represents the percentage of the secondary progress bar. Default: 0
* @param {boolean=} ng-disabled Determines whether to disable the progress element.
*
* @usage
* <hljs lang="html">
* <md-progress-linear md-mode="determinate" value="..."></md-progress-linear>
*
* <md-progress-linear md-mode="determinate" ng-value="..."></md-progress-linear>
*
* <md-progress-linear md-mode="indeterminate"></md-progress-linear>
*
* <md-progress-linear md-mode="buffer" value="..." md-buffer-value="..."></md-progress-linear>
*
* <md-progress-linear md-mode="query"></md-progress-linear>
* </hljs>
*/
function MdProgressLinearDirective($mdTheming, $mdUtil, $log) {
var MODE_DETERMINATE = "determinate";
var MODE_INDETERMINATE = "indeterminate";
var MODE_BUFFER = "buffer";
var MODE_QUERY = "query";
var DISABLED_CLASS = "_md-progress-linear-disabled";
return {
restrict: 'E',
template: '<div class="md-container">' +
'<div class="md-dashed"></div>' +
'<div class="md-bar md-bar1"></div>' +
'<div class="md-bar md-bar2"></div>' +
'</div>',
compile: compile
};
function compile(tElement, tAttrs, transclude) {
tElement.attr('aria-valuemin', 0);
tElement.attr('aria-valuemax', 100);
tElement.attr('role', 'progressbar');
return postLink;
}
function postLink(scope, element, attr) {
$mdTheming(element);
var lastMode;
var isDisabled = attr.hasOwnProperty('disabled');
var toVendorCSS = $mdUtil.dom.animator.toCss;
var bar1 = angular.element(element[0].querySelector('.md-bar1'));
var bar2 = angular.element(element[0].querySelector('.md-bar2'));
var container = angular.element(element[0].querySelector('.md-container'));
element
.attr('md-mode', mode())
.toggleClass(DISABLED_CLASS, isDisabled);
validateMode();
watchAttributes();
/**
* Watch the value, md-buffer-value, and md-mode attributes
*/
function watchAttributes() {
attr.$observe('value', function(value) {
var percentValue = clamp(value);
element.attr('aria-valuenow', percentValue);
if (mode() != MODE_QUERY) animateIndicator(bar2, percentValue);
});
attr.$observe('mdBufferValue', function(value) {
animateIndicator(bar1, clamp(value));
});
attr.$observe('disabled', function(value) {
if (value === true || value === false) {
isDisabled = !!value;
} else {
isDisabled = angular.isDefined(value);
}
element.toggleClass(DISABLED_CLASS, isDisabled);
container.toggleClass(lastMode, !isDisabled);
});
attr.$observe('mdMode', function(mode) {
if (lastMode) container.removeClass( lastMode );
switch( mode ) {
case MODE_QUERY:
case MODE_BUFFER:
case MODE_DETERMINATE:
case MODE_INDETERMINATE:
container.addClass( lastMode = "md-mode-" + mode );
break;
default:
container.addClass( lastMode = "md-mode-" + MODE_INDETERMINATE );
break;
}
});
}
/**
* Auto-defaults the mode to either `determinate` or `indeterminate` mode; if not specified
*/
function validateMode() {
if ( angular.isUndefined(attr.mdMode) ) {
var hasValue = angular.isDefined(attr.value);
var mode = hasValue ? MODE_DETERMINATE : MODE_INDETERMINATE;
var info = "Auto-adding the missing md-mode='{0}' to the ProgressLinear element";
//$log.debug( $mdUtil.supplant(info, [mode]) );
element.attr("md-mode", mode);
attr.mdMode = mode;
}
}
/**
* Is the md-mode a valid option?
*/
function mode() {
var value = (attr.mdMode || "").trim();
if ( value ) {
switch(value) {
case MODE_DETERMINATE:
case MODE_INDETERMINATE:
case MODE_BUFFER:
case MODE_QUERY:
break;
default:
value = MODE_INDETERMINATE;
break;
}
}
return value;
}
/**
* Manually set CSS to animate the Determinate indicator based on the specified
* percentage value (0-100).
*/
function animateIndicator(target, value) {
if ( isDisabled || !mode() ) return;
var to = $mdUtil.supplant("translateX({0}%) scale({1},1)", [ (value-100)/2, value/100 ]);
var styles = toVendorCSS({ transform : to });
angular.element(target).css( styles );
}
}
/**
* Clamps the value to be between 0 and 100.
* @param {number} value The value to clamp.
* @returns {number}
*/
function clamp(value) {
return Math.max(0, Math.min(value || 0, 100));
}
}
ngmaterial.components.progressLinear = angular.module("material.components.progressLinear");

View File

@ -0,0 +1,98 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-radio-button.md-THEME_NAME-theme .md-off {
border-color: '{{foreground-2}}'; }
md-radio-button.md-THEME_NAME-theme .md-on {
background-color: '{{accent-color-0.87}}'; }
md-radio-button.md-THEME_NAME-theme.md-checked .md-off {
border-color: '{{accent-color-0.87}}'; }
md-radio-button.md-THEME_NAME-theme.md-checked .md-ink-ripple {
color: '{{accent-color-0.87}}'; }
md-radio-button.md-THEME_NAME-theme .md-container .md-ripple {
color: '{{accent-A700}}'; }
md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-primary .md-on, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-primary .md-on,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-primary .md-on,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary .md-on {
background-color: '{{primary-color-0.87}}'; }
md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-primary .md-checked .md-off, md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-primary.md-checked .md-off, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-primary .md-checked .md-off, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-off,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-primary .md-checked .md-off,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-primary.md-checked .md-off,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary .md-checked .md-off,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-off {
border-color: '{{primary-color-0.87}}'; }
md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-ink-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-primary .md-checked .md-ink-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-primary.md-checked .md-ink-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary .md-checked .md-ink-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-ink-ripple {
color: '{{primary-color-0.87}}'; }
md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-primary .md-container .md-ripple, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-primary .md-container .md-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-primary .md-container .md-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary .md-container .md-ripple {
color: '{{primary-600}}'; }
md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-warn .md-on, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-warn .md-on,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-warn .md-on,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn .md-on {
background-color: '{{warn-color-0.87}}'; }
md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-warn .md-checked .md-off, md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-warn.md-checked .md-off, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-warn .md-checked .md-off, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-off,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-warn .md-checked .md-off,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-warn.md-checked .md-off,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn .md-checked .md-off,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-off {
border-color: '{{warn-color-0.87}}'; }
md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-ink-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-warn .md-checked .md-ink-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-warn.md-checked .md-ink-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn .md-checked .md-ink-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-ink-ripple {
color: '{{warn-color-0.87}}'; }
md-radio-group.md-THEME_NAME-theme:not([disabled]) .md-warn .md-container .md-ripple, md-radio-group.md-THEME_NAME-theme:not([disabled]).md-warn .md-container .md-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]) .md-warn .md-container .md-ripple,
md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn .md-container .md-ripple {
color: '{{warn-600}}'; }
md-radio-group.md-THEME_NAME-theme[disabled],
md-radio-button.md-THEME_NAME-theme[disabled] {
color: '{{foreground-3}}'; }
md-radio-group.md-THEME_NAME-theme[disabled] .md-container .md-off,
md-radio-button.md-THEME_NAME-theme[disabled] .md-container .md-off {
border-color: '{{foreground-3}}'; }
md-radio-group.md-THEME_NAME-theme[disabled] .md-container .md-on,
md-radio-button.md-THEME_NAME-theme[disabled] .md-container .md-on {
border-color: '{{foreground-3}}'; }
md-radio-group.md-THEME_NAME-theme .md-checked .md-ink-ripple {
color: '{{accent-color-0.26}}'; }
md-radio-group.md-THEME_NAME-theme.md-primary .md-checked:not([disabled]) .md-ink-ripple, md-radio-group.md-THEME_NAME-theme .md-checked:not([disabled]).md-primary .md-ink-ripple {
color: '{{primary-color-0.26}}'; }
md-radio-group.md-THEME_NAME-theme .md-checked.md-primary .md-ink-ripple {
color: '{{warn-color-0.26}}'; }
md-radio-group.md-THEME_NAME-theme.md-focused:not(:empty) .md-checked .md-container:before {
background-color: '{{accent-color-0.26}}'; }
md-radio-group.md-THEME_NAME-theme.md-focused:not(:empty).md-primary .md-checked .md-container:before,
md-radio-group.md-THEME_NAME-theme.md-focused:not(:empty) .md-checked.md-primary .md-container:before {
background-color: '{{primary-color-0.26}}'; }
md-radio-group.md-THEME_NAME-theme.md-focused:not(:empty).md-warn .md-checked .md-container:before,
md-radio-group.md-THEME_NAME-theme.md-focused:not(:empty) .md-checked.md-warn .md-container:before {
background-color: '{{warn-color-0.26}}'; }

View File

@ -0,0 +1,144 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-radio-button {
box-sizing: border-box;
display: block;
margin-bottom: 16px;
white-space: nowrap;
cursor: pointer;
position: relative; }
md-radio-button[disabled] {
cursor: default; }
md-radio-button[disabled] .md-container {
cursor: default; }
md-radio-button .md-container {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
box-sizing: border-box;
display: inline-block;
width: 20px;
height: 20px;
cursor: pointer;
left: 0;
right: auto; }
[dir=rtl] md-radio-button .md-container {
left: auto; }
[dir=rtl] md-radio-button .md-container {
right: 0; }
md-radio-button .md-container .md-ripple-container {
position: absolute;
display: block;
width: auto;
height: auto;
left: -15px;
top: -15px;
right: -15px;
bottom: -15px; }
md-radio-button .md-container:before {
box-sizing: border-box;
background-color: transparent;
border-radius: 50%;
content: '';
position: absolute;
display: block;
height: auto;
left: 0;
top: 0;
right: 0;
bottom: 0;
-webkit-transition: all 0.5s;
transition: all 0.5s;
width: auto; }
md-radio-button.md-align-top-left > div.md-container {
top: 12px; }
md-radio-button .md-off {
box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
border-style: solid;
border-width: 2px;
border-radius: 50%;
-webkit-transition: border-color ease 0.28s;
transition: border-color ease 0.28s; }
md-radio-button .md-on {
box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
border-radius: 50%;
-webkit-transition: -webkit-transform ease 0.28s;
transition: -webkit-transform ease 0.28s;
transition: transform ease 0.28s;
transition: transform ease 0.28s, -webkit-transform ease 0.28s;
-webkit-transform: scale(0);
transform: scale(0); }
md-radio-button.md-checked .md-on {
-webkit-transform: scale(0.5);
transform: scale(0.5); }
md-radio-button .md-label {
box-sizing: border-box;
position: relative;
display: inline-block;
margin-left: 30px;
margin-right: 0;
vertical-align: middle;
white-space: normal;
pointer-events: none;
width: auto; }
[dir=rtl] md-radio-button .md-label {
margin-left: 0; }
[dir=rtl] md-radio-button .md-label {
margin-right: 30px; }
md-radio-group {
/** Layout adjustments for the radio group. */ }
md-radio-group.layout-column md-radio-button, md-radio-group.layout-xs-column md-radio-button, md-radio-group.layout-gt-xs-column md-radio-button, md-radio-group.layout-sm-column md-radio-button, md-radio-group.layout-gt-sm-column md-radio-button, md-radio-group.layout-md-column md-radio-button, md-radio-group.layout-gt-md-column md-radio-button, md-radio-group.layout-lg-column md-radio-button, md-radio-group.layout-gt-lg-column md-radio-button, md-radio-group.layout-xl-column md-radio-button {
margin-bottom: 16px; }
md-radio-group.layout-row md-radio-button, md-radio-group.layout-xs-row md-radio-button, md-radio-group.layout-gt-xs-row md-radio-button, md-radio-group.layout-sm-row md-radio-button, md-radio-group.layout-gt-sm-row md-radio-button, md-radio-group.layout-md-row md-radio-button, md-radio-group.layout-gt-md-row md-radio-button, md-radio-group.layout-lg-row md-radio-button, md-radio-group.layout-gt-lg-row md-radio-button, md-radio-group.layout-xl-row md-radio-button {
margin-top: 0;
margin-bottom: 0;
margin-left: 0;
margin-right: 16px; }
[dir=rtl] md-radio-group.layout-row md-radio-button, [dir=rtl] md-radio-group.layout-xs-row md-radio-button, [dir=rtl] md-radio-group.layout-gt-xs-row md-radio-button, [dir=rtl] md-radio-group.layout-sm-row md-radio-button, [dir=rtl] md-radio-group.layout-gt-sm-row md-radio-button, [dir=rtl] md-radio-group.layout-md-row md-radio-button, [dir=rtl] md-radio-group.layout-gt-md-row md-radio-button, [dir=rtl] md-radio-group.layout-lg-row md-radio-button, [dir=rtl] md-radio-group.layout-gt-lg-row md-radio-button, [dir=rtl] md-radio-group.layout-xl-row md-radio-button {
margin-left: 16px; }
[dir=rtl] md-radio-group.layout-row md-radio-button, [dir=rtl] md-radio-group.layout-xs-row md-radio-button, [dir=rtl] md-radio-group.layout-gt-xs-row md-radio-button, [dir=rtl] md-radio-group.layout-sm-row md-radio-button, [dir=rtl] md-radio-group.layout-gt-sm-row md-radio-button, [dir=rtl] md-radio-group.layout-md-row md-radio-button, [dir=rtl] md-radio-group.layout-gt-md-row md-radio-button, [dir=rtl] md-radio-group.layout-lg-row md-radio-button, [dir=rtl] md-radio-group.layout-gt-lg-row md-radio-button, [dir=rtl] md-radio-group.layout-xl-row md-radio-button {
margin-right: 0; }
md-radio-group.layout-row md-radio-button:last-of-type, md-radio-group.layout-xs-row md-radio-button:last-of-type, md-radio-group.layout-gt-xs-row md-radio-button:last-of-type, md-radio-group.layout-sm-row md-radio-button:last-of-type, md-radio-group.layout-gt-sm-row md-radio-button:last-of-type, md-radio-group.layout-md-row md-radio-button:last-of-type, md-radio-group.layout-gt-md-row md-radio-button:last-of-type, md-radio-group.layout-lg-row md-radio-button:last-of-type, md-radio-group.layout-gt-lg-row md-radio-button:last-of-type, md-radio-group.layout-xl-row md-radio-button:last-of-type {
margin-left: 0;
margin-right: 0; }
md-radio-group:focus {
outline: none; }
md-radio-group.md-focused .md-checked .md-container:before {
left: -8px;
top: -8px;
right: -8px;
bottom: -8px; }
md-radio-group[disabled] md-radio-button {
cursor: default; }
md-radio-group[disabled] md-radio-button .md-container {
cursor: default; }
.md-inline-form md-radio-group {
margin: 18px 0 19px; }
.md-inline-form md-radio-group md-radio-button {
display: inline-block;
height: 30px;
padding: 2px;
box-sizing: border-box;
margin-top: 0;
margin-bottom: 0; }
@media screen and (-ms-high-contrast: active) {
md-radio-button.md-default-theme .md-on {
background-color: #fff; } }

View File

@ -0,0 +1,362 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.radioButton');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.radioButton
* @description radioButton module!
*/
mdRadioGroupDirective['$inject'] = ["$mdUtil", "$mdConstant", "$mdTheming", "$timeout"];
mdRadioButtonDirective['$inject'] = ["$mdAria", "$mdUtil", "$mdTheming"];
angular.module('material.components.radioButton', [
'material.core'
])
.directive('mdRadioGroup', mdRadioGroupDirective)
.directive('mdRadioButton', mdRadioButtonDirective);
/**
* @ngdoc directive
* @module material.components.radioButton
* @name mdRadioGroup
*
* @restrict E
*
* @description
* The `<md-radio-group>` directive identifies a grouping
* container for the 1..n grouped radio buttons; specified using nested
* `<md-radio-button>` tags.
*
* As per the [material design spec](http://www.google.com/design/spec/style/color.html#color-ui-color-application)
* the radio button is in the accent color by default. The primary color palette may be used with
* the `md-primary` class.
*
* Note: `<md-radio-group>` and `<md-radio-button>` handle tabindex differently
* than the native `<input type='radio'>` controls. Whereas the native controls
* force the user to tab through all the radio buttons, `<md-radio-group>`
* is focusable, and by default the `<md-radio-button>`s are not.
*
* @param {string} ng-model Assignable angular expression to data-bind to.
* @param {boolean=} md-no-ink Use of attribute indicates flag to disable ink ripple effects.
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} ngChange AngularJS expression to be executed when input changes due to user
* interaction with the input element.
*
* @usage
* <hljs lang="html">
* <md-radio-group ng-model="selected">
*
* <md-radio-button
* ng-repeat="d in colorOptions"
* ng-value="d.value" aria-label="{{ d.label }}">
*
* {{ d.label }}
*
* </md-radio-button>
*
* </md-radio-group>
* </hljs>
*
*/
function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming, $timeout) {
RadioGroupController.prototype = createRadioGroupControllerProto();
return {
restrict: 'E',
controller: ['$element', RadioGroupController],
require: ['mdRadioGroup', '?ngModel'],
link: { pre: linkRadioGroup }
};
function linkRadioGroup(scope, element, attr, ctrls) {
element.addClass('_md'); // private md component indicator for styling
$mdTheming(element);
var rgCtrl = ctrls[0];
var ngModelCtrl = ctrls[1] || $mdUtil.fakeNgModel();
rgCtrl.init(ngModelCtrl);
scope.mouseActive = false;
element
.attr({
'role': 'radiogroup',
'tabIndex': element.attr('tabindex') || '0'
})
.on('keydown', keydownListener)
.on('mousedown', function(event) {
scope.mouseActive = true;
$timeout(function() {
scope.mouseActive = false;
}, 100);
})
.on('focus', function() {
if(scope.mouseActive === false) {
rgCtrl.$element.addClass('md-focused');
}
})
.on('blur', function() {
rgCtrl.$element.removeClass('md-focused');
});
/**
*
*/
function setFocus() {
if (!element.hasClass('md-focused')) { element.addClass('md-focused'); }
}
/**
*
*/
function keydownListener(ev) {
var keyCode = ev.which || ev.keyCode;
// Only listen to events that we originated ourselves
// so that we don't trigger on things like arrow keys in
// inputs.
if (keyCode != $mdConstant.KEY_CODE.ENTER &&
ev.currentTarget != ev.target) {
return;
}
switch (keyCode) {
case $mdConstant.KEY_CODE.LEFT_ARROW:
case $mdConstant.KEY_CODE.UP_ARROW:
ev.preventDefault();
rgCtrl.selectPrevious();
setFocus();
break;
case $mdConstant.KEY_CODE.RIGHT_ARROW:
case $mdConstant.KEY_CODE.DOWN_ARROW:
ev.preventDefault();
rgCtrl.selectNext();
setFocus();
break;
case $mdConstant.KEY_CODE.ENTER:
var form = angular.element($mdUtil.getClosest(element[0], 'form'));
if (form.length > 0) {
form.triggerHandler('submit');
}
break;
}
}
}
function RadioGroupController($element) {
this._radioButtonRenderFns = [];
this.$element = $element;
}
function createRadioGroupControllerProto() {
return {
init: function(ngModelCtrl) {
this._ngModelCtrl = ngModelCtrl;
this._ngModelCtrl.$render = angular.bind(this, this.render);
},
add: function(rbRender) {
this._radioButtonRenderFns.push(rbRender);
},
remove: function(rbRender) {
var index = this._radioButtonRenderFns.indexOf(rbRender);
if (index !== -1) {
this._radioButtonRenderFns.splice(index, 1);
}
},
render: function() {
this._radioButtonRenderFns.forEach(function(rbRender) {
rbRender();
});
},
setViewValue: function(value, eventType) {
this._ngModelCtrl.$setViewValue(value, eventType);
// update the other radio buttons as well
this.render();
},
getViewValue: function() {
return this._ngModelCtrl.$viewValue;
},
selectNext: function() {
return changeSelectedButton(this.$element, 1);
},
selectPrevious: function() {
return changeSelectedButton(this.$element, -1);
},
setActiveDescendant: function (radioId) {
this.$element.attr('aria-activedescendant', radioId);
},
isDisabled: function() {
return this.$element[0].hasAttribute('disabled');
}
};
}
/**
* Change the radio group's selected button by a given increment.
* If no button is selected, select the first button.
*/
function changeSelectedButton(parent, increment) {
// Coerce all child radio buttons into an array, then wrap then in an iterator
var buttons = $mdUtil.iterator(parent[0].querySelectorAll('md-radio-button'), true);
if (buttons.count()) {
var validate = function (button) {
// If disabled, then NOT valid
return !angular.element(button).attr("disabled");
};
var selected = parent[0].querySelector('md-radio-button.md-checked');
var target = buttons[increment < 0 ? 'previous' : 'next'](selected, validate) || buttons.first();
// Activate radioButton's click listener (triggerHandler won't create a real click event)
angular.element(target).triggerHandler('click');
}
}
}
/**
* @ngdoc directive
* @module material.components.radioButton
* @name mdRadioButton
*
* @restrict E
*
* @description
* The `<md-radio-button>`directive is the child directive required to be used within `<md-radio-group>` elements.
*
* While similar to the `<input type="radio" ng-model="" value="">` directive,
* the `<md-radio-button>` directive provides ink effects, ARIA support, and
* supports use within named radio groups.
*
* @param {string} ngValue AngularJS expression which sets the value to which the expression should
* be set when selected.
* @param {string} value The value to which the expression should be set when selected.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} aria-label Adds label to radio button for accessibility.
* Defaults to radio button's text. If no text content is available, a warning will be logged.
*
* @usage
* <hljs lang="html">
*
* <md-radio-button value="1" aria-label="Label 1">
* Label 1
* </md-radio-button>
*
* <md-radio-button ng-value="specialValue" aria-label="Green">
* Green
* </md-radio-button>
*
* </hljs>
*
*/
function mdRadioButtonDirective($mdAria, $mdUtil, $mdTheming) {
var CHECKED_CSS = 'md-checked';
return {
restrict: 'E',
require: '^mdRadioGroup',
transclude: true,
template: '<div class="md-container" md-ink-ripple md-ink-ripple-checkbox>' +
'<div class="md-off"></div>' +
'<div class="md-on"></div>' +
'</div>' +
'<div ng-transclude class="md-label"></div>',
link: link
};
function link(scope, element, attr, rgCtrl) {
var lastChecked;
$mdTheming(element);
configureAria(element, scope);
// ngAria overwrites the aria-checked inside a $watch for ngValue.
// We should defer the initialization until all the watches have fired.
// This can also be fixed by removing the `lastChecked` check, but that'll
// cause more DOM manipulation on each digest.
if (attr.ngValue) {
$mdUtil.nextTick(initialize, false);
} else {
initialize();
}
/**
* Initializes the component.
*/
function initialize() {
if (!rgCtrl) {
throw 'RadioButton: No RadioGroupController could be found.';
}
rgCtrl.add(render);
attr.$observe('value', render);
element
.on('click', listener)
.on('$destroy', function() {
rgCtrl.remove(render);
});
}
/**
* On click functionality.
*/
function listener(ev) {
if (element[0].hasAttribute('disabled') || rgCtrl.isDisabled()) return;
scope.$apply(function() {
rgCtrl.setViewValue(attr.value, ev && ev.type);
});
}
/**
* Add or remove the `.md-checked` class from the RadioButton (and conditionally its parent).
* Update the `aria-activedescendant` attribute.
*/
function render() {
var checked = rgCtrl.getViewValue() == attr.value;
if (checked === lastChecked) return;
if (element[0].parentNode.nodeName.toLowerCase() !== 'md-radio-group') {
// If the radioButton is inside a div, then add class so highlighting will work
element.parent().toggleClass(CHECKED_CSS, checked);
}
if (checked) {
rgCtrl.setActiveDescendant(element.attr('id'));
}
lastChecked = checked;
element
.attr('aria-checked', checked)
.toggleClass(CHECKED_CSS, checked);
}
/**
* Inject ARIA-specific attributes appropriate for each radio button
*/
function configureAria(element, scope){
element.attr({
id: attr.id || 'radio_' + $mdUtil.nextUid(),
role: 'radio',
'aria-checked': 'false'
});
$mdAria.expectWithText(element, 'aria-label');
}
}
}
ngmaterial.components.radioButton = angular.module("material.components.radioButton");

View File

@ -0,0 +1,121 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-input-container md-select.md-THEME_NAME-theme .md-select-value span:first-child:after {
color: '{{warn-A700}}'; }
md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select.md-THEME_NAME-theme .md-select-value span:first-child:after {
color: '{{foreground-3}}'; }
md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-THEME_NAME-theme .md-select-value {
color: '{{primary-color}}'; }
md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-THEME_NAME-theme .md-select-value.md-select-placeholder {
color: '{{primary-color}}'; }
md-input-container.md-input-invalid md-select.md-THEME_NAME-theme .md-select-value {
color: '{{warn-A700}}' !important;
border-bottom-color: '{{warn-A700}}' !important; }
md-input-container.md-input-invalid md-select.md-THEME_NAME-theme.md-no-underline .md-select-value {
border-bottom-color: transparent !important; }
md-select.md-THEME_NAME-theme[disabled] .md-select-value {
border-bottom-color: transparent;
background-image: -webkit-linear-gradient(left, "{{foreground-3}}" 0%, "{{foreground-3}}" 33%, transparent 0%);
background-image: linear-gradient(to right, "{{foreground-3}}" 0%, "{{foreground-3}}" 33%, transparent 0%);
background-image: -ms-linear-gradient(left, transparent 0%, "{{foreground-3}}" 100%); }
md-select.md-THEME_NAME-theme .md-select-value {
border-bottom-color: '{{foreground-4}}'; }
md-select.md-THEME_NAME-theme .md-select-value.md-select-placeholder {
color: '{{foreground-3}}'; }
md-select.md-THEME_NAME-theme .md-select-value span:first-child:after {
color: '{{warn-A700}}'; }
md-select.md-THEME_NAME-theme.md-no-underline .md-select-value {
border-bottom-color: transparent !important; }
md-select.md-THEME_NAME-theme.ng-invalid.ng-touched .md-select-value {
color: '{{warn-A700}}' !important;
border-bottom-color: '{{warn-A700}}' !important; }
md-select.md-THEME_NAME-theme.ng-invalid.ng-touched.md-no-underline .md-select-value {
border-bottom-color: transparent !important; }
md-select.md-THEME_NAME-theme:not([disabled]):focus .md-select-value {
border-bottom-color: '{{primary-color}}';
color: '{{ foreground-1 }}'; }
md-select.md-THEME_NAME-theme:not([disabled]):focus .md-select-value.md-select-placeholder {
color: '{{ foreground-1 }}'; }
md-select.md-THEME_NAME-theme:not([disabled]):focus.md-no-underline .md-select-value {
border-bottom-color: transparent !important; }
md-select.md-THEME_NAME-theme:not([disabled]):focus.md-accent .md-select-value {
border-bottom-color: '{{accent-color}}'; }
md-select.md-THEME_NAME-theme:not([disabled]):focus.md-warn .md-select-value {
border-bottom-color: '{{warn-color}}'; }
md-select.md-THEME_NAME-theme[disabled] .md-select-value {
color: '{{foreground-3}}'; }
md-select.md-THEME_NAME-theme[disabled] .md-select-value.md-select-placeholder {
color: '{{foreground-3}}'; }
md-select.md-THEME_NAME-theme[disabled] .md-select-icon {
color: '{{foreground-3}}'; }
md-select.md-THEME_NAME-theme .md-select-icon {
color: '{{foreground-2}}'; }
md-select-menu.md-THEME_NAME-theme md-content {
background: '{{background-A100}}'; }
md-select-menu.md-THEME_NAME-theme md-content md-optgroup {
color: '{{background-600-0.87}}'; }
md-select-menu.md-THEME_NAME-theme md-content md-option {
color: '{{background-900-0.87}}'; }
md-select-menu.md-THEME_NAME-theme md-content md-option[disabled] .md-text {
color: '{{background-400-0.87}}'; }
md-select-menu.md-THEME_NAME-theme md-content md-option:not([disabled]):focus, md-select-menu.md-THEME_NAME-theme md-content md-option:not([disabled]):hover {
background: '{{background-200}}'; }
md-select-menu.md-THEME_NAME-theme md-content md-option[selected] {
color: '{{primary-500}}'; }
md-select-menu.md-THEME_NAME-theme md-content md-option[selected]:focus {
color: '{{primary-600}}'; }
md-select-menu.md-THEME_NAME-theme md-content md-option[selected].md-accent {
color: '{{accent-color}}'; }
md-select-menu.md-THEME_NAME-theme md-content md-option[selected].md-accent:focus {
color: '{{accent-A700}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme .md-ripple {
color: '{{primary-600}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme[selected] .md-ripple {
color: '{{background-600}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme .md-ink-ripple {
color: '{{foreground-2}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme[selected] .md-ink-ripple {
color: '{{primary-color-0.87}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme:not(.md-checked) .md-icon {
border-color: '{{foreground-2}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme[selected] .md-icon {
background-color: '{{primary-color-0.87}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme[selected].md-focused .md-container:before {
background-color: '{{primary-color-0.26}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme[selected] .md-icon:after {
border-color: '{{primary-contrast-0.87}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme .md-indeterminate[disabled] .md-container {
color: '{{foreground-3}}'; }
.md-checkbox-enabled.md-THEME_NAME-theme md-option .md-text {
color: '{{background-900-0.87}}'; }

View File

@ -0,0 +1,356 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-input-container:not([md-no-float]) .md-select-placeholder span:first-child {
-webkit-transition: -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transform-origin: left top;
transform-origin: left top; }
[dir=rtl] md-input-container:not([md-no-float]) .md-select-placeholder span:first-child {
-webkit-transform-origin: right top;
transform-origin: right top; }
md-input-container.md-input-focused:not([md-no-float]) .md-select-placeholder span:first-child {
-webkit-transform: translateY(-22px) translateX(-2px) scale(0.75);
transform: translateY(-22px) translateX(-2px) scale(0.75); }
.md-select-menu-container {
position: fixed;
left: 0;
top: 0;
z-index: 90;
opacity: 0;
display: none;
-webkit-transform: translateY(-1px);
transform: translateY(-1px); }
.md-select-menu-container:not(.md-clickable) {
pointer-events: none; }
.md-select-menu-container md-progress-circular {
display: table;
margin: 24px auto !important; }
.md-select-menu-container.md-active {
display: block;
opacity: 1; }
.md-select-menu-container.md-active md-select-menu {
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transition-duration: 150ms;
transition-duration: 150ms; }
.md-select-menu-container.md-active md-select-menu > * {
opacity: 1;
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
-webkit-transition-duration: 150ms;
transition-duration: 150ms;
-webkit-transition-delay: 100ms;
transition-delay: 100ms; }
.md-select-menu-container.md-leave {
opacity: 0;
-webkit-transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
-webkit-transition-duration: 250ms;
transition-duration: 250ms; }
md-input-container > md-select {
margin: 0;
-webkit-box-ordinal-group: 3;
-webkit-order: 2;
order: 2; }
md-input-container:not(.md-input-has-value) md-select[required]:not(.md-no-asterisk) .md-select-value span:first-child:after, md-input-container:not(.md-input-has-value) md-select.ng-required:not(.md-no-asterisk) .md-select-value span:first-child:after {
content: ' *';
font-size: 13px;
vertical-align: top; }
md-input-container.md-input-invalid md-select .md-select-value {
border-bottom-style: solid;
padding-bottom: 1px; }
md-select {
display: -webkit-box;
display: -webkit-flex;
display: flex;
margin: 20px 0 26px 0; }
md-select[required].ng-invalid:not(.md-no-asterisk) .md-select-value span:first-child:after, md-select.ng-required.ng-invalid:not(.md-no-asterisk) .md-select-value span:first-child:after {
content: ' *';
font-size: 13px;
vertical-align: top; }
md-select[disabled] .md-select-value {
background-position: 0 bottom;
background-size: 4px 1px;
background-repeat: repeat-x;
margin-bottom: -1px; }
md-select:focus {
outline: none; }
md-select[disabled]:hover {
cursor: default; }
md-select:not([disabled]):hover {
cursor: pointer; }
md-select:not([disabled]).ng-invalid.ng-touched .md-select-value {
border-bottom-style: solid;
padding-bottom: 1px; }
md-select:not([disabled]):focus .md-select-value {
border-bottom-width: 2px;
border-bottom-style: solid;
padding-bottom: 0; }
md-select:not([disabled]):focus.ng-invalid.ng-touched .md-select-value {
padding-bottom: 0; }
md-input-container.md-input-has-value .md-select-value > span:not(.md-select-icon) {
-webkit-transform: translate3d(0, 1px, 0);
transform: translate3d(0, 1px, 0); }
.md-select-value {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
padding: 2px 2px 1px;
border-bottom-width: 1px;
border-bottom-style: solid;
background-color: transparent;
position: relative;
box-sizing: content-box;
min-width: 64px;
min-height: 26px;
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
flex-grow: 1; }
.md-select-value > span:not(.md-select-icon) {
max-width: 100%;
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden; }
.md-select-value > span:not(.md-select-icon) .md-text {
display: inline; }
.md-select-value .md-select-icon {
display: block;
-webkit-box-align: end;
-webkit-align-items: flex-end;
align-items: flex-end;
text-align: end;
width: 24px;
margin: 0 4px;
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
font-size: 1.2rem; }
.md-select-value .md-select-icon:after {
display: block;
content: '\25BC';
position: relative;
top: 2px;
speak: none;
font-size: 13px;
-webkit-transform: scaleY(0.5) scaleX(1);
transform: scaleY(0.5) scaleX(1); }
.md-select-value.md-select-placeholder {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
order: 1;
pointer-events: none;
-webkit-font-smoothing: antialiased;
padding-left: 2px;
z-index: 1; }
md-select-menu {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 2px 1px -1px rgba(0, 0, 0, 0.12);
max-height: 256px;
min-height: 48px;
overflow-y: hidden;
-webkit-transform-origin: left top;
transform-origin: left top;
-webkit-transform: scale(1);
transform: scale(1); }
md-select-menu.md-reverse {
-webkit-box-orient: vertical;
-webkit-box-direction: reverse;
-webkit-flex-direction: column-reverse;
flex-direction: column-reverse; }
md-select-menu:not(.md-overflow) md-content {
padding-top: 8px;
padding-bottom: 8px; }
[dir=rtl] md-select-menu {
-webkit-transform-origin: right top;
transform-origin: right top; }
md-select-menu md-content {
min-width: 136px;
min-height: 48px;
max-height: 256px;
overflow-y: auto; }
md-select-menu > * {
opacity: 0; }
md-option {
cursor: pointer;
position: relative;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
width: auto;
-webkit-transition: background 0.15s linear;
transition: background 0.15s linear;
padding: 0 16px 0 16px;
height: 48px; }
md-option[disabled] {
cursor: default; }
md-option:focus {
outline: none; }
md-option .md-text {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
width: auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis; }
md-optgroup {
display: block; }
md-optgroup label {
display: block;
font-size: 14px;
text-transform: uppercase;
padding: 16px;
font-weight: 500; }
md-optgroup md-option {
padding-left: 32px;
padding-right: 32px; }
@media screen and (-ms-high-contrast: active) {
.md-select-backdrop {
background-color: transparent; }
md-select-menu {
border: 1px solid #fff; } }
md-select-menu[multiple] md-option.md-checkbox-enabled {
padding-left: 40px;
padding-right: 16px; }
[dir=rtl] md-select-menu[multiple] md-option.md-checkbox-enabled {
padding-left: 16px; }
[dir=rtl] md-select-menu[multiple] md-option.md-checkbox-enabled {
padding-right: 40px; }
md-select-menu[multiple] md-option.md-checkbox-enabled .md-container {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
box-sizing: border-box;
display: inline-block;
width: 20px;
height: 20px;
left: 0;
right: auto; }
[dir=rtl] md-select-menu[multiple] md-option.md-checkbox-enabled .md-container {
left: auto; }
[dir=rtl] md-select-menu[multiple] md-option.md-checkbox-enabled .md-container {
right: 0; }
md-select-menu[multiple] md-option.md-checkbox-enabled .md-container:before {
box-sizing: border-box;
background-color: transparent;
border-radius: 50%;
content: '';
position: absolute;
display: block;
height: auto;
left: 0;
top: 0;
right: 0;
bottom: 0;
-webkit-transition: all 0.5s;
transition: all 0.5s;
width: auto; }
md-select-menu[multiple] md-option.md-checkbox-enabled .md-container:after {
box-sizing: border-box;
content: '';
position: absolute;
top: -10px;
right: -10px;
bottom: -10px;
left: -10px; }
md-select-menu[multiple] md-option.md-checkbox-enabled .md-container .md-ripple-container {
position: absolute;
display: block;
width: auto;
height: auto;
left: -15px;
top: -15px;
right: -15px;
bottom: -15px; }
md-select-menu[multiple] md-option.md-checkbox-enabled .md-icon {
box-sizing: border-box;
-webkit-transition: 240ms;
transition: 240ms;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
border-width: 2px;
border-style: solid;
border-radius: 2px; }
md-select-menu[multiple] md-option.md-checkbox-enabled[selected] .md-icon {
border-color: transparent; }
md-select-menu[multiple] md-option.md-checkbox-enabled[selected] .md-icon:after {
box-sizing: border-box;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
left: 4.66667px;
top: 0.22222px;
display: table;
width: 6.66667px;
height: 13.33333px;
border-width: 2px;
border-style: solid;
border-top: 0;
border-left: 0;
content: ''; }
md-select-menu[multiple] md-option.md-checkbox-enabled[disabled] {
cursor: default; }
md-select-menu[multiple] md-option.md-checkbox-enabled.md-indeterminate .md-icon:after {
box-sizing: border-box;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
display: table;
width: 12px;
height: 2px;
border-width: 2px;
border-style: solid;
border-top: 0;
border-left: 0;
content: ''; }
md-select-menu[multiple] md-option.md-checkbox-enabled .md-container {
margin-left: 10.66667px;
margin-right: auto; }
[dir=rtl] md-select-menu[multiple] md-option.md-checkbox-enabled .md-container {
margin-left: auto; }
[dir=rtl] md-select-menu[multiple] md-option.md-checkbox-enabled .md-container {
margin-right: 10.66667px; }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.showHide');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.showHide
*/
// Add additional handlers to ng-show and ng-hide that notify directives
// contained within that they should recompute their size.
// These run in addition to AngularJS's built-in ng-hide and ng-show directives.
angular.module('material.components.showHide', [
'material.core'
])
.directive('ngShow', createDirective('ngShow', true))
.directive('ngHide', createDirective('ngHide', false));
function createDirective(name, targetValue) {
return ['$mdUtil', '$window', function($mdUtil, $window) {
return {
restrict: 'A',
multiElement: true,
link: function($scope, $element, $attr) {
var unregister = $scope.$on('$md-resize-enable', function() {
unregister();
var node = $element[0];
var cachedTransitionStyles = node.nodeType === $window.Node.ELEMENT_NODE ?
$window.getComputedStyle(node) : {};
$scope.$watch($attr[name], function(value) {
if (!!value === targetValue) {
$mdUtil.nextTick(function() {
$scope.$broadcast('$md-resize');
});
var opts = {
cachedTransitionStyles: cachedTransitionStyles
};
$mdUtil.dom.animator.waitTransitionEnd($element, opts).then(function() {
$scope.$broadcast('$md-resize');
});
}
});
});
}
};
}];
}
ngmaterial.components.showHide = angular.module("material.components.showHide");

View File

@ -0,0 +1,8 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-sidenav.md-THEME_NAME-theme, md-sidenav.md-THEME_NAME-theme md-content {
background-color: '{{background-hue-1}}'; }

View File

@ -0,0 +1,110 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-sidenav {
box-sizing: border-box;
position: absolute;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
z-index: 60;
width: 320px;
max-width: 320px;
bottom: 0;
overflow: auto;
-webkit-overflow-scrolling: touch; }
md-sidenav ul {
list-style: none; }
md-sidenav.md-closed {
display: none; }
md-sidenav.md-closed-add, md-sidenav.md-closed-remove {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-transition: 0.2s ease-in all;
transition: 0.2s ease-in all; }
md-sidenav.md-closed-add.md-closed-add-active, md-sidenav.md-closed-remove.md-closed-remove-active {
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); }
md-sidenav.md-locked-open-add, md-sidenav.md-locked-open-remove {
position: static;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0); }
md-sidenav.md-locked-open, md-sidenav.md-locked-open.md-closed, md-sidenav.md-locked-open.md-closed.md-sidenav-left, md-sidenav.md-locked-open.md-closed, md-sidenav.md-locked-open.md-closed.md-sidenav-right {
position: static;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0); }
md-sidenav.md-locked-open-remove.md-closed {
position: static;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0); }
md-sidenav.md-closed.md-locked-open-add {
position: static;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-transform: translate3d(0%, 0, 0);
transform: translate3d(0%, 0, 0); }
md-sidenav.md-closed.md-locked-open-add:not(.md-locked-open-add-active) {
-webkit-transition: width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2), min-width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2), min-width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
width: 0 !important;
min-width: 0 !important; }
md-sidenav.md-closed.md-locked-open-add-active {
-webkit-transition: width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2), min-width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2), min-width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-sidenav.md-locked-open-remove-active {
-webkit-transition: width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2), min-width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition: width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2), min-width 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
width: 0 !important;
min-width: 0 !important; }
.md-sidenav-backdrop.md-locked-open {
display: none; }
.md-sidenav-left, md-sidenav {
left: 0;
top: 0;
-webkit-transform: translate3d(0%, 0, 0);
transform: translate3d(0%, 0, 0); }
.md-sidenav-left.md-closed, md-sidenav.md-closed {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0); }
.md-sidenav-right {
left: 100%;
top: 0;
-webkit-transform: translate(-100%, 0);
transform: translate(-100%, 0); }
.md-sidenav-right.md-closed {
-webkit-transform: translate(0%, 0);
transform: translate(0%, 0); }
@media (min-width: 600px) {
md-sidenav {
max-width: 400px; } }
@media (max-width: 456px) {
md-sidenav {
width: calc(100% - 56px);
min-width: calc(100% - 56px);
max-width: calc(100% - 56px); } }
@media screen and (-ms-high-contrast: active) {
.md-sidenav-left, md-sidenav {
border-right: 1px solid #fff; }
.md-sidenav-right {
border-left: 1px solid #fff; } }

View File

@ -0,0 +1,560 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.sidenav');
goog.require('ngmaterial.components.backdrop');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.sidenav
*
* @description
* A Sidenav QP component.
*/
SidenavService['$inject'] = ["$mdComponentRegistry", "$mdUtil", "$q", "$log"];
SidenavDirective['$inject'] = ["$mdMedia", "$mdUtil", "$mdConstant", "$mdTheming", "$mdInteraction", "$animate", "$compile", "$parse", "$log", "$q", "$document", "$window", "$$rAF"];
SidenavController['$inject'] = ["$scope", "$attrs", "$mdComponentRegistry", "$q", "$interpolate"];
angular
.module('material.components.sidenav', [
'material.core',
'material.components.backdrop'
])
.factory('$mdSidenav', SidenavService )
.directive('mdSidenav', SidenavDirective)
.directive('mdSidenavFocus', SidenavFocusDirective)
.controller('$mdSidenavController', SidenavController);
/**
* @ngdoc service
* @name $mdSidenav
* @module material.components.sidenav
*
* @description
* `$mdSidenav` makes it easy to interact with multiple sidenavs
* in an app. When looking up a sidenav instance, you can either look
* it up synchronously or wait for it to be initializied asynchronously.
* This is done by passing the second argument to `$mdSidenav`.
*
* @usage
* <hljs lang="js">
* // Async lookup for sidenav instance; will resolve when the instance is available
* $mdSidenav(componentId, true).then(function(instance) {
* $log.debug( componentId + "is now ready" );
* });
* // Sync lookup for sidenav instance; this will resolve immediately.
* $mdSidenav(componentId).then(function(instance) {
* $log.debug( componentId + "is now ready" );
* });
* // Async toggle the given sidenav;
* // when instance is known ready and lazy lookup is not needed.
* $mdSidenav(componentId)
* .toggle()
* .then(function(){
* $log.debug('toggled');
* });
* // Async open the given sidenav
* $mdSidenav(componentId)
* .open()
* .then(function(){
* $log.debug('opened');
* });
* // Async close the given sidenav
* $mdSidenav(componentId)
* .close()
* .then(function(){
* $log.debug('closed');
* });
* // Sync check to see if the specified sidenav is set to be open
* $mdSidenav(componentId).isOpen();
* // Sync check to whether given sidenav is locked open
* // If this is true, the sidenav will be open regardless of close()
* $mdSidenav(componentId).isLockedOpen();
* // On close callback to handle close, backdrop click or escape key pressed
* // Callback happens BEFORE the close action occurs.
* $mdSidenav(componentId).onClose(function () {
* $log.debug('closing');
* });
* </hljs>
*/
function SidenavService($mdComponentRegistry, $mdUtil, $q, $log) {
var errorMsg = "SideNav '{0}' is not available! Did you use md-component-id='{0}'?";
var service = {
find : findInstance, // sync - returns proxy API
waitFor : waitForInstance // async - returns promise
};
/**
* Service API that supports three (3) usages:
* $mdSidenav().find("left") // sync (must already exist) or returns undefined
* $mdSidenav("left").toggle(); // sync (must already exist) or returns reject promise;
* $mdSidenav("left",true).then( function(left){ // async returns instance when available
* left.toggle();
* });
*/
return function(handle, enableWait) {
if ( angular.isUndefined(handle) ) return service;
var shouldWait = enableWait === true;
var instance = service.find(handle, shouldWait);
return !instance && shouldWait ? service.waitFor(handle) :
!instance && angular.isUndefined(enableWait) ? addLegacyAPI(service, handle) : instance;
};
/**
* For failed instance/handle lookups, older-clients expect an response object with noops
* that include `rejected promise APIs`
*/
function addLegacyAPI(service, handle) {
var falseFn = function() { return false; };
var rejectFn = function() {
return $q.when($mdUtil.supplant(errorMsg, [handle || ""]));
};
return angular.extend({
isLockedOpen : falseFn,
isOpen : falseFn,
toggle : rejectFn,
open : rejectFn,
close : rejectFn,
onClose : angular.noop,
then : function(callback) {
return waitForInstance(handle)
.then(callback || angular.noop);
}
}, service);
}
/**
* Synchronously lookup the controller instance for the specified sidNav instance which has been
* registered with the markup `md-component-id`
*/
function findInstance(handle, shouldWait) {
var instance = $mdComponentRegistry.get(handle);
if (!instance && !shouldWait) {
// Report missing instance
$log.error( $mdUtil.supplant(errorMsg, [handle || ""]) );
// The component has not registered itself... most like NOT yet created
// return null to indicate that the Sidenav is not in the DOM
return undefined;
}
return instance;
}
/**
* Asynchronously wait for the component instantiation,
* Deferred lookup of component instance using $component registry
*/
function waitForInstance(handle) {
return $mdComponentRegistry.when(handle).catch($log.error);
}
}
/**
* @ngdoc directive
* @name mdSidenavFocus
* @module material.components.sidenav
*
* @restrict A
*
* @description
* `mdSidenavFocus` provides a way to specify the focused element when a sidenav opens.
* This is completely optional, as the sidenav itself is focused by default.
*
* @usage
* <hljs lang="html">
* <md-sidenav>
* <form>
* <md-input-container>
* <label for="testInput">Label</label>
* <input id="testInput" type="text" md-sidenav-focus>
* </md-input-container>
* </form>
* </md-sidenav>
* </hljs>
**/
function SidenavFocusDirective() {
return {
restrict: 'A',
require: '^mdSidenav',
link: function(scope, element, attr, sidenavCtrl) {
// @see $mdUtil.findFocusTarget(...)
}
};
}
/**
* @ngdoc directive
* @name mdSidenav
* @module material.components.sidenav
* @restrict E
*
* @description
*
* A Sidenav component that can be opened and closed programatically.
*
* By default, upon opening it will slide out on top of the main content area.
*
* For keyboard and screen reader accessibility, focus is sent to the sidenav wrapper by default.
* It can be overridden with the `md-autofocus` directive on the child element you want focused.
*
* @usage
* <hljs lang="html">
* <div layout="row" ng-controller="MyController">
* <md-sidenav md-component-id="left" class="md-sidenav-left">
* Left Nav!
* </md-sidenav>
*
* <md-content>
* Center Content
* <md-button ng-click="openLeftMenu()">
* Open Left Menu
* </md-button>
* </md-content>
*
* <md-sidenav md-component-id="right"
* md-is-locked-open="$mdMedia('min-width: 333px')"
* class="md-sidenav-right">
* <form>
* <md-input-container>
* <label for="testInput">Test input</label>
* <input id="testInput" type="text"
* ng-model="data" md-autofocus>
* </md-input-container>
* </form>
* </md-sidenav>
* </div>
* </hljs>
*
* <hljs lang="js">
* var app = angular.module('myApp', ['ngMaterial']);
* app.controller('MyController', function($scope, $mdSidenav) {
* $scope.openLeftMenu = function() {
* $mdSidenav('left').toggle();
* };
* });
* </hljs>
*
* @param {expression=} md-is-open A model bound to whether the sidenav is opened.
* @param {boolean=} md-disable-backdrop When present in the markup, the sidenav will not show a backdrop.
* @param {string=} md-component-id componentId to use with $mdSidenav service.
* @param {expression=} md-is-locked-open When this expression evaluates to true,
* the sidenav 'locks open': it falls into the content's flow instead
* of appearing over it. This overrides the `md-is-open` attribute.
* @param {string=} md-disable-scroll-target Selector, pointing to an element, whose scrolling will
* be disabled when the sidenav is opened. By default this is the sidenav's direct parent.
*
* The $mdMedia() service is exposed to the is-locked-open attribute, which
* can be given a media query or one of the `sm`, `gt-sm`, `md`, `gt-md`, `lg` or `gt-lg` presets.
* Examples:
*
* - `<md-sidenav md-is-locked-open="shouldLockOpen"></md-sidenav>`
* - `<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, $mdInteraction, $animate,
$compile, $parse, $log, $q, $document, $window, $$rAF) {
return {
restrict: 'E',
scope: {
isOpen: '=?mdIsOpen'
},
controller: '$mdSidenavController',
compile: function(element) {
element.addClass('md-closed').attr('tabIndex', '-1');
return postLink;
}
};
/**
* Directive Post Link function...
*/
function postLink(scope, element, attr, sidenavCtrl) {
var lastParentOverFlow;
var backdrop;
var disableScrollTarget = null;
var triggeringInteractionType;
var triggeringElement = null;
var previousContainerStyles;
var promise = $q.when(true);
var isLockedOpenParsed = $parse(attr.mdIsLockedOpen);
var ngWindow = angular.element($window);
var isLocked = function() {
return isLockedOpenParsed(scope.$parent, {
$media: function(arg) {
$log.warn("$media is deprecated for is-locked-open. Use $mdMedia instead.");
return $mdMedia(arg);
},
$mdMedia: $mdMedia
});
};
if (attr.mdDisableScrollTarget) {
disableScrollTarget = $document[0].querySelector(attr.mdDisableScrollTarget);
if (disableScrollTarget) {
disableScrollTarget = angular.element(disableScrollTarget);
} else {
$log.warn($mdUtil.supplant('mdSidenav: couldn\'t find element matching ' +
'selector "{selector}". Falling back to parent.', { selector: attr.mdDisableScrollTarget }));
}
}
if (!disableScrollTarget) {
disableScrollTarget = element.parent();
}
// Only create the backdrop if the backdrop isn't disabled.
if (!attr.hasOwnProperty('mdDisableBackdrop')) {
backdrop = $mdUtil.createBackdrop(scope, "md-sidenav-backdrop md-opaque ng-enter");
}
element.addClass('_md'); // private md component indicator for styling
$mdTheming(element);
// The backdrop should inherit the sidenavs theme,
// because the backdrop will take its parent theme by default.
if ( backdrop ) $mdTheming.inherit(backdrop, element);
element.on('$destroy', function() {
backdrop && backdrop.remove();
sidenavCtrl.destroy();
});
scope.$on('$destroy', function(){
backdrop && backdrop.remove();
});
scope.$watch(isLocked, updateIsLocked);
scope.$watch('isOpen', updateIsOpen);
// Publish special accessor for the Controller instance
sidenavCtrl.$toggleOpen = toggleOpen;
/**
* Toggle the DOM classes to indicate `locked`
* @param isLocked
*/
function updateIsLocked(isLocked, oldValue) {
scope.isLockedOpen = isLocked;
if (isLocked === oldValue) {
element.toggleClass('md-locked-open', !!isLocked);
} else {
$animate[isLocked ? 'addClass' : 'removeClass'](element, 'md-locked-open');
}
if (backdrop) {
backdrop.toggleClass('md-locked-open', !!isLocked);
}
}
/**
* Toggle the SideNav view and attach/detach listeners
* @param isOpen
*/
function updateIsOpen(isOpen) {
// Support deprecated md-sidenav-focus attribute as fallback
var focusEl = $mdUtil.findFocusTarget(element) || $mdUtil.findFocusTarget(element,'[md-sidenav-focus]') || element;
var parent = element.parent();
parent[isOpen ? 'on' : 'off']('keydown', onKeyDown);
if (backdrop) backdrop[isOpen ? 'on' : 'off']('click', close);
var restorePositioning = updateContainerPositions(parent, isOpen);
if ( isOpen ) {
// Capture upon opening..
triggeringElement = $document[0].activeElement;
triggeringInteractionType = $mdInteraction.getLastInteractionType();
}
disableParentScroll(isOpen);
return promise = $q.all([
isOpen && backdrop ? $animate.enter(backdrop, parent) : backdrop ?
$animate.leave(backdrop) : $q.when(true),
$animate[isOpen ? 'removeClass' : 'addClass'](element, 'md-closed')
]).then(function() {
// Perform focus when animations are ALL done...
if (scope.isOpen) {
$$rAF(function() {
// Notifies child components that the sidenav was opened. Should wait
// a frame in order to allow for the element height to be computed.
ngWindow.triggerHandler('resize');
});
focusEl && focusEl.focus();
}
// Restores the positioning on the sidenav and backdrop.
restorePositioning && restorePositioning();
});
}
function updateContainerPositions(parent, willOpen) {
var drawerEl = element[0];
var scrollTop = parent[0].scrollTop;
if (willOpen && scrollTop) {
previousContainerStyles = {
top: drawerEl.style.top,
bottom: drawerEl.style.bottom,
height: drawerEl.style.height
};
// When the parent is scrolled down, then we want to be able to show the sidenav at the current scroll
// position. We're moving the sidenav down to the correct scroll position and apply the height of the
// parent, to increase the performance. Using 100% as height, will impact the performance heavily.
var positionStyle = {
top: scrollTop + 'px',
bottom: 'auto',
height: parent[0].clientHeight + 'px'
};
// Apply the new position styles to the sidenav and backdrop.
element.css(positionStyle);
backdrop.css(positionStyle);
}
// When the sidenav is closing and we have previous defined container styles,
// then we return a restore function, which resets the sidenav and backdrop.
if (!willOpen && previousContainerStyles) {
return function() {
drawerEl.style.top = previousContainerStyles.top;
drawerEl.style.bottom = previousContainerStyles.bottom;
drawerEl.style.height = previousContainerStyles.height;
backdrop[0].style.top = null;
backdrop[0].style.bottom = null;
backdrop[0].style.height = null;
previousContainerStyles = null;
};
}
}
/**
* Prevent parent scrolling (when the SideNav is open)
*/
function disableParentScroll(disabled) {
if ( disabled && !lastParentOverFlow ) {
lastParentOverFlow = disableScrollTarget.css('overflow');
disableScrollTarget.css('overflow', 'hidden');
} else if (angular.isDefined(lastParentOverFlow)) {
disableScrollTarget.css('overflow', lastParentOverFlow);
lastParentOverFlow = undefined;
}
}
/**
* Toggle the sideNav view and publish a promise to be resolved when
* the view animation finishes.
*
* @param isOpen
* @returns {*}
*/
function toggleOpen( isOpen ) {
if (scope.isOpen == isOpen ) {
return $q.when(true);
} else {
if (scope.isOpen && sidenavCtrl.onCloseCb) sidenavCtrl.onCloseCb();
return $q(function(resolve){
// Toggle value to force an async `updateIsOpen()` to run
scope.isOpen = isOpen;
$mdUtil.nextTick(function() {
// When the current `updateIsOpen()` animation finishes
promise.then(function(result) {
if ( !scope.isOpen && triggeringElement && triggeringInteractionType === 'keyboard') {
// reset focus to originating element (if available) upon close
triggeringElement.focus();
triggeringElement = null;
}
resolve(result);
});
});
});
}
}
/**
* Auto-close sideNav when the `escape` key is pressed.
* @param evt
*/
function onKeyDown(ev) {
var isEscape = (ev.keyCode === $mdConstant.KEY_CODE.ESCAPE);
return isEscape ? close(ev) : $q.when(true);
}
/**
* With backdrop `clicks` or `escape` key-press, immediately
* apply the CSS close transition... Then notify the controller
* to close() and perform its own actions.
*/
function close(ev) {
ev.preventDefault();
return sidenavCtrl.close();
}
}
}
/*
* @private
* @ngdoc controller
* @name SidenavController
* @module material.components.sidenav
*/
function SidenavController($scope, $attrs, $mdComponentRegistry, $q, $interpolate) {
var self = this;
// Use Default internal method until overridden by directive postLink
// Synchronous getters
self.isOpen = function() { return !!$scope.isOpen; };
self.isLockedOpen = function() { return !!$scope.isLockedOpen; };
// Synchronous setters
self.onClose = function (callback) {
self.onCloseCb = callback;
return self;
};
// Async actions
self.open = function() { return self.$toggleOpen( true ); };
self.close = function() { return self.$toggleOpen( false ); };
self.toggle = function() { return self.$toggleOpen( !$scope.isOpen ); };
self.$toggleOpen = function(value) { return $q.when($scope.isOpen = value); };
// Evaluate the component id.
var rawId = $attrs.mdComponentId;
var hasDataBinding = rawId && rawId.indexOf($interpolate.startSymbol()) > -1;
var componentId = hasDataBinding ? $interpolate(rawId)($scope.$parent) : rawId;
// Register the component.
self.destroy = $mdComponentRegistry.register(self, componentId);
// Watch and update the component, if the id has changed.
if (hasDataBinding) {
$attrs.$observe('mdComponentId', function(id) {
if (id && id !== self.$$mdHandle) {
self.destroy(); // `destroy` only deregisters the old component id so we can add the new one.
self.destroy = $mdComponentRegistry.register(self, id);
}
});
}
}
ngmaterial.components.sidenav = angular.module("material.components.sidenav");

View File

@ -0,0 +1,125 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
md-slider.md-THEME_NAME-theme .md-track {
background-color: '{{foreground-3}}'; }
md-slider.md-THEME_NAME-theme .md-track-ticks {
color: '{{background-contrast}}'; }
md-slider.md-THEME_NAME-theme .md-focus-ring {
background-color: '{{accent-A200-0.2}}'; }
md-slider.md-THEME_NAME-theme .md-disabled-thumb {
border-color: '{{background-color}}';
background-color: '{{background-color}}'; }
md-slider.md-THEME_NAME-theme.md-min .md-thumb:after {
background-color: '{{background-color}}';
border-color: '{{foreground-3}}'; }
md-slider.md-THEME_NAME-theme.md-min .md-focus-ring {
background-color: '{{foreground-3-0.38}}'; }
md-slider.md-THEME_NAME-theme.md-min[md-discrete] .md-thumb:after {
background-color: '{{background-contrast}}';
border-color: transparent; }
md-slider.md-THEME_NAME-theme.md-min[md-discrete] .md-sign {
background-color: '{{background-400}}'; }
md-slider.md-THEME_NAME-theme.md-min[md-discrete] .md-sign:after {
border-top-color: '{{background-400}}'; }
md-slider.md-THEME_NAME-theme.md-min[md-discrete][md-vertical] .md-sign:after {
border-top-color: transparent;
border-left-color: '{{background-400}}'; }
md-slider.md-THEME_NAME-theme .md-track.md-track-fill {
background-color: '{{accent-color}}'; }
md-slider.md-THEME_NAME-theme .md-thumb:after {
border-color: '{{accent-color}}';
background-color: '{{accent-color}}'; }
md-slider.md-THEME_NAME-theme .md-sign {
background-color: '{{accent-color}}'; }
md-slider.md-THEME_NAME-theme .md-sign:after {
border-top-color: '{{accent-color}}'; }
md-slider.md-THEME_NAME-theme[md-vertical] .md-sign:after {
border-top-color: transparent;
border-left-color: '{{accent-color}}'; }
md-slider.md-THEME_NAME-theme .md-thumb-text {
color: '{{accent-contrast}}'; }
md-slider.md-THEME_NAME-theme.md-warn .md-focus-ring {
background-color: '{{warn-200-0.38}}'; }
md-slider.md-THEME_NAME-theme.md-warn .md-track.md-track-fill {
background-color: '{{warn-color}}'; }
md-slider.md-THEME_NAME-theme.md-warn .md-thumb:after {
border-color: '{{warn-color}}';
background-color: '{{warn-color}}'; }
md-slider.md-THEME_NAME-theme.md-warn .md-sign {
background-color: '{{warn-color}}'; }
md-slider.md-THEME_NAME-theme.md-warn .md-sign:after {
border-top-color: '{{warn-color}}'; }
md-slider.md-THEME_NAME-theme.md-warn[md-vertical] .md-sign:after {
border-top-color: transparent;
border-left-color: '{{warn-color}}'; }
md-slider.md-THEME_NAME-theme.md-warn .md-thumb-text {
color: '{{warn-contrast}}'; }
md-slider.md-THEME_NAME-theme.md-primary .md-focus-ring {
background-color: '{{primary-200-0.38}}'; }
md-slider.md-THEME_NAME-theme.md-primary .md-track.md-track-fill {
background-color: '{{primary-color}}'; }
md-slider.md-THEME_NAME-theme.md-primary .md-thumb:after {
border-color: '{{primary-color}}';
background-color: '{{primary-color}}'; }
md-slider.md-THEME_NAME-theme.md-primary .md-sign {
background-color: '{{primary-color}}'; }
md-slider.md-THEME_NAME-theme.md-primary .md-sign:after {
border-top-color: '{{primary-color}}'; }
md-slider.md-THEME_NAME-theme.md-primary[md-vertical] .md-sign:after {
border-top-color: transparent;
border-left-color: '{{primary-color}}'; }
md-slider.md-THEME_NAME-theme.md-primary .md-thumb-text {
color: '{{primary-contrast}}'; }
md-slider.md-THEME_NAME-theme[disabled] .md-thumb:after {
border-color: transparent; }
md-slider.md-THEME_NAME-theme[disabled]:not(.md-min) .md-thumb:after, md-slider.md-THEME_NAME-theme[disabled][md-discrete] .md-thumb:after {
background-color: '{{foreground-3}}';
border-color: transparent; }
md-slider.md-THEME_NAME-theme[disabled][readonly] .md-sign {
background-color: '{{background-400}}'; }
md-slider.md-THEME_NAME-theme[disabled][readonly] .md-sign:after {
border-top-color: '{{background-400}}'; }
md-slider.md-THEME_NAME-theme[disabled][readonly][md-vertical] .md-sign:after {
border-top-color: transparent;
border-left-color: '{{background-400}}'; }
md-slider.md-THEME_NAME-theme[disabled][readonly] .md-disabled-thumb {
border-color: transparent;
background-color: transparent; }
md-slider-container[disabled] > *:first-child:not(md-slider),
md-slider-container[disabled] > *:last-child:not(md-slider) {
color: '{{foreground-3}}'; }

View File

@ -0,0 +1,439 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
@-webkit-keyframes sliderFocusThumb {
0% {
-webkit-transform: scale(0.7);
transform: scale(0.7); }
30% {
-webkit-transform: scale(1);
transform: scale(1); }
100% {
-webkit-transform: scale(0.7);
transform: scale(0.7); } }
@keyframes sliderFocusThumb {
0% {
-webkit-transform: scale(0.7);
transform: scale(0.7); }
30% {
-webkit-transform: scale(1);
transform: scale(1); }
100% {
-webkit-transform: scale(0.7);
transform: scale(0.7); } }
@-webkit-keyframes sliderDiscreteFocusThumb {
0% {
-webkit-transform: scale(0.7);
transform: scale(0.7); }
50% {
-webkit-transform: scale(0.8);
transform: scale(0.8); }
100% {
-webkit-transform: scale(0);
transform: scale(0); } }
@keyframes sliderDiscreteFocusThumb {
0% {
-webkit-transform: scale(0.7);
transform: scale(0.7); }
50% {
-webkit-transform: scale(0.8);
transform: scale(0.8); }
100% {
-webkit-transform: scale(0);
transform: scale(0); } }
@-webkit-keyframes sliderDiscreteFocusRing {
0% {
-webkit-transform: scale(0.7);
transform: scale(0.7);
opacity: 0; }
50% {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1; }
100% {
-webkit-transform: scale(0);
transform: scale(0); } }
@keyframes sliderDiscreteFocusRing {
0% {
-webkit-transform: scale(0.7);
transform: scale(0.7);
opacity: 0; }
50% {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1; }
100% {
-webkit-transform: scale(0);
transform: scale(0); } }
md-slider {
height: 48px;
min-width: 128px;
position: relative;
margin-left: 4px;
margin-right: 4px;
padding: 0;
display: block;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
/**
* Track
*/
/**
* Slider thumb
*/
/* The sign that's focused in discrete mode */
/**
* The border/background that comes in when focused in non-discrete mode
*/
/* Don't animate left/right while panning */ }
md-slider *, md-slider *:after {
box-sizing: border-box; }
md-slider .md-slider-wrapper {
outline: none;
width: 100%;
height: 100%; }
md-slider .md-slider-content {
position: relative; }
md-slider .md-track-container {
width: 100%;
position: absolute;
top: 23px;
height: 2px; }
md-slider .md-track {
position: absolute;
left: 0;
right: 0;
height: 100%; }
md-slider .md-track-fill {
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transition-property: width, height;
transition-property: width, height; }
md-slider .md-track-ticks {
position: absolute;
left: 0;
right: 0;
height: 100%; }
md-slider .md-track-ticks canvas {
width: 100%;
height: 100%; }
md-slider .md-thumb-container {
position: absolute;
left: 0;
top: 50%;
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0);
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transition-property: left, right, bottom;
transition-property: left, right, bottom; }
[dir=rtl] md-slider .md-thumb-container {
left: auto;
right: 0; }
md-slider .md-thumb {
z-index: 1;
position: absolute;
left: -10px;
top: 14px;
width: 20px;
height: 20px;
border-radius: 20px;
-webkit-transform: scale(0.7);
transform: scale(0.7);
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); }
[dir=rtl] md-slider .md-thumb {
left: auto;
right: -10px; }
md-slider .md-thumb:after {
content: '';
position: absolute;
width: 20px;
height: 20px;
border-radius: 20px;
border-width: 3px;
border-style: solid;
-webkit-transition: inherit;
transition: inherit; }
md-slider .md-sign {
/* Center the children (slider-thumb-text) */
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
position: absolute;
left: -14px;
top: -17px;
width: 28px;
height: 28px;
border-radius: 28px;
-webkit-transform: scale(0.4) translate3d(0, 67.5px, 0);
transform: scale(0.4) translate3d(0, 67.5px, 0);
-webkit-transition: all 0.3s cubic-bezier(0.35, 0, 0.25, 1);
transition: all 0.3s cubic-bezier(0.35, 0, 0.25, 1);
/* The arrow pointing down under the sign */ }
md-slider .md-sign:after {
position: absolute;
content: '';
left: 0px;
border-radius: 16px;
top: 19px;
border-left: 14px solid transparent;
border-right: 14px solid transparent;
border-top-width: 16px;
border-top-style: solid;
opacity: 0;
-webkit-transform: translate3d(0, -8px, 0);
transform: translate3d(0, -8px, 0);
-webkit-transition: all 0.2s cubic-bezier(0.35, 0, 0.25, 1);
transition: all 0.2s cubic-bezier(0.35, 0, 0.25, 1); }
[dir=rtl] md-slider .md-sign:after {
left: auto;
right: 0px; }
md-slider .md-sign .md-thumb-text {
z-index: 1;
font-size: 12px;
font-weight: bold; }
md-slider .md-focus-ring {
position: absolute;
left: -17px;
top: 7px;
width: 34px;
height: 34px;
border-radius: 34px;
-webkit-transform: scale(0.7);
transform: scale(0.7);
opacity: 0;
-webkit-transition: all 0.35s cubic-bezier(0.35, 0, 0.25, 1);
transition: all 0.35s cubic-bezier(0.35, 0, 0.25, 1); }
[dir=rtl] md-slider .md-focus-ring {
left: auto;
right: -17px; }
md-slider .md-disabled-thumb {
position: absolute;
left: -14px;
top: 10px;
width: 28px;
height: 28px;
border-radius: 28px;
-webkit-transform: scale(0.5);
transform: scale(0.5);
border-width: 4px;
border-style: solid;
display: none; }
[dir=rtl] md-slider .md-disabled-thumb {
left: auto;
right: -14px; }
md-slider.md-min .md-sign {
opacity: 0; }
md-slider:focus {
outline: none; }
md-slider.md-dragging .md-thumb-container,
md-slider.md-dragging .md-track-fill {
-webkit-transition: none;
transition: none; }
md-slider:not([md-discrete]) {
/* Hide the sign and ticks in non-discrete mode */ }
md-slider:not([md-discrete]) .md-track-ticks,
md-slider:not([md-discrete]) .md-sign {
display: none; }
md-slider:not([md-discrete]):not([disabled]) .md-slider-wrapper .md-thumb:hover {
-webkit-transform: scale(0.8);
transform: scale(0.8); }
md-slider:not([md-discrete]):not([disabled]) .md-slider-wrapper.md-focused .md-focus-ring {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1; }
md-slider:not([md-discrete]):not([disabled]) .md-slider-wrapper.md-focused .md-thumb {
-webkit-animation: sliderFocusThumb 0.7s cubic-bezier(0.35, 0, 0.25, 1);
animation: sliderFocusThumb 0.7s cubic-bezier(0.35, 0, 0.25, 1); }
md-slider:not([md-discrete]):not([disabled]).md-active .md-slider-wrapper .md-thumb {
-webkit-transform: scale(1);
transform: scale(1); }
md-slider[md-discrete]:not([disabled]) .md-slider-wrapper.md-focused .md-focus-ring {
-webkit-transform: scale(0);
transform: scale(0);
-webkit-animation: sliderDiscreteFocusRing 0.5s cubic-bezier(0.35, 0, 0.25, 1);
animation: sliderDiscreteFocusRing 0.5s cubic-bezier(0.35, 0, 0.25, 1); }
md-slider[md-discrete]:not([disabled]) .md-slider-wrapper.md-focused .md-thumb {
-webkit-animation: sliderDiscreteFocusThumb 0.5s cubic-bezier(0.35, 0, 0.25, 1);
animation: sliderDiscreteFocusThumb 0.5s cubic-bezier(0.35, 0, 0.25, 1); }
md-slider[md-discrete]:not([disabled]) .md-slider-wrapper.md-focused .md-thumb, md-slider[md-discrete]:not([disabled]).md-active .md-thumb {
-webkit-transform: scale(0);
transform: scale(0); }
md-slider[md-discrete]:not([disabled]) .md-slider-wrapper.md-focused .md-sign,
md-slider[md-discrete]:not([disabled]) .md-slider-wrapper.md-focused .md-sign:after, md-slider[md-discrete]:not([disabled]).md-active .md-sign,
md-slider[md-discrete]:not([disabled]).md-active .md-sign:after {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale(1);
transform: translate3d(0, 0, 0) scale(1); }
md-slider[md-discrete][disabled][readonly] .md-thumb {
-webkit-transform: scale(0);
transform: scale(0); }
md-slider[md-discrete][disabled][readonly] .md-sign,
md-slider[md-discrete][disabled][readonly] .md-sign:after {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale(1);
transform: translate3d(0, 0, 0) scale(1); }
md-slider[disabled] .md-track-fill {
display: none; }
md-slider[disabled] .md-track-ticks {
opacity: 0; }
md-slider[disabled]:not([readonly]) .md-sign {
opacity: 0; }
md-slider[disabled] .md-thumb {
-webkit-transform: scale(0.5);
transform: scale(0.5); }
md-slider[disabled] .md-disabled-thumb {
display: block; }
md-slider[md-vertical] {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
min-height: 128px;
min-width: 0; }
md-slider[md-vertical] .md-slider-wrapper {
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
padding-top: 12px;
padding-bottom: 12px;
width: 48px;
-webkit-align-self: center;
align-self: center;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center; }
md-slider[md-vertical] .md-track-container {
height: 100%;
width: 2px;
top: 0;
left: calc(50% - (2px / 2)); }
md-slider[md-vertical] .md-thumb-container {
top: auto;
margin-bottom: 23px;
left: calc(50% - 1px);
bottom: 0; }
md-slider[md-vertical] .md-thumb-container .md-thumb:after {
left: 1px; }
md-slider[md-vertical] .md-thumb-container .md-focus-ring {
left: -16px; }
md-slider[md-vertical] .md-track-fill {
bottom: 0; }
md-slider[md-vertical][md-discrete] .md-sign {
left: -40px;
top: 9.5px;
-webkit-transform: scale(0.4) translate3d(67.5px, 0, 0);
transform: scale(0.4) translate3d(67.5px, 0, 0);
/* The arrow pointing left next the sign */ }
md-slider[md-vertical][md-discrete] .md-sign:after {
top: 9.5px;
left: 19px;
border-top: 14px solid transparent;
border-right: 0;
border-bottom: 14px solid transparent;
border-left-width: 16px;
border-left-style: solid;
opacity: 0;
-webkit-transform: translate3d(0, -8px, 0);
transform: translate3d(0, -8px, 0);
-webkit-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out; }
md-slider[md-vertical][md-discrete] .md-sign .md-thumb-text {
z-index: 1;
font-size: 12px;
font-weight: bold; }
md-slider[md-vertical][md-discrete].md-active .md-sign:after,
md-slider[md-vertical][md-discrete] .md-focused .md-sign:after, md-slider[md-vertical][md-discrete][disabled][readonly] .md-sign:after {
top: 0; }
md-slider[md-vertical][disabled][readonly] .md-thumb {
-webkit-transform: scale(0);
transform: scale(0); }
md-slider[md-vertical][disabled][readonly] .md-sign,
md-slider[md-vertical][disabled][readonly] .md-sign:after {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale(1);
transform: translate3d(0, 0, 0) scale(1); }
md-slider[md-invert]:not([md-vertical]) .md-track-fill {
left: auto;
right: 0; }
[dir=rtl] md-slider[md-invert]:not([md-vertical]) .md-track-fill {
left: 0; }
[dir=rtl] md-slider[md-invert]:not([md-vertical]) .md-track-fill {
right: auto; }
md-slider[md-invert][md-vertical] .md-track-fill {
bottom: auto;
top: 0; }
md-slider-container {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row; }
md-slider-container > *:first-child:not(md-slider),
md-slider-container > *:last-child:not(md-slider) {
min-width: 25px;
max-width: 42px;
height: 25px;
-webkit-transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transition-property: color, max-width;
transition-property: color, max-width; }
md-slider-container > *:first-child:not(md-slider) {
margin-right: 16px; }
[dir=rtl] md-slider-container > *:first-child:not(md-slider) {
margin-right: auto;
margin-left: 16px; }
md-slider-container > *:last-child:not(md-slider) {
margin-left: 16px; }
[dir=rtl] md-slider-container > *:last-child:not(md-slider) {
margin-left: auto;
margin-right: 16px; }
md-slider-container[md-vertical] {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column; }
md-slider-container[md-vertical] > *:first-child:not(md-slider),
md-slider-container[md-vertical] > *:last-child:not(md-slider) {
margin-right: 0;
margin-left: 0;
text-align: center; }
md-slider-container md-input-container input[type="number"] {
text-align: center;
padding-left: 15px;
height: 50px;
margin-top: -25px; }
[dir=rtl] md-slider-container md-input-container input[type="number"] {
padding-left: 0;
padding-right: 15px; }
@media screen and (-ms-high-contrast: active) {
md-slider.md-default-theme .md-track {
border-bottom: 1px solid #fff; } }

View File

@ -0,0 +1,606 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.slider');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.slider
*/
SliderDirective['$inject'] = ["$$rAF", "$window", "$mdAria", "$mdUtil", "$mdConstant", "$mdTheming", "$mdGesture", "$parse", "$log", "$timeout"];
angular.module('material.components.slider', [
'material.core'
])
.directive('mdSlider', SliderDirective)
.directive('mdSliderContainer', SliderContainerDirective);
/**
* @ngdoc directive
* @name mdSliderContainer
* @module material.components.slider
* @restrict E
* @description
* The `<md-slider-container>` contains slider with two other elements.
*
*
* @usage
* <h4>Normal Mode</h4>
* <hljs lang="html">
* </hljs>
*/
function SliderContainerDirective() {
return {
controller: function () {},
compile: function (elem) {
var slider = elem.find('md-slider');
if (!slider) {
return;
}
var vertical = slider.attr('md-vertical');
if (vertical !== undefined) {
elem.attr('md-vertical', '');
}
if(!slider.attr('flex')) {
slider.attr('flex', '');
}
return function postLink(scope, element, attr, ctrl) {
element.addClass('_md'); // private md component indicator for styling
// We have to manually stop the $watch on ngDisabled because it exists
// on the parent scope, and won't be automatically destroyed when
// the component is destroyed.
function setDisable(value) {
element.children().attr('disabled', value);
element.find('input').attr('disabled', value);
}
var stopDisabledWatch = angular.noop;
if (attr.disabled) {
setDisable(true);
}
else if (attr.ngDisabled) {
stopDisabledWatch = scope.$watch(attr.ngDisabled, function (value) {
setDisable(value);
});
}
scope.$on('$destroy', function () {
stopDisabledWatch();
});
var initialMaxWidth;
ctrl.fitInputWidthToTextLength = function (length) {
var input = element[0].querySelector('md-input-container');
if (input) {
var computedStyle = getComputedStyle(input);
var minWidth = parseInt(computedStyle.minWidth);
var padding = parseInt(computedStyle.padding) * 2;
initialMaxWidth = initialMaxWidth || parseInt(computedStyle.maxWidth);
var newMaxWidth = Math.max(initialMaxWidth, minWidth + padding + (minWidth / 2 * length));
input.style.maxWidth = newMaxWidth + 'px';
}
};
};
}
};
}
/**
* @ngdoc directive
* @name mdSlider
* @module material.components.slider
* @restrict E
* @description
* The `<md-slider>` component allows the user to choose from a range of
* values.
*
* As per the [material design spec](http://www.google.com/design/spec/style/color.html#color-ui-color-application)
* the slider is in the accent color by default. The primary color palette may be used with
* the `md-primary` class.
*
* It has two modes: 'normal' mode, where the user slides between a wide range
* of values, and 'discrete' mode, where the user slides between only a few
* select values.
*
* To enable discrete mode, add the `md-discrete` attribute to a slider,
* and use the `step` attribute to change the distance between
* values the user is allowed to pick.
*
* @usage
* <h4>Normal Mode</h4>
* <hljs lang="html">
* <md-slider ng-model="myValue" min="5" max="500">
* </md-slider>
* </hljs>
* <h4>Discrete Mode</h4>
* <hljs lang="html">
* <md-slider md-discrete ng-model="myDiscreteValue" step="10" min="10" max="130">
* </md-slider>
* </hljs>
* <h4>Invert Mode</h4>
* <hljs lang="html">
* <md-slider md-invert ng-model="myValue" step="10" min="10" max="130">
* </md-slider>
* </hljs>
*
* @param {boolean=} md-discrete Whether to enable discrete mode.
* @param {boolean=} md-invert Whether to enable invert mode.
* @param {number=} step The distance between values the user is allowed to pick. Default 1.
* @param {number=} min The minimum value the user is allowed to pick. Default 0.
* @param {number=} max The maximum value the user is allowed to pick. Default 100.
* @param {number=} round The amount of numbers after the decimal point, maximum is 6 to prevent scientific notation. Default 3.
*/
function SliderDirective($$rAF, $window, $mdAria, $mdUtil, $mdConstant, $mdTheming, $mdGesture, $parse, $log, $timeout) {
return {
scope: {},
require: ['?ngModel', '?^mdSliderContainer'],
template:
'<div class="md-slider-wrapper">' +
'<div class="md-slider-content">' +
'<div class="md-track-container">' +
'<div class="md-track"></div>' +
'<div class="md-track md-track-fill"></div>' +
'<div class="md-track-ticks"></div>' +
'</div>' +
'<div class="md-thumb-container">' +
'<div class="md-thumb"></div>' +
'<div class="md-focus-thumb"></div>' +
'<div class="md-focus-ring"></div>' +
'<div class="md-sign">' +
'<span class="md-thumb-text"></span>' +
'</div>' +
'<div class="md-disabled-thumb"></div>' +
'</div>' +
'</div>' +
'</div>',
compile: compile
};
// **********************************************************
// Private Methods
// **********************************************************
function compile (tElement, tAttrs) {
var wrapper = angular.element(tElement[0].getElementsByClassName('md-slider-wrapper'));
var tabIndex = tAttrs.tabindex || 0;
wrapper.attr('tabindex', tabIndex);
if (tAttrs.disabled || tAttrs.ngDisabled) wrapper.attr('tabindex', -1);
wrapper.attr('role', 'slider');
$mdAria.expect(tElement, 'aria-label');
return postLink;
}
function postLink(scope, element, attr, ctrls) {
$mdTheming(element);
var ngModelCtrl = ctrls[0] || {
// Mock ngModelController if it doesn't exist to give us
// the minimum functionality needed
$setViewValue: function(val) {
this.$viewValue = val;
this.$viewChangeListeners.forEach(function(cb) { cb(); });
},
$parsers: [],
$formatters: [],
$viewChangeListeners: []
};
var containerCtrl = ctrls[1];
var container = angular.element($mdUtil.getClosest(element, '_md-slider-container', true));
var isDisabled = attr.ngDisabled ? angular.bind(null, $parse(attr.ngDisabled), scope.$parent) : function () {
return element[0].hasAttribute('disabled');
};
var thumb = angular.element(element[0].querySelector('.md-thumb'));
var thumbText = angular.element(element[0].querySelector('.md-thumb-text'));
var thumbContainer = thumb.parent();
var trackContainer = angular.element(element[0].querySelector('.md-track-container'));
var activeTrack = angular.element(element[0].querySelector('.md-track-fill'));
var tickContainer = angular.element(element[0].querySelector('.md-track-ticks'));
var wrapper = angular.element(element[0].getElementsByClassName('md-slider-wrapper'));
var content = angular.element(element[0].getElementsByClassName('md-slider-content'));
var throttledRefreshDimensions = $mdUtil.throttle(refreshSliderDimensions, 5000);
// Default values, overridable by attrs
var DEFAULT_ROUND = 3;
var vertical = angular.isDefined(attr.mdVertical);
var discrete = angular.isDefined(attr.mdDiscrete);
var invert = angular.isDefined(attr.mdInvert);
angular.isDefined(attr.min) ? attr.$observe('min', updateMin) : updateMin(0);
angular.isDefined(attr.max) ? attr.$observe('max', updateMax) : updateMax(100);
angular.isDefined(attr.step)? attr.$observe('step', updateStep) : updateStep(1);
angular.isDefined(attr.round)? attr.$observe('round', updateRound) : updateRound(DEFAULT_ROUND);
// We have to manually stop the $watch on ngDisabled because it exists
// on the parent scope, and won't be automatically destroyed when
// the component is destroyed.
var stopDisabledWatch = angular.noop;
if (attr.ngDisabled) {
stopDisabledWatch = scope.$parent.$watch(attr.ngDisabled, updateAriaDisabled);
}
$mdGesture.register(wrapper, 'drag', { horizontal: !vertical });
scope.mouseActive = false;
wrapper
.on('keydown', keydownListener)
.on('mousedown', mouseDownListener)
.on('focus', focusListener)
.on('blur', blurListener)
.on('$md.pressdown', onPressDown)
.on('$md.pressup', onPressUp)
.on('$md.dragstart', onDragStart)
.on('$md.drag', onDrag)
.on('$md.dragend', onDragEnd);
// On resize, recalculate the slider's dimensions and re-render
function updateAll() {
refreshSliderDimensions();
ngModelRender();
}
setTimeout(updateAll, 0);
var debouncedUpdateAll = $$rAF.throttle(updateAll);
angular.element($window).on('resize', debouncedUpdateAll);
scope.$on('$destroy', function() {
angular.element($window).off('resize', debouncedUpdateAll);
});
ngModelCtrl.$render = ngModelRender;
ngModelCtrl.$viewChangeListeners.push(ngModelRender);
ngModelCtrl.$formatters.push(minMaxValidator);
ngModelCtrl.$formatters.push(stepValidator);
/**
* Attributes
*/
var min;
var max;
var step;
var round;
function updateMin(value) {
min = parseFloat(value);
element.attr('aria-valuemin', value);
updateAll();
}
function updateMax(value) {
max = parseFloat(value);
element.attr('aria-valuemax', value);
updateAll();
}
function updateStep(value) {
step = parseFloat(value);
}
function updateRound(value) {
// Set max round digits to 6, after 6 the input uses scientific notation
round = minMaxValidator(parseInt(value), 0, 6);
}
function updateAriaDisabled() {
element.attr('aria-disabled', !!isDisabled());
}
// Draw the ticks with canvas.
// The alternative to drawing ticks with canvas is to draw one element for each tick,
// which could quickly become a performance bottleneck.
var tickCanvas, tickCtx;
function redrawTicks() {
if (!discrete || isDisabled()) return;
if ( angular.isUndefined(step) ) return;
if ( step <= 0 ) {
var msg = 'Slider step value must be greater than zero when in discrete mode';
$log.error(msg);
throw new Error(msg);
}
var numSteps = Math.floor( (max - min) / step );
if (!tickCanvas) {
tickCanvas = angular.element('<canvas>').css('position', 'absolute');
tickContainer.append(tickCanvas);
tickCtx = tickCanvas[0].getContext('2d');
}
var dimensions = getSliderDimensions();
// If `dimensions` doesn't have height and width it might be the first attempt so we will refresh dimensions
if (dimensions && !dimensions.height && !dimensions.width) {
refreshSliderDimensions();
dimensions = sliderDimensions;
}
tickCanvas[0].width = dimensions.width;
tickCanvas[0].height = dimensions.height;
var distance;
for (var i = 0; i <= numSteps; i++) {
var trackTicksStyle = $window.getComputedStyle(tickContainer[0]);
tickCtx.fillStyle = trackTicksStyle.color || 'black';
distance = Math.floor((vertical ? dimensions.height : dimensions.width) * (i / numSteps));
tickCtx.fillRect(vertical ? 0 : distance - 1,
vertical ? distance - 1 : 0,
vertical ? dimensions.width : 2,
vertical ? 2 : dimensions.height);
}
}
function clearTicks() {
if(tickCanvas && tickCtx) {
var dimensions = getSliderDimensions();
tickCtx.clearRect(0, 0, dimensions.width, dimensions.height);
}
}
/**
* Refreshing Dimensions
*/
var sliderDimensions = {};
refreshSliderDimensions();
function refreshSliderDimensions() {
sliderDimensions = trackContainer[0].getBoundingClientRect();
}
function getSliderDimensions() {
throttledRefreshDimensions();
return sliderDimensions;
}
/**
* left/right/up/down arrow listener
*/
function keydownListener(ev) {
if (isDisabled()) return;
var changeAmount;
if (vertical ? ev.keyCode === $mdConstant.KEY_CODE.DOWN_ARROW : ev.keyCode === $mdConstant.KEY_CODE.LEFT_ARROW) {
changeAmount = -step;
} else if (vertical ? ev.keyCode === $mdConstant.KEY_CODE.UP_ARROW : ev.keyCode === $mdConstant.KEY_CODE.RIGHT_ARROW) {
changeAmount = step;
}
changeAmount = invert ? -changeAmount : changeAmount;
if (changeAmount) {
if (ev.metaKey || ev.ctrlKey || ev.altKey) {
changeAmount *= 4;
}
ev.preventDefault();
ev.stopPropagation();
scope.$evalAsync(function() {
setModelValue(ngModelCtrl.$viewValue + changeAmount);
});
}
}
function mouseDownListener() {
redrawTicks();
scope.mouseActive = true;
wrapper.removeClass('md-focused');
$timeout(function() {
scope.mouseActive = false;
}, 100);
}
function focusListener() {
if (scope.mouseActive === false) {
wrapper.addClass('md-focused');
}
}
function blurListener() {
wrapper.removeClass('md-focused');
element.removeClass('md-active');
clearTicks();
}
/**
* ngModel setters and validators
*/
function setModelValue(value) {
ngModelCtrl.$setViewValue( minMaxValidator(stepValidator(value)) );
}
function ngModelRender() {
if (isNaN(ngModelCtrl.$viewValue)) {
ngModelCtrl.$viewValue = ngModelCtrl.$modelValue;
}
ngModelCtrl.$viewValue = minMaxValidator(ngModelCtrl.$viewValue);
var percent = valueToPercent(ngModelCtrl.$viewValue);
scope.modelValue = ngModelCtrl.$viewValue;
element.attr('aria-valuenow', ngModelCtrl.$viewValue);
setSliderPercent(percent);
thumbText.text( ngModelCtrl.$viewValue );
}
function minMaxValidator(value, minValue, maxValue) {
if (angular.isNumber(value)) {
minValue = angular.isNumber(minValue) ? minValue : min;
maxValue = angular.isNumber(maxValue) ? maxValue : max;
return Math.max(minValue, Math.min(maxValue, value));
}
}
function stepValidator(value) {
if (angular.isNumber(value)) {
var formattedValue = (Math.round((value - min) / step) * step + min);
formattedValue = (Math.round(formattedValue * Math.pow(10, round)) / Math.pow(10, round));
if (containerCtrl && containerCtrl.fitInputWidthToTextLength){
$mdUtil.debounce(function () {
containerCtrl.fitInputWidthToTextLength(formattedValue.toString().length);
}, 100)();
}
return formattedValue;
}
}
/**
* @param percent 0-1
*/
function setSliderPercent(percent) {
percent = clamp(percent);
var thumbPosition = (percent * 100) + '%';
var activeTrackPercent = invert ? (1 - percent) * 100 + '%' : thumbPosition;
if (vertical) {
thumbContainer.css('bottom', thumbPosition);
}
else {
$mdUtil.bidiProperty(thumbContainer, 'left', 'right', thumbPosition);
}
activeTrack.css(vertical ? 'height' : 'width', activeTrackPercent);
element.toggleClass((invert ? 'md-max' : 'md-min'), percent === 0);
element.toggleClass((invert ? 'md-min' : 'md-max'), percent === 1);
}
/**
* Slide listeners
*/
var isDragging = false;
function onPressDown(ev) {
if (isDisabled()) return;
element.addClass('md-active');
element[0].focus();
refreshSliderDimensions();
var exactVal = percentToValue( positionToPercent( vertical ? ev.pointer.y : ev.pointer.x ));
var closestVal = minMaxValidator( stepValidator(exactVal) );
scope.$apply(function() {
setModelValue( closestVal );
setSliderPercent( valueToPercent(closestVal));
});
}
function onPressUp(ev) {
if (isDisabled()) return;
element.removeClass('md-dragging');
var exactVal = percentToValue( positionToPercent( vertical ? ev.pointer.y : ev.pointer.x ));
var closestVal = minMaxValidator( stepValidator(exactVal) );
scope.$apply(function() {
setModelValue(closestVal);
ngModelRender();
});
}
function onDragStart(ev) {
if (isDisabled()) return;
isDragging = true;
ev.stopPropagation();
element.addClass('md-dragging');
setSliderFromEvent(ev);
}
function onDrag(ev) {
if (!isDragging) return;
ev.stopPropagation();
setSliderFromEvent(ev);
}
function onDragEnd(ev) {
if (!isDragging) return;
ev.stopPropagation();
isDragging = false;
}
function setSliderFromEvent(ev) {
// While panning discrete, update only the
// visual positioning but not the model value.
if ( discrete ) adjustThumbPosition( vertical ? ev.pointer.y : ev.pointer.x );
else doSlide( vertical ? ev.pointer.y : ev.pointer.x );
}
/**
* Slide the UI by changing the model value
* @param x
*/
function doSlide( x ) {
scope.$evalAsync( function() {
setModelValue( percentToValue( positionToPercent(x) ));
});
}
/**
* Slide the UI without changing the model (while dragging/panning)
* @param x
*/
function adjustThumbPosition( x ) {
var exactVal = percentToValue( positionToPercent( x ));
var closestVal = minMaxValidator( stepValidator(exactVal) );
setSliderPercent( positionToPercent(x) );
thumbText.text( closestVal );
}
/**
* Clamps the value to be between 0 and 1.
* @param {number} value The value to clamp.
* @returns {number}
*/
function clamp(value) {
return Math.max(0, Math.min(value || 0, 1));
}
/**
* Convert position on slider to percentage value of offset from beginning...
* @param position
* @returns {number}
*/
function positionToPercent( position ) {
var offset = vertical ? sliderDimensions.top : sliderDimensions.left;
var size = vertical ? sliderDimensions.height : sliderDimensions.width;
var calc = (position - offset) / size;
if (!vertical && $mdUtil.bidi() === 'rtl') {
calc = 1 - calc;
}
return Math.max(0, Math.min(1, vertical ? 1 - calc : calc));
}
/**
* Convert percentage offset on slide to equivalent model value
* @param percent
* @returns {*}
*/
function percentToValue( percent ) {
var adjustedPercent = invert ? (1 - percent) : percent;
return (min + adjustedPercent * (max - min));
}
function valueToPercent( val ) {
var percent = (val - min) / (max - min);
return invert ? (1 - percent) : percent;
}
}
}
ngmaterial.components.slider = angular.module("material.components.slider");

View File

@ -0,0 +1,20 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
.md-sticky-clone {
z-index: 2;
top: 0;
left: 0;
right: 0;
position: absolute !important;
-webkit-transform: translate3d(-9999px, -9999px, 0);
transform: translate3d(-9999px, -9999px, 0); }
.md-sticky-clone[sticky-state="active"] {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0); }
.md-sticky-clone[sticky-state="active"]:not(.md-sticky-no-effect) .md-subheader-inner {
-webkit-animation: subheaderStickyHoverIn 0.3s ease-out both;
animation: subheaderStickyHoverIn 0.3s ease-out both; }

View File

@ -0,0 +1,364 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.sticky');
goog.require('ngmaterial.components.content');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.sticky
* @description
* Sticky effects for md
*
*/
MdSticky['$inject'] = ["$mdConstant", "$$rAF", "$mdUtil", "$compile"];
angular
.module('material.components.sticky', [
'material.core',
'material.components.content'
])
.factory('$mdSticky', MdSticky);
/**
* @ngdoc service
* @name $mdSticky
* @module material.components.sticky
*
* @description
* The `$mdSticky`service provides a mixin to make elements sticky.
*
* Whenever the current browser supports stickiness natively, the `$mdSticky` service will just
* use the native browser stickiness.
*
* By default the `$mdSticky` service compiles the cloned element, when not specified through the `elementClone`
* parameter, in the same scope as the actual element lives.
*
*
* <h3>Notes</h3>
* When using an element which is containing a compiled directive, which changed its DOM structure during compilation,
* you should compile the clone yourself using the plain template.<br/><br/>
* See the right usage below:
* <hljs lang="js">
* angular.module('myModule')
* .directive('stickySelect', function($mdSticky, $compile) {
* var SELECT_TEMPLATE =
* '<md-select ng-model="selected">' +
* '<md-option>Option 1</md-option>' +
* '</md-select>';
*
* return {
* restrict: 'E',
* replace: true,
* template: SELECT_TEMPLATE,
* link: function(scope,element) {
* $mdSticky(scope, element, $compile(SELECT_TEMPLATE)(scope));
* }
* };
* });
* </hljs>
*
* @usage
* <hljs lang="js">
* angular.module('myModule')
* .directive('stickyText', function($mdSticky, $compile) {
* return {
* restrict: 'E',
* template: '<span>Sticky Text</span>',
* link: function(scope,element) {
* $mdSticky(scope, element);
* }
* };
* });
* </hljs>
*
* @returns A `$mdSticky` function that takes three arguments:
* - `scope`
* - `element`: The element that will be 'sticky'
* - `elementClone`: A clone of the element, that will be shown
* when the user starts scrolling past the original element.
* If not provided, it will use the result of `element.clone()` and compiles it in the given scope.
*/
function MdSticky($mdConstant, $$rAF, $mdUtil, $compile) {
var browserStickySupport = $mdUtil.checkStickySupport();
/**
* Registers an element as sticky, used internally by directives to register themselves
*/
return function registerStickyElement(scope, element, stickyClone) {
var contentCtrl = element.controller('mdContent');
if (!contentCtrl) return;
if (browserStickySupport) {
element.css({
position: browserStickySupport,
top: 0,
'z-index': 2
});
} else {
var $$sticky = contentCtrl.$element.data('$$sticky');
if (!$$sticky) {
$$sticky = setupSticky(contentCtrl);
contentCtrl.$element.data('$$sticky', $$sticky);
}
// Compile our cloned element, when cloned in this service, into the given scope.
var cloneElement = stickyClone || $compile(element.clone())(scope);
var deregister = $$sticky.add(element, cloneElement);
scope.$on('$destroy', deregister);
}
};
function setupSticky(contentCtrl) {
var contentEl = contentCtrl.$element;
// Refresh elements is very expensive, so we use the debounced
// version when possible.
var debouncedRefreshElements = $$rAF.throttle(refreshElements);
// setupAugmentedScrollEvents gives us `$scrollstart` and `$scroll`,
// more reliable than `scroll` on android.
setupAugmentedScrollEvents(contentEl);
contentEl.on('$scrollstart', debouncedRefreshElements);
contentEl.on('$scroll', onScroll);
var self;
return self = {
prev: null,
current: null, //the currently stickied item
next: null,
items: [],
add: add,
refreshElements: refreshElements
};
/***************
* Public
***************/
// Add an element and its sticky clone to this content's sticky collection
function add(element, stickyClone) {
stickyClone.addClass('md-sticky-clone');
var item = {
element: element,
clone: stickyClone
};
self.items.push(item);
$mdUtil.nextTick(function() {
contentEl.prepend(item.clone);
});
debouncedRefreshElements();
return function remove() {
self.items.forEach(function(item, index) {
if (item.element[0] === element[0]) {
self.items.splice(index, 1);
item.clone.remove();
}
});
debouncedRefreshElements();
};
}
function refreshElements() {
// Sort our collection of elements by their current position in the DOM.
// We need to do this because our elements' order of being added may not
// be the same as their order of display.
self.items.forEach(refreshPosition);
self.items = self.items.sort(function(a, b) {
return a.top < b.top ? -1 : 1;
});
// Find which item in the list should be active,
// based upon the content's current scroll position
var item;
var currentScrollTop = contentEl.prop('scrollTop');
for (var i = self.items.length - 1; i >= 0; i--) {
if (currentScrollTop > self.items[i].top) {
item = self.items[i];
break;
}
}
setCurrentItem(item);
}
/***************
* Private
***************/
// Find the `top` of an item relative to the content element,
// and also the height.
function refreshPosition(item) {
// Find the top of an item by adding to the offsetHeight until we reach the
// content element.
var current = item.element[0];
item.top = 0;
item.left = 0;
item.right = 0;
while (current && current !== contentEl[0]) {
item.top += current.offsetTop;
item.left += current.offsetLeft;
if ( current.offsetParent ){
item.right += current.offsetParent.offsetWidth - current.offsetWidth - current.offsetLeft; //Compute offsetRight
}
current = current.offsetParent;
}
item.height = item.element.prop('offsetHeight');
var defaultVal = $mdUtil.floatingScrollbars() ? '0' : undefined;
$mdUtil.bidi(item.clone, 'margin-left', item.left, defaultVal);
$mdUtil.bidi(item.clone, 'margin-right', defaultVal, item.right);
}
// As we scroll, push in and select the correct sticky element.
function onScroll() {
var scrollTop = contentEl.prop('scrollTop');
var isScrollingDown = scrollTop > (onScroll.prevScrollTop || 0);
// Store the previous scroll so we know which direction we are scrolling
onScroll.prevScrollTop = scrollTop;
//
// AT TOP (not scrolling)
//
if (scrollTop === 0) {
// If we're at the top, just clear the current item and return
setCurrentItem(null);
return;
}
//
// SCROLLING DOWN (going towards the next item)
//
if (isScrollingDown) {
// If we've scrolled down past the next item's position, sticky it and return
if (self.next && self.next.top <= scrollTop) {
setCurrentItem(self.next);
return;
}
// If the next item is close to the current one, push the current one up out of the way
if (self.current && self.next && self.next.top - scrollTop <= self.next.height) {
translate(self.current, scrollTop + (self.next.top - self.next.height - scrollTop));
return;
}
}
//
// SCROLLING UP (not at the top & not scrolling down; must be scrolling up)
//
if (!isScrollingDown) {
// If we've scrolled up past the previous item's position, sticky it and return
if (self.current && self.prev && scrollTop < self.current.top) {
setCurrentItem(self.prev);
return;
}
// If the next item is close to the current one, pull the current one down into view
if (self.next && self.current && (scrollTop >= (self.next.top - self.current.height))) {
translate(self.current, scrollTop + (self.next.top - scrollTop - self.current.height));
return;
}
}
//
// Otherwise, just move the current item to the proper place (scrolling up or down)
//
if (self.current) {
translate(self.current, scrollTop);
}
}
function setCurrentItem(item) {
if (self.current === item) return;
// Deactivate currently active item
if (self.current) {
translate(self.current, null);
setStickyState(self.current, null);
}
// Activate new item if given
if (item) {
setStickyState(item, 'active');
}
self.current = item;
var index = self.items.indexOf(item);
// If index === -1, index + 1 = 0. It works out.
self.next = self.items[index + 1];
self.prev = self.items[index - 1];
setStickyState(self.next, 'next');
setStickyState(self.prev, 'prev');
}
function setStickyState(item, state) {
if (!item || item.state === state) return;
if (item.state) {
item.clone.attr('sticky-prev-state', item.state);
item.element.attr('sticky-prev-state', item.state);
}
item.clone.attr('sticky-state', state);
item.element.attr('sticky-state', state);
item.state = state;
}
function translate(item, amount) {
if (!item) return;
if (amount === null || amount === undefined) {
if (item.translateY) {
item.translateY = null;
item.clone.css($mdConstant.CSS.TRANSFORM, '');
}
} else {
item.translateY = amount;
$mdUtil.bidi( item.clone, $mdConstant.CSS.TRANSFORM,
'translate3d(' + item.left + 'px,' + amount + 'px,0)',
'translateY(' + amount + 'px)'
);
}
}
}
// Android 4.4 don't accurately give scroll events.
// To fix this problem, we setup a fake scroll event. We say:
// > If a scroll or touchmove event has happened in the last DELAY milliseconds,
// then send a `$scroll` event every animationFrame.
// Additionally, we add $scrollstart and $scrollend events.
function setupAugmentedScrollEvents(element) {
var SCROLL_END_DELAY = 200;
var isScrolling;
var lastScrollTime;
element.on('scroll touchmove', function() {
if (!isScrolling) {
isScrolling = true;
$$rAF.throttle(loopScrollEvent);
element.triggerHandler('$scrollstart');
}
element.triggerHandler('$scroll');
lastScrollTime = +$mdUtil.now();
});
function loopScrollEvent() {
if (+$mdUtil.now() - lastScrollTime > SCROLL_END_DELAY) {
isScrolling = false;
element.triggerHandler('$scrollend');
} else {
element.triggerHandler('$scroll');
$$rAF.throttle(loopScrollEvent);
}
}
}
}
ngmaterial.components.sticky = angular.module("material.components.sticky");

View File

@ -0,0 +1,15 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
.md-subheader.md-THEME_NAME-theme {
color: '{{ foreground-2-0.23 }}';
background-color: '{{background-default}}'; }
.md-subheader.md-THEME_NAME-theme.md-primary {
color: '{{primary-color}}'; }
.md-subheader.md-THEME_NAME-theme.md-accent {
color: '{{accent-color}}'; }
.md-subheader.md-THEME_NAME-theme.md-warn {
color: '{{warn-color}}'; }

View File

@ -0,0 +1,57 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
@-webkit-keyframes subheaderStickyHoverIn {
0% {
box-shadow: 0 0 0 0 transparent; }
100% {
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); } }
@keyframes subheaderStickyHoverIn {
0% {
box-shadow: 0 0 0 0 transparent; }
100% {
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); } }
@-webkit-keyframes subheaderStickyHoverOut {
0% {
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); }
100% {
box-shadow: 0 0 0 0 transparent; } }
@keyframes subheaderStickyHoverOut {
0% {
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); }
100% {
box-shadow: 0 0 0 0 transparent; } }
.md-subheader-wrapper:not(.md-sticky-no-effect) {
-webkit-transition: 0.2s ease-out margin;
transition: 0.2s ease-out margin; }
.md-subheader-wrapper:not(.md-sticky-no-effect) .md-subheader {
margin: 0; }
.md-subheader-wrapper:not(.md-sticky-no-effect).md-sticky-clone {
z-index: 2; }
.md-subheader-wrapper:not(.md-sticky-no-effect)[sticky-state="active"] {
margin-top: -2px; }
.md-subheader-wrapper:not(.md-sticky-no-effect):not(.md-sticky-clone)[sticky-prev-state="active"] .md-subheader-inner:after {
-webkit-animation: subheaderStickyHoverOut 0.3s ease-out both;
animation: subheaderStickyHoverOut 0.3s ease-out both; }
.md-subheader {
display: block;
font-size: 14px;
font-weight: 500;
line-height: 1em;
margin: 0 0 0 0;
position: relative; }
.md-subheader .md-subheader-inner {
display: block;
padding: 16px; }
.md-subheader .md-subheader-content {
display: block;
z-index: 1;
position: relative; }

View File

@ -0,0 +1,132 @@
/*!
* AngularJS Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.5
*/
goog.provide('ngmaterial.components.subheader');
goog.require('ngmaterial.components.sticky');
goog.require('ngmaterial.core');
/**
* @ngdoc module
* @name material.components.subheader
* @description
* SubHeader module
*
* Subheaders are special list tiles that delineate distinct sections of a
* list or grid list and are typically related to the current filtering or
* sorting criteria. Subheader tiles are either displayed inline with tiles or
* can be associated with content, for example, in an adjacent column.
*
* Upon scrolling, subheaders remain pinned to the top of the screen and remain
* pinned until pushed on or off screen by the next subheader. @see [Material
* Design Specifications](https://www.google.com/design/spec/components/subheaders.html)
*
* > To improve the visual grouping of content, use the system color for your subheaders.
*
*/
MdSubheaderDirective['$inject'] = ["$mdSticky", "$compile", "$mdTheming", "$mdUtil", "$mdAria"];
angular
.module('material.components.subheader', [
'material.core',
'material.components.sticky'
])
.directive('mdSubheader', MdSubheaderDirective);
/**
* @ngdoc directive
* @name mdSubheader
* @module material.components.subheader
*
* @restrict E
*
* @description
* The `md-subheader` directive creates a sticky subheader for a section.
*
* Developers are able to disable the stickiness of the subheader by using the following markup
*
* <hljs lang="html">
* <md-subheader class="md-no-sticky">Not Sticky</md-subheader>
* </hljs>
*
* ### Notes
* - The `md-subheader` directive uses the <a ng-href="api/service/$mdSticky">$mdSticky</a> service
* to make the subheader sticky.
*
* > Whenever the current browser doesn't support stickiness natively, the subheader
* will be compiled twice to create a sticky clone of the subheader.
*
* @usage
* <hljs lang="html">
* <md-subheader>Online Friends</md-subheader>
* </hljs>
*/
function MdSubheaderDirective($mdSticky, $compile, $mdTheming, $mdUtil, $mdAria) {
return {
restrict: 'E',
replace: true,
transclude: true,
template: (
'<div class="md-subheader _md">' +
' <div class="md-subheader-inner">' +
' <div class="md-subheader-content"></div>' +
' </div>' +
'</div>'
),
link: function postLink(scope, element, attr, controllers, transclude) {
$mdTheming(element);
element.addClass('_md');
// Remove the ngRepeat attribute from the root element, because we don't want to compile
// the ngRepeat for the sticky clone again.
$mdUtil.prefixer().removeAttribute(element, 'ng-repeat');
var outerHTML = element[0].outerHTML;
function getContent(el) {
return angular.element(el[0].querySelector('.md-subheader-content'));
}
// Set the ARIA attributes on the original element since it keeps it's original place in
// the DOM, whereas the clones are in reverse order. Should be done after the outerHTML,
// in order to avoid having multiple element be marked as headers.
attr.$set('role', 'heading');
$mdAria.expect(element, 'aria-level', '2');
// Transclude the user-given contents of the subheader
// the conventional way.
transclude(scope, function(clone) {
getContent(element).append(clone);
});
// Create another clone, that uses the outer and inner contents
// of the element, that will be 'stickied' as the user scrolls.
if (!element.hasClass('md-no-sticky')) {
transclude(scope, function(clone) {
// If the user adds an ng-if or ng-repeat directly to the md-subheader element, the
// compiled clone below will only be a comment tag (since they replace their elements with
// a comment) which cannot be properly passed to the $mdSticky; so we wrap it in our own
// DIV to ensure we have something $mdSticky can use
var wrapper = $compile('<div class="md-subheader-wrapper" aria-hidden="true">' + outerHTML + '</div>')(scope);
// Delay initialization until after any `ng-if`/`ng-repeat`/etc has finished before
// attempting to create the clone
$mdUtil.nextTick(function() {
// Append our transcluded clone into the wrapper.
// We don't have to recompile the element again, because the clone is already
// compiled in it's transclusion scope. If we recompile the outerHTML of the new clone, we would lose
// our ngIf's and other previous registered bindings / properties.
getContent(wrapper).append(clone);
});
// Make the element sticky and provide the stickyClone our self, to avoid recompilation of the subheader
// element.
$mdSticky(scope, element, wrapper);
});
}
}
};
}
ngmaterial.components.subheader = angular.module("material.components.subheader");

Some files were not shown because too many files have changed in this diff Show More