Neues Initialrelease mit IonicMaterial

This commit is contained in:
Carsten Hilmer
2016-08-22 12:55:52 +02:00
parent 30a5df79aa
commit 45e482b14d
1249 changed files with 305225 additions and 68794 deletions

View File

@@ -0,0 +1,24 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-autocomplete.md-THEME_NAME-theme {
background: '{{background-50}}'; }
md-autocomplete.md-THEME_NAME-theme[disabled] {
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.md-THEME_NAME-theme {
background: '{{background-50}}'; }
.md-autocomplete-suggestions.md-THEME_NAME-theme li {
color: '{{background-900}}'; }
.md-autocomplete-suggestions.md-THEME_NAME-theme li .highlight {
color: '{{background-600}}'; }
.md-autocomplete-suggestions.md-THEME_NAME-theme li:hover, .md-autocomplete-suggestions.md-THEME_NAME-theme li.selected {
background: '{{background-200}}'; }

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-autocomplete.md-THEME_NAME-theme,md-autocomplete.md-THEME_NAME-theme[disabled]{background:0 0}md-autocomplete.md-THEME_NAME-theme button md-icon path{fill:'{{background-600}}'}.md-autocomplete-suggestions.md-THEME_NAME-theme,md-autocomplete.md-THEME_NAME-theme button:after{background:0 0}.md-autocomplete-suggestions.md-THEME_NAME-theme li{color:'{{background-900}}'}.md-autocomplete-suggestions.md-THEME_NAME-theme li .highlight{color:'{{background-600}}'}.md-autocomplete-suggestions.md-THEME_NAME-theme li.selected,.md-autocomplete-suggestions.md-THEME_NAME-theme li:hover{background:0 0}

View File

@@ -0,0 +1,220 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
@-webkit-keyframes md-autocomplete-list-out {
0% {
-webkit-animation-timing-function: linear;
animation-timing-function: linear; }
50% {
opacity: 0;
height: 40px;
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in; }
100% {
height: 0;
opacity: 0; } }
@keyframes md-autocomplete-list-out {
0% {
-webkit-animation-timing-function: linear;
animation-timing-function: linear; }
50% {
opacity: 0;
height: 40px;
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in; }
100% {
height: 0;
opacity: 0; } }
@-webkit-keyframes md-autocomplete-list-in {
0% {
opacity: 0;
height: 0;
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out; }
50% {
opacity: 0;
height: 40px; }
100% {
opacity: 1;
height: 40px; } }
@keyframes md-autocomplete-list-in {
0% {
opacity: 0;
height: 0;
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out; }
50% {
opacity: 0;
height: 40px; }
100% {
opacity: 1;
height: 40px; } }
md-autocomplete {
border-radius: 2px;
display: block;
height: 40px;
position: relative;
overflow: visible;
min-width: 190px; }
md-autocomplete[disabled] input {
cursor: not-allowed; }
md-autocomplete[md-floating-label] {
padding-bottom: 26px;
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] button {
position: absolute;
top: auto;
bottom: 0;
right: 0;
width: 30px;
height: 30px; }
md-autocomplete md-autocomplete-wrap {
display: block;
position: relative;
overflow: visible;
height: 40px; }
md-autocomplete md-autocomplete-wrap md-progress-linear[md-mode=indeterminate] {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 3px;
transition: none; }
md-autocomplete md-autocomplete-wrap md-progress-linear[md-mode=indeterminate] .md-container {
transition: none;
top: auto;
height: 3px; }
md-autocomplete md-autocomplete-wrap md-progress-linear[md-mode=indeterminate].ng-enter {
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 {
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) {
width: 100%;
box-sizing: border-box;
border: none;
box-shadow: none;
padding: 0 15px;
font-size: 14px;
line-height: 40px;
height: 40px;
outline: none;
background: transparent; }
md-autocomplete input:not(.md-input)::-ms-clear {
display: none; }
md-autocomplete 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 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;
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); }
md-autocomplete button:focus {
outline: none; }
md-autocomplete button:focus:after {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1; }
md-autocomplete 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 button md-icon path {
stroke-width: 0; }
md-autocomplete button.ng-enter {
-webkit-transform: scale(0);
transform: scale(0);
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out; }
md-autocomplete button.ng-enter.ng-enter-active {
-webkit-transform: scale(1);
transform: scale(1); }
md-autocomplete button.ng-leave {
transition: -webkit-transform 0.15s ease-out;
transition: transform 0.15s ease-out; }
md-autocomplete 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-autocomplete-suggestions {
position: absolute;
margin: 0;
list-style: none;
padding: 0;
overflow: auto;
max-height: 225.5px;
z-index: 100; }
.md-autocomplete-suggestions li {
cursor: pointer;
font-size: 14px;
overflow: hidden;
padding: 0 15px;
line-height: 48px;
height: 48px;
transition: background 0.15s linear;
margin: 0;
white-space: nowrap;
text-overflow: ellipsis; }
.md-autocomplete-suggestions li.ng-enter, .md-autocomplete-suggestions li.ng-hide-remove {
transition: none;
-webkit-animation: md-autocomplete-list-in 0.2s;
animation: md-autocomplete-list-in 0.2s; }
.md-autocomplete-suggestions li.ng-leave, .md-autocomplete-suggestions li.ng-hide-add {
transition: none;
-webkit-animation: md-autocomplete-list-out 0.2s;
animation: md-autocomplete-list-out 0.2s; }
.md-autocomplete-suggestions li:focus {
outline: none; }
@media screen and (-ms-high-contrast: active) {
md-autocomplete, .md-autocomplete-suggestions {
border: 1px solid #fff; } }

View File

@@ -0,0 +1,951 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.autocomplete
*/
/*
* @see js folder for autocomplete implementation
*/
angular.module('material.components.autocomplete', [
'material.core',
'material.components.icon'
]);
angular
.module('material.components.autocomplete')
.controller('MdAutocompleteCtrl', MdAutocompleteCtrl);
var ITEM_HEIGHT = 41,
MAX_HEIGHT = 5.5 * ITEM_HEIGHT,
MENU_PADDING = 8;
function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $timeout, $mdTheming, $window,
$animate, $rootElement, $attrs) {
//-- private variables
var ctrl = this,
itemParts = $scope.itemsExpr.split(/ in /i),
itemExpr = itemParts[1],
elements = null,
promise = null,
cache = {},
noBlur = false,
selectedItemWatchers = [],
hasFocus = false,
lastCount = 0;
//-- public variables with handlers
defineProperty('hidden', handleHiddenChange, true);
//-- public variables
ctrl.scope = $scope;
ctrl.parent = $scope.$parent;
ctrl.itemName = itemParts[0];
ctrl.matches = [];
ctrl.loading = false;
ctrl.hidden = true;
ctrl.index = null;
ctrl.messages = [];
ctrl.id = $mdUtil.nextUid();
ctrl.isDisabled = null;
ctrl.isRequired = null;
//-- public methods
ctrl.keydown = keydown;
ctrl.blur = blur;
ctrl.focus = focus;
ctrl.clear = clearValue;
ctrl.select = select;
ctrl.listEnter = onListEnter;
ctrl.listLeave = onListLeave;
ctrl.mouseUp = onMouseup;
ctrl.getCurrentDisplayValue = getCurrentDisplayValue;
ctrl.registerSelectedItemWatcher = registerSelectedItemWatcher;
ctrl.unregisterSelectedItemWatcher = unregisterSelectedItemWatcher;
return init();
//-- initialization methods
/**
* Initialize the controller, setup watchers, gather elements
*/
function init () {
$mdUtil.initOptionalProperties($scope, $attrs, { searchText: null, selectedItem: null } );
$mdTheming($element);
configureWatchers();
$timeout(function () {
gatherElements();
focusElement();
moveDropdown();
});
}
/**
* Calculates the dropdown's position and applies the new styles to the menu element
* @returns {*}
*/
function positionDropdown () {
if (!elements) return $timeout(positionDropdown, 0, false);
var hrect = elements.wrap.getBoundingClientRect(),
vrect = elements.snap.getBoundingClientRect(),
root = elements.root.getBoundingClientRect(),
top = vrect.bottom - root.top,
bot = root.bottom - vrect.top,
left = hrect.left - root.left,
width = hrect.width,
styles = {
left: left + 'px',
minWidth: width + 'px',
maxWidth: Math.max(hrect.right - root.left, root.right - hrect.left) - MENU_PADDING + 'px'
};
if (top > bot && root.height - hrect.bottom - MENU_PADDING < MAX_HEIGHT) {
styles.top = 'auto';
styles.bottom = bot + 'px';
styles.maxHeight = Math.min(MAX_HEIGHT, hrect.top - root.top - MENU_PADDING) + 'px';
} else {
styles.top = top + 'px';
styles.bottom = 'auto';
styles.maxHeight = Math.min(MAX_HEIGHT, root.bottom - hrect.bottom - MENU_PADDING) + 'px';
}
elements.$.ul.css(styles);
$timeout(correctHorizontalAlignment, 0, false);
/**
* Makes sure that the menu doesn't go off of the screen on either side.
*/
function correctHorizontalAlignment () {
var dropdown = elements.ul.getBoundingClientRect(),
styles = {};
if (dropdown.right > root.right - MENU_PADDING) {
styles.left = (hrect.right - dropdown.width) + 'px';
}
elements.$.ul.css(styles);
}
}
/**
* Moves the dropdown menu to the body tag in order to avoid z-index and overflow issues.
*/
function moveDropdown () {
if (!elements.$.root.length) return;
$mdTheming(elements.$.ul);
elements.$.ul.detach();
elements.$.root.append(elements.$.ul);
if ($animate.pin) $animate.pin(elements.$.ul, $rootElement);
}
/**
* Sends focus to the input element.
*/
function focusElement () {
if ($scope.autofocus) elements.input.focus();
}
/**
* Sets up any watchers used by autocomplete
*/
function configureWatchers () {
var wait = parseInt($scope.delay, 10) || 0;
$attrs.$observe('disabled', function (value) { ctrl.isDisabled = value; });
$attrs.$observe('required', function (value) { ctrl.isRequired = value !== null; });
$scope.$watch('searchText', wait ? $mdUtil.debounce(handleSearchText, wait) : handleSearchText);
registerSelectedItemWatcher(selectedItemChange);
$scope.$watch('selectedItem', handleSelectedItemChange);
angular.element($window).on('resize', positionDropdown);
$scope.$on('$destroy', cleanup);
}
/**
* Removes any events or leftover elements created by this controller
*/
function cleanup () {
angular.element($window).off('resize', positionDropdown);
elements.$.ul.remove();
}
/**
* Gathers all of the elements needed for this controller
*/
function gatherElements () {
elements = {
main: $element[0],
ul: $element.find('ul')[0],
input: $element.find('input')[0],
wrap: $element.find('md-autocomplete-wrap')[0],
root: document.body
};
elements.li = elements.ul.getElementsByTagName('li');
elements.snap = getSnapTarget();
elements.$ = getAngularElements(elements);
}
/**
* Finds the element that the menu will base its position on
* @returns {*}
*/
function getSnapTarget () {
for (var element = $element; element.length; element = element.parent()) {
if (angular.isDefined(element.attr('md-autocomplete-snap'))) return element[0];
}
return elements.wrap;
}
/**
* Gathers angular-wrapped versions of each element
* @param elements
* @returns {{}}
*/
function getAngularElements (elements) {
var obj = {};
for (var key in elements) {
obj[key] = angular.element(elements[key]);
}
return obj;
}
//-- event/change handlers
/**
* Handles changes to the `hidden` property.
* @param hidden
* @param oldHidden
*/
function handleHiddenChange (hidden, oldHidden) {
if (!hidden && oldHidden) positionDropdown();
if (!hidden) {
if (elements) $timeout(function () { $mdUtil.disableScrollAround(elements.ul); }, 0, false);
} else {
$mdUtil.enableScrolling();
}
}
/**
* When the user mouses over the dropdown menu, ignore blur events.
*/
function onListEnter () {
noBlur = true;
}
/**
* When the user's mouse leaves the menu, blur events may hide the menu again.
*/
function onListLeave () {
noBlur = false;
if (!hasFocus) ctrl.hidden = true;
}
/**
* When the mouse button is released, send focus back to the input field.
*/
function onMouseup () {
elements.input.focus();
}
/**
* Handles changes to the selected item.
* @param selectedItem
* @param previousSelectedItem
*/
function selectedItemChange (selectedItem, previousSelectedItem) {
if (selectedItem) {
$scope.searchText = getDisplayValue(selectedItem);
}
if ($scope.itemChange && selectedItem !== previousSelectedItem)
$scope.itemChange(getItemScope(selectedItem));
}
/**
* Calls any external watchers listening for the selected item. Used in conjunction with
* `registerSelectedItemWatcher`.
* @param selectedItem
* @param previousSelectedItem
*/
function handleSelectedItemChange(selectedItem, previousSelectedItem) {
for (var i = 0; i < selectedItemWatchers.length; ++i) {
selectedItemWatchers[i](selectedItem, previousSelectedItem);
}
}
/**
* Register a function to be called when the selected item changes.
* @param cb
*/
function registerSelectedItemWatcher(cb) {
if (selectedItemWatchers.indexOf(cb) == -1) {
selectedItemWatchers.push(cb);
}
}
/**
* Unregister a function previously registered for selected item changes.
* @param cb
*/
function unregisterSelectedItemWatcher(cb) {
var i = selectedItemWatchers.indexOf(cb);
if (i != -1) {
selectedItemWatchers.splice(i, 1);
}
}
/**
* Handles changes to the searchText property.
* @param searchText
* @param previousSearchText
*/
function handleSearchText (searchText, previousSearchText) {
ctrl.index = getDefaultIndex();
//-- do nothing on init
if (searchText === previousSearchText) return;
//-- clear selected item if search text no longer matches it
if (searchText !== getDisplayValue($scope.selectedItem)) $scope.selectedItem = null;
else return;
//-- trigger change event if available
if ($scope.textChange && searchText !== previousSearchText)
$scope.textChange(getItemScope($scope.selectedItem));
//-- cancel results if search text is not long enough
if (!isMinLengthMet()) {
ctrl.loading = false;
ctrl.matches = [];
ctrl.hidden = shouldHide();
updateMessages();
} else {
handleQuery();
}
}
/**
* Handles input blur event, determines if the dropdown should hide.
*/
function blur () {
hasFocus = false;
if (!noBlur) ctrl.hidden = true;
}
/**
* Handles input focus event, determines if the dropdown should show.
*/
function focus () {
hasFocus = true;
//-- if searchText is null, let's force it to be a string
if (!angular.isString($scope.searchText)) $scope.searchText = '';
if ($scope.minLength > 0) return;
ctrl.hidden = shouldHide();
if (!ctrl.hidden) handleQuery();
}
/**
* Handles keyboard input.
* @param event
*/
function keydown (event) {
switch (event.keyCode) {
case $mdConstant.KEY_CODE.DOWN_ARROW:
if (ctrl.loading) return;
event.preventDefault();
ctrl.index = Math.min(ctrl.index + 1, ctrl.matches.length - 1);
updateScroll();
updateMessages();
break;
case $mdConstant.KEY_CODE.UP_ARROW:
if (ctrl.loading) return;
event.preventDefault();
ctrl.index = ctrl.index < 0 ? ctrl.matches.length - 1 : Math.max(0, ctrl.index - 1);
updateScroll();
updateMessages();
break;
case $mdConstant.KEY_CODE.TAB:
case $mdConstant.KEY_CODE.ENTER:
if (ctrl.hidden || ctrl.loading || ctrl.index < 0 || ctrl.matches.length < 1) return;
event.preventDefault();
select(ctrl.index);
break;
case $mdConstant.KEY_CODE.ESCAPE:
ctrl.matches = [];
ctrl.hidden = true;
ctrl.index = getDefaultIndex();
break;
default:
}
}
//-- getters
/**
* Returns the minimum length needed to display the dropdown.
* @returns {*}
*/
function getMinLength () {
return angular.isNumber($scope.minLength) ? $scope.minLength : 1;
}
/**
* Returns the display value for an item.
* @param item
* @returns {*}
*/
function getDisplayValue (item) {
return (item && $scope.itemText) ? $scope.itemText(getItemScope(item)) : item;
}
/**
* Returns the locals object for compiling item templates.
* @param item
* @returns {{}}
*/
function getItemScope (item) {
if (!item) return;
var locals = {};
if (ctrl.itemName) locals[ctrl.itemName] = item;
return locals;
}
/**
* Returns the default index based on whether or not autoselect is enabled.
* @returns {number}
*/
function getDefaultIndex () {
return $scope.autoselect ? 0 : -1;
}
/**
* Determines if the menu should be hidden.
* @returns {boolean}
*/
function shouldHide () {
if (!isMinLengthMet()) return true;
}
/**
* Returns the display value of the current item.
* @returns {*}
*/
function getCurrentDisplayValue () {
return getDisplayValue(ctrl.matches[ctrl.index]);
}
/**
* Determines if the minimum length is met by the search text.
* @returns {*}
*/
function isMinLengthMet () {
return angular.isDefined($scope.searchText) && $scope.searchText.length >= getMinLength();
}
//-- actions
/**
* Defines a public property with a handler and a default value.
* @param key
* @param handler
* @param value
*/
function defineProperty (key, handler, value) {
Object.defineProperty(ctrl, key, {
get: function () { return value; },
set: function (newValue) {
var oldValue = value;
value = newValue;
handler(newValue, oldValue);
}
});
}
/**
* Selects the item at the given index.
* @param index
*/
function select (index) {
$scope.selectedItem = ctrl.matches[index];
ctrl.hidden = true;
ctrl.index = 0;
ctrl.matches = [];
//-- force form to update state for validation
$timeout(function () {
elements.$.input.controller('ngModel').$setViewValue(getDisplayValue($scope.selectedItem) ||
$scope.searchText);
ctrl.hidden = true;
});
}
/**
* Clears the searchText value and selected item.
*/
function clearValue () {
$scope.searchText = '';
select(-1);
// Per http://www.w3schools.com/jsref/event_oninput.asp
var eventObj = document.createEvent('CustomEvent');
eventObj.initCustomEvent('input', true, true, {value: $scope.searchText});
elements.input.dispatchEvent(eventObj);
elements.input.focus();
}
/**
* Fetches the results for the provided search text.
* @param searchText
*/
function fetchResults (searchText) {
var items = $scope.$parent.$eval(itemExpr),
term = searchText.toLowerCase();
if (angular.isArray(items)) {
handleResults(items);
} else if (items) {
ctrl.loading = true;
if (items.success) items.success(handleResults);
if (items.then) items.then(handleResults);
if (items.error) items.error(function () { ctrl.loading = false; });
}
function handleResults (matches) {
cache[term] = matches;
if (searchText !== $scope.searchText) return; //-- just cache the results if old request
ctrl.loading = false;
promise = null;
ctrl.matches = matches;
ctrl.hidden = shouldHide();
updateMessages();
positionDropdown();
}
}
/**
* Updates the ARIA messages
*/
function updateMessages () {
ctrl.messages = [ getCountMessage(), getCurrentDisplayValue() ];
}
/**
* Returns the ARIA message for how many results match the current query.
* @returns {*}
*/
function getCountMessage () {
if (lastCount === ctrl.matches.length) return '';
lastCount = ctrl.matches.length;
switch (ctrl.matches.length) {
case 0: return 'There are no matches available.';
case 1: return 'There is 1 match available.';
default: return 'There are ' + ctrl.matches.length + ' matches available.';
}
}
/**
* Makes sure that the focused element is within view.
*/
function updateScroll () {
if (!elements.li[ctrl.index]) return;
var li = elements.li[ctrl.index],
top = li.offsetTop,
bot = top + li.offsetHeight,
hgt = elements.ul.clientHeight;
if (top < elements.ul.scrollTop) {
elements.ul.scrollTop = top;
} else if (bot > elements.ul.scrollTop + hgt) {
elements.ul.scrollTop = bot - hgt;
}
}
/**
* Starts the query to gather the results for the current searchText. Attempts to return cached
* results first, then forwards the process to `fetchResults` if necessary.
*/
function handleQuery () {
var searchText = $scope.searchText,
term = searchText.toLowerCase();
//-- cancel promise if a promise is in progress
if (promise && promise.cancel) {
promise.cancel();
promise = null;
}
//-- if results are cached, pull in cached results
if (!$scope.noCache && cache[term]) {
ctrl.matches = cache[term];
updateMessages();
} else {
fetchResults(searchText);
}
if (hasFocus) ctrl.hidden = shouldHide();
}
}
MdAutocompleteCtrl.$inject = ["$scope", "$element", "$mdUtil", "$mdConstant", "$timeout", "$mdTheming", "$window", "$animate", "$rootElement", "$attrs"];
angular
.module('material.components.autocomplete')
.directive('mdAutocomplete', MdAutocomplete);
/**
* @ngdoc directive
* @name mdAutocomplete
* @module material.components.autocomplete
*
* @description
* `<md-autocomplete>` is a special input component with a drop-down of all possible matches to a custom query.
* This component allows you to provide real-time suggestions as the user types in the input area.
*
* To start, you will need to specify the required parameters and provide a template for your results.
* The content inside `md-autocomplete` will be treated as a template.
*
* In more complex cases, you may want to include other content such as a message to display when
* no matches were found. You can do this by wrapping your template in `md-item-template` and adding
* a tag for `md-not-found`. An example of this is shown below.
* ### Validation
*
* You can use `ng-messages` to include validation the same way that you would normally validate;
* however, if you want to replicate a standard input with a floating label, you will have to do the
* following:
*
* - Make sure that your template is wrapped in `md-item-template`
* - Add your `ng-messages` code inside of `md-autocomplete`
* - Add your validation properties to `md-autocomplete` (ie. `required`)
* - Add a `name` to `md-autocomplete` (to be used on the generated `input`)
*
* There is an example below of how this should look.
*
*
* @param {expression} md-items An expression in the format of `item in items` to iterate over matches for your search.
* @param {expression=} md-selected-item-change An expression to be run each time a new item is selected
* @param {expression=} md-search-text-change An expression to be run each time the search text updates
* @param {string=} md-search-text A model to bind the search query text to
* @param {object=} md-selected-item A model to bind the selected item to
* @param {string=} md-item-text An expression that will convert your object to a single string.
* @param {string=} placeholder Placeholder text that will be forwarded to the input.
* @param {boolean=} md-no-cache Disables the internal caching that happens in autocomplete
* @param {boolean=} ng-disabled Determines whether or not to disable the input field
* @param {number=} md-min-length Specifies the minimum length of text before autocomplete will make suggestions
* @param {number=} md-delay Specifies the amount of time (in milliseconds) to wait before looking for results
* @param {boolean=} md-autofocus If true, will immediately focus the input element
* @param {boolean=} md-autoselect If true, the first item will be selected by default
* @param {string=} md-menu-class This will be applied to the dropdown menu for styling
* @param {string=} md-floating-label This will add a floating label to autocomplete and wrap it in `md-input-container`
*
* @usage
* ###Basic Example
* <hljs lang="html">
* <md-autocomplete
* md-selected-item="selectedItem"
* md-search-text="searchText"
* md-items="item in getMatches(searchText)"
* md-item-text="item.display">
* <span md-highlight-text="searchText">{{item.display}}</span>
* </md-autocomplete>
* </hljs>
*
* ###Example with "not found" message
* <hljs lang="html">
* <md-autocomplete
* md-selected-item="selectedItem"
* md-search-text="searchText"
* md-items="item in getMatches(searchText)"
* md-item-text="item.display">
* <md-item-template>
* <span md-highlight-text="searchText">{{item.display}}</span>
* </md-item-template>
* <md-not-found>
* No matches found.
* </md-not-found>
* </md-autocomplete>
* </hljs>
*
* In this example, our code utilizes `md-item-template` and `md-not-found` to specify the different
* parts that make up our component.
*
* ### Example with validation
* <hljs lang="html">
* <form name="autocompleteForm">
* <md-autocomplete
* required
* input-name="autocomplete"
* md-selected-item="selectedItem"
* md-search-text="searchText"
* md-items="item in getMatches(searchText)"
* md-item-text="item.display">
* <md-item-template>
* <span md-highlight-text="searchText">{{item.display}}</span>
* </md-item-template>
* <div ng-messages="autocompleteForm.autocomplete.$error">
* <div ng-message="required">This field is required</div>
* </div>
* </md-autocomplete>
* </form>
* </hljs>
*
* In this example, our code utilizes `md-item-template` and `md-not-found` to specify the different
* parts that make up our component.
*/
function MdAutocomplete ($mdTheming, $mdUtil) {
return {
controller: 'MdAutocompleteCtrl',
controllerAs: '$mdAutocompleteCtrl',
scope: {
inputName: '@mdInputName',
inputMinlength: '@mdInputMinlength',
inputMaxlength: '@mdInputMaxlength',
searchText: '=?mdSearchText',
selectedItem: '=?mdSelectedItem',
itemsExpr: '@mdItems',
itemText: '&mdItemText',
placeholder: '@placeholder',
noCache: '=?mdNoCache',
itemChange: '&?mdSelectedItemChange',
textChange: '&?mdSearchTextChange',
minLength: '=?mdMinLength',
delay: '=?mdDelay',
autofocus: '=?mdAutofocus',
floatingLabel: '@?mdFloatingLabel',
autoselect: '=?mdAutoselect',
menuClass: '@?mdMenuClass'
},
template: function (element, attr) {
var noItemsTemplate = getNoItemsTemplate(),
itemTemplate = getItemTemplate(),
leftover = element.html();
return '\
<md-autocomplete-wrap\
layout="row"\
ng-class="{ \'md-whiteframe-z1\': !floatingLabel }"\
role="listbox">\
' + getInputElement() + '\
<md-progress-linear\
ng-if="$mdAutocompleteCtrl.loading"\
md-mode="indeterminate"></md-progress-linear>\
<ul role="presentation"\
class="md-autocomplete-suggestions md-whiteframe-z1 {{menuClass || \'\'}}"\
id="ul-{{$mdAutocompleteCtrl.id}}"\
ng-hide="$mdAutocompleteCtrl.hidden"\
ng-mouseenter="$mdAutocompleteCtrl.listEnter()"\
ng-mouseleave="$mdAutocompleteCtrl.listLeave()"\
ng-mouseup="$mdAutocompleteCtrl.mouseUp()">\
<li ng-repeat="(index, item) in $mdAutocompleteCtrl.matches"\
ng-class="{ selected: index === $mdAutocompleteCtrl.index }"\
ng-click="$mdAutocompleteCtrl.select(index)"\
md-autocomplete-list-item="$mdAutocompleteCtrl.itemName">\
' + itemTemplate + '\
</li>\
' + noItemsTemplate + '\
</ul>\
</md-autocomplete-wrap>\
<aria-status\
class="md-visually-hidden"\
role="status"\
aria-live="assertive">\
<p ng-repeat="message in $mdAutocompleteCtrl.messages" ng-if="message">{{message}}</p>\
</aria-status>';
function getItemTemplate() {
var templateTag = element.find('md-item-template').remove(),
html = templateTag.length ? templateTag.html() : element.html();
if (!templateTag.length) element.empty();
return html;
}
function getNoItemsTemplate() {
var templateTag = element.find('md-not-found').remove(),
template = templateTag.length ? templateTag.html() : '';
return template
? '<li ng-if="!$mdAutocompleteCtrl.matches.length && !$mdAutocompleteCtrl.loading\
&& !$mdAutocompleteCtrl.hidden"\
ng-hide="$mdAutocompleteCtrl.hidden"\
md-autocomplete-parent-scope>' + template + '</li>'
: '';
}
function getInputElement() {
if (attr.mdFloatingLabel) {
return '\
<md-input-container flex ng-if="floatingLabel">\
<label>{{floatingLabel}}</label>\
<input type="search"\
id="fl-input-{{$mdAutocompleteCtrl.id}}"\
name="{{inputName}}"\
autocomplete="off"\
ng-required="isRequired"\
ng-minlength="inputMinlength"\
ng-maxlength="inputMaxlength"\
ng-disabled="$mdAutocompleteCtrl.isDisabled"\
ng-model="$mdAutocompleteCtrl.scope.searchText"\
ng-keydown="$mdAutocompleteCtrl.keydown($event)"\
ng-blur="$mdAutocompleteCtrl.blur()"\
ng-focus="$mdAutocompleteCtrl.focus()"\
aria-owns="ul-{{$mdAutocompleteCtrl.id}}"\
aria-label="{{floatingLabel}}"\
aria-autocomplete="list"\
aria-haspopup="true"\
aria-activedescendant=""\
aria-expanded="{{!$mdAutocompleteCtrl.hidden}}"/>\
<div md-autocomplete-parent-scope md-autocomplete-replace>' + leftover + '</div>\
</md-input-container>';
} else {
return '\
<input flex type="search"\
id="input-{{$mdAutocompleteCtrl.id}}"\
name="{{inputName}}"\
ng-if="!floatingLabel"\
autocomplete="off"\
ng-required="isRequired"\
ng-disabled="$mdAutocompleteCtrl.isDisabled"\
ng-model="$mdAutocompleteCtrl.scope.searchText"\
ng-keydown="$mdAutocompleteCtrl.keydown($event)"\
ng-blur="$mdAutocompleteCtrl.blur()"\
ng-focus="$mdAutocompleteCtrl.focus()"\
placeholder="{{placeholder}}"\
aria-owns="ul-{{$mdAutocompleteCtrl.id}}"\
aria-label="{{placeholder}}"\
aria-autocomplete="list"\
aria-haspopup="true"\
aria-activedescendant=""\
aria-expanded="{{!$mdAutocompleteCtrl.hidden}}"/>\
<button\
type="button"\
tabindex="-1"\
ng-if="$mdAutocompleteCtrl.scope.searchText && !$mdAutocompleteCtrl.isDisabled"\
ng-click="$mdAutocompleteCtrl.clear()">\
<md-icon md-svg-icon="md-close"></md-icon>\
<span class="md-visually-hidden">Clear</span>\
</button>\
';
}
}
}
};
}
MdAutocomplete.$inject = ["$mdTheming", "$mdUtil"];
angular
.module('material.components.autocomplete')
.controller('MdHighlightCtrl', MdHighlightCtrl);
function MdHighlightCtrl ($scope, $element, $interpolate) {
this.init = init;
return init();
function init (term) {
var unsafeText = $interpolate($element.html())($scope),
text = angular.element('<div>').text(unsafeText).html(),
flags = $element.attr('md-highlight-flags') || '',
watcher = $scope.$watch(term, function (term) {
var regex = getRegExp(term, flags),
html = text.replace(regex, '<span class="highlight">$&</span>');
$element.html(html);
});
$element.on('$destroy', function () { watcher(); });
}
function sanitize (term) {
if (!term) return term;
return term.replace(/[\\\^\$\*\+\?\.\(\)\|\{\}\[\]]/g, '\\$&');
}
function getRegExp (text, flags) {
var str = '';
if (flags.indexOf('^') >= 1) str += '^';
str += text;
if (flags.indexOf('$') >= 1) str += '$';
return new RegExp(sanitize(str), flags.replace(/[\$\^]/g, ''));
}
}
MdHighlightCtrl.$inject = ["$scope", "$element", "$interpolate"];
angular
.module('material.components.autocomplete')
.directive('mdHighlightText', MdHighlight);
/**
* @ngdoc directive
* @name mdHighlightText
* @module material.components.autocomplete
*
* @description
* The `md-highlight-text` directive allows you to specify text that should be highlighted within
* an element. Highlighted text will be wrapped in `<span class="highlight"></span>` which can
* be styled through CSS. Please note that child elements may not be used with this directive.
*
* @param {string} md-highlight-text A model to be searched for
* @param {string=} md-highlight-flags A list of flags (loosely based on JavaScript RexExp flags).
* #### **Supported flags**:
* - `g`: Find all matches within the provided text
* - `i`: Ignore case when searching for matches
* - `$`: Only match if the text ends with the search term
* - `^`: Only match if the text begins with the search term
*
* @usage
* <hljs lang="html">
* <input placeholder="Enter a search term..." ng-model="searchTerm" type="text" />
* <ul>
* <li ng-repeat="result in results" md-highlight-text="searchTerm">
* {{result.text}}
* </li>
* </ul>
* </hljs>
*/
function MdHighlight () {
return {
terminal: true,
scope: false,
controller: 'MdHighlightCtrl',
link: function (scope, element, attr, ctrl) {
ctrl.init(attr.mdHighlightText);
}
};
}
angular
.module('material.components.autocomplete')
.directive('mdAutocompleteListItem', MdAutocompleteListItem);
function MdAutocompleteListItem ($compile, $mdUtil) {
return {
terminal: true,
link: postLink,
scope: false
};
function postLink (scope, element, attr) {
var ctrl = scope.$parent.$mdAutocompleteCtrl,
newScope = ctrl.parent.$new(false, ctrl.parent),
itemName = ctrl.scope.$eval(attr.mdAutocompleteListItem);
newScope[itemName] = scope.item;
$compile(element.contents())(newScope);
element.attr({
role: 'option',
id: 'item_' + $mdUtil.nextUid()
});
}
}
MdAutocompleteListItem.$inject = ["$compile", "$mdUtil"];
angular
.module('material.components.autocomplete')
.directive('mdAutocompleteParentScope', MdAutocompleteParentScope);
function MdAutocompleteParentScope ($compile, $mdUtil) {
return {
restrict: 'A',
terminal: true,
link: postLink,
scope: false
};
function postLink (scope, element, attr) {
var ctrl = scope.$parent.$mdAutocompleteCtrl;
$compile(element.contents())(ctrl.parent);
if (attr.hasOwnProperty('mdAutocompleteReplace')) {
element.after(element.contents());
element.remove();
}
}
}
MdAutocompleteParentScope.$inject = ["$compile", "$mdUtil"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/@-webkit-keyframes md-autocomplete-list-out{0%{-webkit-animation-timing-function:linear;animation-timing-function:linear}50%{opacity:0;height:40px;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{height:0;opacity:0}}@keyframes md-autocomplete-list-out{0%{-webkit-animation-timing-function:linear;animation-timing-function:linear}50%{opacity:0;height:40px;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{height:0;opacity:0}}@-webkit-keyframes md-autocomplete-list-in{0%{opacity:0;height:0;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{opacity:0;height:40px}100%{opacity:1;height:40px}}@keyframes md-autocomplete-list-in{0%{opacity:0;height:0;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{opacity:0;height:40px}100%{opacity:1;height:40px}}md-autocomplete{border-radius:2px;display:block;height:40px;position:relative;overflow:visible;min-width:190px}md-autocomplete[disabled] input{cursor:not-allowed}md-autocomplete[md-floating-label]{padding-bottom:26px;border-radius:0;background:0 0;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] button{position:absolute;top:auto;bottom:0;right:0;width:30px;height:30px}md-autocomplete md-autocomplete-wrap{display:block;position:relative;overflow:visible;height:40px}md-autocomplete md-autocomplete-wrap md-progress-linear[md-mode=indeterminate]{position:absolute;bottom:0;left:0;width:100%;height:3px;transition:none}md-autocomplete md-autocomplete-wrap md-progress-linear[md-mode=indeterminate] .md-container{transition:none;top:auto;height:3px}md-autocomplete md-autocomplete-wrap md-progress-linear[md-mode=indeterminate].ng-enter{transition:opacity .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{transition:opacity .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){width:100%;box-sizing:border-box;border:none;box-shadow:none;padding:0 15px;font-size:14px;line-height:40px;height:40px;outline:0;background:0 0}md-autocomplete input:not(.md-input)::-ms-clear{display:none}md-autocomplete 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:0 0;margin:auto 5px}md-autocomplete 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;transition:all .4s cubic-bezier(.25,.8,.25,1)}md-autocomplete button:focus{outline:0}md-autocomplete button:focus:after{-webkit-transform:scale(1);transform:scale(1);opacity:1}md-autocomplete button md-icon{position:absolute;top:50%;left:50%;-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9)}md-autocomplete button md-icon path{stroke-width:0}md-autocomplete button.ng-enter{-webkit-transform:scale(0);transform:scale(0);transition:-webkit-transform .15s ease-out;transition:transform .15s ease-out}md-autocomplete button.ng-enter.ng-enter-active{-webkit-transform:scale(1);transform:scale(1)}md-autocomplete button.ng-leave{transition:-webkit-transform .15s ease-out;transition:transform .15s ease-out}md-autocomplete 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-autocomplete-suggestions{position:absolute;margin:0;list-style:none;padding:0;overflow:auto;max-height:225.5px;z-index:100}.md-autocomplete-suggestions li{cursor:pointer;font-size:14px;overflow:hidden;padding:0 15px;line-height:48px;height:48px;transition:background .15s linear;margin:0;white-space:nowrap;text-overflow:ellipsis}.md-autocomplete-suggestions li.ng-enter,.md-autocomplete-suggestions li.ng-hide-remove{transition:none;-webkit-animation:md-autocomplete-list-in .2s;animation:md-autocomplete-list-in .2s}.md-autocomplete-suggestions li.ng-hide-add,.md-autocomplete-suggestions li.ng-leave{transition:none;-webkit-animation:md-autocomplete-list-out .2s;animation:md-autocomplete-list-out .2s}.md-autocomplete-suggestions li:focus{outline:0}@media screen and (-ms-high-contrast:active){.md-autocomplete-suggestions,md-autocomplete{border:1px solid #fff}}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
{
"name": "angular-material-autocomplete",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0",
"angular-material-icon": "0.10.0"
}
}

View File

@@ -0,0 +1,9 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-backdrop.md-opaque.md-THEME_NAME-theme {
background-color: '{{foreground-4-0.5}}'; }

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-backdrop.md-opaque.md-THEME_NAME-theme{background-color:'{{foreground-4-0.5}}'}

View File

@@ -0,0 +1,59 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-backdrop {
z-index: 50;
background-color: transparent;
position: absolute;
height: 100%;
left: 0;
right: 0; }
md-backdrop.md-select-backdrop {
z-index: 81; }
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 {
top: 0;
position: fixed; }
md-backdrop.ng-enter {
-webkit-animation: cubic-bezier(0.25, 0.8, 0.25, 1) mdBackdropFadeIn 0.5s both;
animation: cubic-bezier(0.25, 0.8, 0.25, 1) mdBackdropFadeIn 0.5s both; }
md-backdrop.ng-leave {
-webkit-animation: cubic-bezier(0.55, 0, 0.55, 0.2) mdBackdropFadeOut 0.2s both;
animation: cubic-bezier(0.55, 0, 0.55, 0.2) mdBackdropFadeOut 0.2s both; }
@-webkit-keyframes mdBackdropFadeIn {
from {
opacity: 0; }
to {
opacity: 1; } }
@keyframes mdBackdropFadeIn {
from {
opacity: 0; }
to {
opacity: 1; } }
@-webkit-keyframes mdBackdropFadeOut {
from {
opacity: 1; }
to {
opacity: 0; } }
@keyframes mdBackdropFadeOut {
from {
opacity: 1; }
to {
opacity: 0; } }

View File

@@ -0,0 +1,39 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/*
* @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', BackdropDirective);
function BackdropDirective($mdTheming) {
return $mdTheming;
}
BackdropDirective.$inject = ["$mdTheming"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-backdrop{z-index:50;background-color:transparent;position:absolute;height:100%;left:0;right:0}md-backdrop.md-select-backdrop{z-index:81}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{top:0;position:fixed}md-backdrop.ng-enter{-webkit-animation:cubic-bezier(.25,.8,.25,1) mdBackdropFadeIn .5s both;animation:cubic-bezier(.25,.8,.25,1) mdBackdropFadeIn .5s both}md-backdrop.ng-leave{-webkit-animation:cubic-bezier(.55,0,.55,.2) mdBackdropFadeOut .2s both;animation:cubic-bezier(.55,0,.55,.2) mdBackdropFadeOut .2s both}@-webkit-keyframes mdBackdropFadeIn{from{opacity:0}to{opacity:1}}@keyframes mdBackdropFadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes mdBackdropFadeOut{from{opacity:1}to{opacity:0}}@keyframes mdBackdropFadeOut{from{opacity:1}to{opacity:0}}

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(n,e,i){"use strict";function o(n){return n}e.module("material.components.backdrop",["material.core"]).directive("mdBackdrop",o),o.$inject=["$mdTheming"]}(window,window.angular);

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-backdrop",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,16 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
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,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/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}}';color:'{{foreground-1}}'}

View File

@@ -0,0 +1,170 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
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);
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition-property: -webkit-transform;
transition-property: 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;
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-bottom-sheet .md-subheader {
background-color: transparent;
font-family: RobotoDraft, 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-flex;
display: -ms-flexbox;
display: flex;
outline: none; }
md-bottom-sheet md-list-item:hover {
cursor: pointer; }
md-bottom-sheet.md-list md-list-item {
padding: 0;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
height: 48px; }
md-bottom-sheet.md-list md-list-item div.md-icon-container {
display: inline-block;
height: 24px;
margin-right: 32px; }
md-bottom-sheet.md-grid {
padding-left: 24px;
padding-right: 24px;
padding-top: 0; }
md-bottom-sheet.md-grid md-list {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
transition: all 0.5s;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; }
md-bottom-sheet.md-grid md-list-item {
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
transition: all 0.5s;
height: 96px;
margin-top: 8px;
margin-bottom: 8px;
/* Mixin for how many grid items to show per row */ }
@media screen and (max-width: 600px) {
md-bottom-sheet.md-grid md-list-item {
-webkit-flex: 1 1 33.33333%;
-ms-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-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start; }
md-bottom-sheet.md-grid md-list-item:nth-of-type(3n) {
-webkit-align-items: flex-end;
-ms-flex-align: end;
align-items: flex-end; } }
@media screen and (min-width: 600px) and (max-width: 960px) {
md-bottom-sheet.md-grid md-list-item {
-webkit-flex: 1 1 25%;
-ms-flex: 1 1 25%;
flex: 1 1 25%;
max-width: 25%; } }
@media screen and (min-width: 960px) and (max-width: 1200px) {
md-bottom-sheet.md-grid md-list-item {
-webkit-flex: 1 1 16.66667%;
-ms-flex: 1 1 16.66667%;
flex: 1 1 16.66667%;
max-width: 16.66667%; } }
@media screen and (min-width: 1200px) {
md-bottom-sheet.md-grid md-list-item {
-webkit-flex: 1 1 14.28571%;
-ms-flex: 1 1 14.28571%;
flex: 1 1 14.28571%;
max-width: 14.28571%; } }
md-bottom-sheet.md-grid md-list-item .md-list-item-content {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-align-items: center;
-ms-flex-align: 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-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
width: 80px; }
md-bottom-sheet.md-grid md-list-item .md-icon-container {
display: inline-block;
box-sizing: border-box;
height: 48px;
width: 48px;
margin: 0 0; }
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,267 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.bottomSheet
* @description
* BottomSheet
*/
angular.module('material.components.bottomSheet', [
'material.core',
'material.components.backdrop'
])
.directive('mdBottomSheet', MdBottomSheetDirective)
.provider('$mdBottomSheet', MdBottomSheetProvider);
function MdBottomSheetDirective() {
return {
restrict: 'E'
};
}
/**
* @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-bottom-sheet>'
* });
* };
* });
* </hljs>
*/
/**
* @ngdoc method
* @name $mdBottomSheet#show
*
* @description
* Show a bottom sheet with the specified options.
*
* @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.
* - `targetEvent` - `{DOMClickEvent=}`: A click's event object. When passed in as an option,
* the location of the click will be used as the starting point for the opening animation
* of the the dialog.
* - `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).
*
* @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()`.
*
* @param {*=} response An argument for the rejected promise.
*
*/
function MdBottomSheetProvider($$interimElementProvider) {
// how fast we need to flick down to close the sheet, pixels/ms
var CLOSING_VELOCITY = 0.5;
var PADDING = 80; // same as css
bottomSheetDefaults.$inject = ["$animate", "$mdConstant", "$mdUtil", "$timeout", "$compile", "$mdTheming", "$mdBottomSheet", "$rootElement", "$mdGesture"];
return $$interimElementProvider('$mdBottomSheet')
.setDefaults({
methods: ['disableParentScroll', 'escapeToClose', 'targetEvent'],
options: bottomSheetDefaults
});
/* ngInject */
function bottomSheetDefaults($animate, $mdConstant, $mdUtil, $timeout, $compile, $mdTheming, $mdBottomSheet, $rootElement, $mdGesture) {
var backdrop;
return {
themable: true,
targetEvent: null,
onShow: onShow,
onRemove: onRemove,
escapeToClose: true,
disableParentScroll: true
};
function onShow(scope, element, options) {
element = $mdUtil.extractElementByName(element, 'md-bottom-sheet');
// Add a backdrop that will close on click
backdrop = $compile('<md-backdrop class="md-opaque md-bottom-sheet-backdrop">')(scope);
backdrop.on('click', function() {
$timeout($mdBottomSheet.cancel);
});
$mdTheming.inherit(backdrop, options.parent);
$animate.enter(backdrop, options.parent, null);
var bottomSheet = new BottomSheet(element, options.parent);
options.bottomSheet = bottomSheet;
// Give up focus on calling item
options.targetEvent && angular.element(options.targetEvent.target).blur();
$mdTheming.inherit(bottomSheet.element, options.parent);
if (options.disableParentScroll) {
options.lastOverflow = options.parent.css('overflow');
options.parent.css('overflow', 'hidden');
}
return $animate.enter(bottomSheet.element, options.parent)
.then(function() {
var focusable = angular.element(
element[0].querySelector('button') ||
element[0].querySelector('a') ||
element[0].querySelector('[ng-click]')
);
focusable.focus();
if (options.escapeToClose) {
options.rootElementKeyupCallback = function(e) {
if (e.keyCode === $mdConstant.KEY_CODE.ESCAPE) {
$timeout($mdBottomSheet.cancel);
}
};
$rootElement.on('keyup', options.rootElementKeyupCallback);
}
});
}
function onRemove(scope, element, options) {
var bottomSheet = options.bottomSheet;
$animate.leave(backdrop);
return $animate.leave(bottomSheet.element).then(function() {
if (options.disableParentScroll) {
options.parent.css('overflow', options.lastOverflow);
delete options.lastOverflow;
}
bottomSheet.cleanup();
// Restore focus
options.targetEvent && angular.element(options.targetEvent.target).focus();
});
}
/**
* 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)
.off('$md.drag', onDrag)
.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');
$timeout($mdBottomSheet.cancel);
} else {
element.css($mdConstant.CSS.TRANSITION_DURATION, '');
element.css($mdConstant.CSS.TRANSFORM, '');
}
}
}
}
}
MdBottomSheetProvider.$inject = ["$$interimElementProvider"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-bottom-sheet{position:absolute;left:0;right:0;bottom:0;padding:8px 16px 88px;z-index:70;border-top-width:1px;border-top-style:solid;-webkit-transform:translate3d(0,80px,0);transform:translate3d(0,80px,0);transition:all .4s cubic-bezier(.25,.8,.25,1);transition-property:-webkit-transform;transition-property: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;transition:all .3s cubic-bezier(.55,0,.55,.2)}md-bottom-sheet .md-subheader{background-color:transparent;font-family:RobotoDraft,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-flex;display:-ms-flexbox;display:flex;outline:0}md-bottom-sheet md-list-item:hover{cursor:pointer}md-bottom-sheet.md-list md-list-item{padding:0;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:48px}md-bottom-sheet.md-list md-list-item div.md-icon-container{display:inline-block;height:24px;margin-right:32px}md-bottom-sheet.md-grid{padding-left:24px;padding-right:24px;padding-top:0}md-bottom-sheet.md-grid md-list{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;transition:all .5s;-webkit-align-items:center;-ms-flex-align:center;align-items:center}md-bottom-sheet.md-grid md-list-item{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:center;-ms-flex-align:center;align-items:center;transition:all .5s;height:96px;margin-top:8px;margin-bottom:8px}@media screen and (max-width:600px){md-bottom-sheet.md-grid md-list-item{-webkit-flex:1 1 33.33333%;-ms-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-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}md-bottom-sheet.md-grid md-list-item:nth-of-type(3n){-webkit-align-items:flex-end;-ms-flex-align:end;align-items:flex-end}}@media screen and (min-width:600px) and (max-width:960px){md-bottom-sheet.md-grid md-list-item{-webkit-flex:1 1 25%;-ms-flex:1 1 25%;flex:1 1 25%;max-width:25%}}@media screen and (min-width:960px) and (max-width:1200px){md-bottom-sheet.md-grid md-list-item{-webkit-flex:1 1 16.66667%;-ms-flex:1 1 16.66667%;flex:1 1 16.66667%;max-width:16.66667%}}@media screen and (min-width:1200px){md-bottom-sheet.md-grid md-list-item{-webkit-flex:1 1 14.28571%;-ms-flex:1 1 14.28571%;flex:1 1 14.28571%;max-width:14.28571%}}md-bottom-sheet.md-grid md-list-item .md-list-item-content{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:center;-ms-flex-align: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-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:center;-ms-flex-align:center;align-items:center;width:80px}md-bottom-sheet.md-grid md-list-item .md-icon-container{display:inline-block;box-sizing:border-box;height:48px;width:48px;margin:0}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,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(e,t,n){"use strict";function o(){return{restrict:"E"}}function r(e){function n(e,n,a,l,c,i,s,m,d){function u(o,r,d){r=a.extractElementByName(r,"md-bottom-sheet"),S=c('<md-backdrop class="md-opaque md-bottom-sheet-backdrop">')(o),S.on("click",function(){l(s.cancel)}),i.inherit(S,d.parent),e.enter(S,d.parent,null);var u=new f(r,d.parent);return d.bottomSheet=u,d.targetEvent&&t.element(d.targetEvent.target).blur(),i.inherit(u.element,d.parent),d.disableParentScroll&&(d.lastOverflow=d.parent.css("overflow"),d.parent.css("overflow","hidden")),e.enter(u.element,d.parent).then(function(){var e=t.element(r[0].querySelector("button")||r[0].querySelector("a")||r[0].querySelector("[ng-click]"));e.focus(),d.escapeToClose&&(d.rootElementKeyupCallback=function(e){e.keyCode===n.KEY_CODE.ESCAPE&&l(s.cancel)},m.on("keyup",d.rootElementKeyupCallback))})}function p(n,o,r){var a=r.bottomSheet;return e.leave(S),e.leave(a.element).then(function(){r.disableParentScroll&&(r.parent.css("overflow",r.lastOverflow),delete r.lastOverflow),a.cleanup(),r.targetEvent&&t.element(r.targetEvent.target).focus()})}function f(e,t){function a(t){e.css(n.CSS.TRANSITION_DURATION,"0ms")}function c(t){var o=t.pointer.distanceY;5>o&&(o=Math.max(-r,o/2)),e.css(n.CSS.TRANSFORM,"translate3d(0,"+(r+o)+"px,0)")}function i(t){if(t.pointer.distanceY>0&&(t.pointer.distanceY>20||Math.abs(t.pointer.velocityY)>o)){var r=e.prop("offsetHeight")-t.pointer.distanceY,a=Math.min(r/t.pointer.velocityY*.75,500);e.css(n.CSS.TRANSITION_DURATION,a+"ms"),l(s.cancel)}else e.css(n.CSS.TRANSITION_DURATION,""),e.css(n.CSS.TRANSFORM,"")}var m=d.register(t,"drag",{horizontal:!1});return t.on("$md.dragstart",a).on("$md.drag",c).on("$md.dragend",i),{element:e,cleanup:function(){m(),t.off("$md.dragstart",a).off("$md.drag",c).off("$md.dragend",i)}}}var S;return{themable:!0,targetEvent:null,onShow:u,onRemove:p,escapeToClose:!0,disableParentScroll:!0}}var o=.5,r=80;return n.$inject=["$animate","$mdConstant","$mdUtil","$timeout","$compile","$mdTheming","$mdBottomSheet","$rootElement","$mdGesture"],e("$mdBottomSheet").setDefaults({methods:["disableParentScroll","escapeToClose","targetEvent"],options:n})}t.module("material.components.bottomSheet",["material.core","material.components.backdrop"]).directive("mdBottomSheet",o).provider("$mdBottomSheet",r),r.$inject=["$$interimElementProvider"]}(window,window.angular);

View File

@@ -0,0 +1,8 @@
{
"name": "angular-material-bottomSheet",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0",
"angular-material-backdrop": "0.10.0"
}
}

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-button",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,94 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
a.md-button.md-THEME_NAME-theme, .md-button.md-THEME_NAME-theme {
border-radius: 3px; }
a.md-button.md-THEME_NAME-theme:not([disabled]):hover, .md-button.md-THEME_NAME-theme:not([disabled]):hover {
background-color: '{{background-500-0.2}}'; }
a.md-button.md-THEME_NAME-theme:not([disabled]).md-focused, .md-button.md-THEME_NAME-theme:not([disabled]).md-focused {
background-color: '{{background-500-0.2}}'; }
a.md-button.md-THEME_NAME-theme:not([disabled]).md-icon-button:hover, .md-button.md-THEME_NAME-theme:not([disabled]).md-icon-button:hover {
background-color: transparent; }
a.md-button.md-THEME_NAME-theme.md-fab, .md-button.md-THEME_NAME-theme.md-fab {
border-radius: 50%;
background-color: '{{accent-color}}';
color: '{{accent-contrast}}'; }
a.md-button.md-THEME_NAME-theme.md-fab md-icon, .md-button.md-THEME_NAME-theme.md-fab md-icon {
color: '{{accent-contrast}}'; }
a.md-button.md-THEME_NAME-theme.md-fab:not([disabled]):hover, .md-button.md-THEME_NAME-theme.md-fab:not([disabled]):hover {
background-color: '{{accent-color}}'; }
a.md-button.md-THEME_NAME-theme.md-fab:not([disabled]).md-focused, .md-button.md-THEME_NAME-theme.md-fab:not([disabled]).md-focused {
background-color: '{{accent-A700}}'; }
a.md-button.md-THEME_NAME-theme.md-icon-button, .md-button.md-THEME_NAME-theme.md-icon-button {
border-radius: 50%; }
a.md-button.md-THEME_NAME-theme.md-primary, .md-button.md-THEME_NAME-theme.md-primary {
color: '{{primary-color}}'; }
a.md-button.md-THEME_NAME-theme.md-primary.md-raised, a.md-button.md-THEME_NAME-theme.md-primary.md-fab, .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}}'; }
a.md-button.md-THEME_NAME-theme.md-primary.md-raised:not([disabled]) md-icon, a.md-button.md-THEME_NAME-theme.md-primary.md-fab:not([disabled]) md-icon, .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}}'; }
a.md-button.md-THEME_NAME-theme.md-primary.md-raised:not([disabled]):hover, a.md-button.md-THEME_NAME-theme.md-primary.md-fab:not([disabled]):hover, .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-color}}'; }
a.md-button.md-THEME_NAME-theme.md-primary.md-raised:not([disabled]).md-focused, a.md-button.md-THEME_NAME-theme.md-primary.md-fab:not([disabled]).md-focused, .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}}'; }
a.md-button.md-THEME_NAME-theme.md-primary:not([disabled]) md-icon, .md-button.md-THEME_NAME-theme.md-primary:not([disabled]) md-icon {
color: '{{primary-color}}'; }
a.md-button.md-THEME_NAME-theme.md-fab, .md-button.md-THEME_NAME-theme.md-fab {
border-radius: 50%;
background-color: '{{accent-color}}';
color: '{{accent-contrast}}'; }
a.md-button.md-THEME_NAME-theme.md-fab:not([disabled]) .md-icon, .md-button.md-THEME_NAME-theme.md-fab:not([disabled]) .md-icon {
color: '{{accent-contrast}}'; }
a.md-button.md-THEME_NAME-theme.md-fab:not([disabled]):hover, .md-button.md-THEME_NAME-theme.md-fab:not([disabled]):hover {
background-color: '{{accent-color}}'; }
a.md-button.md-THEME_NAME-theme.md-fab:not([disabled]).md-focused, .md-button.md-THEME_NAME-theme.md-fab:not([disabled]).md-focused {
background-color: '{{accent-A700}}'; }
a.md-button.md-THEME_NAME-theme.md-raised, .md-button.md-THEME_NAME-theme.md-raised {
color: '{{background-contrast}}';
background-color: '{{background-50}}'; }
a.md-button.md-THEME_NAME-theme.md-raised:not([disabled]) .md-icon, .md-button.md-THEME_NAME-theme.md-raised:not([disabled]) .md-icon {
color: '{{background-contrast}}'; }
a.md-button.md-THEME_NAME-theme.md-raised:not([disabled]):hover, .md-button.md-THEME_NAME-theme.md-raised:not([disabled]):hover {
background-color: '{{background-50}}'; }
a.md-button.md-THEME_NAME-theme.md-raised:not([disabled]).md-focused, .md-button.md-THEME_NAME-theme.md-raised:not([disabled]).md-focused {
background-color: '{{background-200}}'; }
a.md-button.md-THEME_NAME-theme.md-warn, .md-button.md-THEME_NAME-theme.md-warn {
color: '{{warn-color}}'; }
a.md-button.md-THEME_NAME-theme.md-warn.md-raised, a.md-button.md-THEME_NAME-theme.md-warn.md-fab, .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}}'; }
a.md-button.md-THEME_NAME-theme.md-warn.md-raised:not([disabled]) md-icon, a.md-button.md-THEME_NAME-theme.md-warn.md-fab:not([disabled]) md-icon, .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}}'; }
a.md-button.md-THEME_NAME-theme.md-warn.md-raised:not([disabled]):hover, a.md-button.md-THEME_NAME-theme.md-warn.md-fab:not([disabled]):hover, .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-color}}'; }
a.md-button.md-THEME_NAME-theme.md-warn.md-raised:not([disabled]).md-focused, a.md-button.md-THEME_NAME-theme.md-warn.md-fab:not([disabled]).md-focused, .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-700}}'; }
a.md-button.md-THEME_NAME-theme.md-warn:not([disabled]) md-icon, .md-button.md-THEME_NAME-theme.md-warn:not([disabled]) md-icon {
color: '{{warn-color}}'; }
a.md-button.md-THEME_NAME-theme.md-accent, .md-button.md-THEME_NAME-theme.md-accent {
color: '{{accent-color}}'; }
a.md-button.md-THEME_NAME-theme.md-accent.md-raised, a.md-button.md-THEME_NAME-theme.md-accent.md-fab, .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}}'; }
a.md-button.md-THEME_NAME-theme.md-accent.md-raised:not([disabled]) md-icon, a.md-button.md-THEME_NAME-theme.md-accent.md-fab:not([disabled]) md-icon, .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}}'; }
a.md-button.md-THEME_NAME-theme.md-accent.md-raised:not([disabled]):hover, a.md-button.md-THEME_NAME-theme.md-accent.md-fab:not([disabled]):hover, .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-color}}'; }
a.md-button.md-THEME_NAME-theme.md-accent.md-raised:not([disabled]).md-focused, a.md-button.md-THEME_NAME-theme.md-accent.md-fab:not([disabled]).md-focused, .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-700}}'; }
a.md-button.md-THEME_NAME-theme.md-accent:not([disabled]) md-icon, .md-button.md-THEME_NAME-theme.md-accent:not([disabled]) md-icon {
color: '{{accent-color}}'; }
a.md-button.md-THEME_NAME-theme[disabled], a.md-button.md-THEME_NAME-theme.md-raised[disabled], a.md-button.md-THEME_NAME-theme.md-fab[disabled], a.md-button.md-THEME_NAME-theme.md-accent[disabled], a.md-button.md-THEME_NAME-theme.md-warn[disabled], .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: not-allowed; }
a.md-button.md-THEME_NAME-theme[disabled] md-icon, a.md-button.md-THEME_NAME-theme.md-raised[disabled] md-icon, a.md-button.md-THEME_NAME-theme.md-fab[disabled] md-icon, a.md-button.md-THEME_NAME-theme.md-accent[disabled] md-icon, a.md-button.md-THEME_NAME-theme.md-warn[disabled] md-icon, .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}}'; }
a.md-button.md-THEME_NAME-theme.md-raised[disabled], a.md-button.md-THEME_NAME-theme.md-fab[disabled], .md-button.md-THEME_NAME-theme.md-raised[disabled], .md-button.md-THEME_NAME-theme.md-fab[disabled] {
background-color: '{{foreground-4}}'; }
a.md-button.md-THEME_NAME-theme[disabled], .md-button.md-THEME_NAME-theme[disabled] {
background-color: transparent; }

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,158 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
/**
* Position a FAB button.
*/
.md-button {
box-sizing: border-box;
color: currentColor;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
position: relative;
outline: none;
border: 0;
display: inline-table;
padding: 0 6px;
margin: 6px 8px;
line-height: 36px;
min-height: 36px;
background: transparent;
white-space: nowrap;
min-width: 88px;
text-align: center;
text-transform: uppercase;
font-weight: 500;
font-size: 14px;
font-style: inherit;
font-variant: inherit;
font-family: inherit;
text-decoration: none;
cursor: pointer;
overflow: hidden;
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-button *, .md-button *:before, .md-button *:after {
box-sizing: border-box; }
.md-button:focus {
outline: none; }
.md-button:hover, .md-button:focus {
text-decoration: none; }
.md-button.ng-hide, .md-button.ng-leave {
transition: none; }
.md-button.md-cornered {
border-radius: 0; }
.md-button.md-icon {
padding: 0;
background: none; }
.md-button.md-icon-button {
margin: 0 6px;
height: 48px;
min-width: 0;
line-height: 48px;
padding-left: 0;
padding-right: 0;
width: 48px;
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;
border-radius: 50%;
background-clip: padding-box;
overflow: hidden;
transition: 0.2s linear;
transition-property: background-color, box-shadow; }
.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-icon {
margin-top: 0; }
.md-button.md-fab.md-mini {
line-height: 40px;
width: 40px;
height: 40px; }
.md-toast-open-top .md-button.md-fab-top-left, .md-toast-open-top .md-button.md-fab-top-right {
-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-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-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
width: 100%; }
.md-button-group > .md-button {
-webkit-flex: 1;
-ms-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,136 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.button
* @description
*
* Button
*/
angular
.module('material.components.button', [ 'material.core' ])
.directive('mdButton', MdButtonDirective);
/**
* @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](http://www.google.com/design/spec/style/color.html#color-ui-color-application)
* the FAB button background is filled with the accent color [by default]. The primary color palette may be used with
* the `md-primary` class.
*
* @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, $timeout) {
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) {
return isAnchor(attr) ?
'<a class="md-button" ng-transclude></a>' :
'<button class="md-button" ng-transclude></button>';
}
function postLink(scope, element, attr) {
var node = element[0];
$mdTheming(element);
$mdButtonInkRipple.attach(scope, element);
var elementHasText = node.textContent.trim();
if (!elementHasText) {
$mdAria.expect(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();
}
});
// restrict focus styles to the keyboard
scope.mouseActive = false;
element.on('mousedown', function() {
scope.mouseActive = true;
$timeout(function(){
scope.mouseActive = false;
}, 100);
})
.on('focus', function() {
if(scope.mouseActive === false) { element.addClass('md-focused'); }
})
.on('blur', function() { element.removeClass('md-focused'); });
}
}
MdButtonDirective.$inject = ["$mdButtonInkRipple", "$mdTheming", "$mdAria", "$timeout"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/.md-button{box-sizing:border-box;color:currentColor;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;outline:0;border:0;display:inline-table;padding:0 6px;margin:6px 8px;line-height:36px;min-height:36px;background:0 0;white-space:nowrap;min-width:88px;text-align:center;text-transform:uppercase;font-weight:500;font-size:14px;font-style:inherit;font-variant:inherit;font-family:inherit;text-decoration:none;cursor:pointer;overflow:hidden;transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1)}.md-button *,.md-button :after,.md-button :before{box-sizing:border-box}.md-button:focus{outline:0}.md-button:focus,.md-button:hover{text-decoration:none}.md-button.ng-hide,.md-button.ng-leave{transition:none}.md-button.md-cornered{border-radius:0}.md-button.md-icon{padding:0;background:0 0}.md-button.md-icon-button{margin:0 6px;height:48px;min-width:0;line-height:48px;padding-left:0;padding-right:0;width:48px;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;border-radius:50%;background-clip:padding-box;overflow:hidden;transition:.2s linear;transition-property:background-color,box-shadow}.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-icon{margin-top:0}.md-button.md-fab.md-mini{line-height:40px;width:40px;height:40px}.md-toast-open-top .md-button.md-fab-top-left,.md-toast-open-top .md-button.md-fab-top-right{-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-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-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;width:100%}.md-button-group>.md-button{-webkit-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;width:0;border-width:1px 0 1px 1px;border-radius:0;text-align:center;text-overflow:ellipsis;white-space:nowrap}.md-button-group>.md-button:first-child{border-radius:2px 0 0 2px}.md-button-group>.md-button:last-child{border-right-width:1px;border-radius:0 2px 2px 0}@media screen and (-ms-high-contrast:active){.md-button.md-fab,.md-button.md-raised{border:1px solid #fff}}

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(n,t,e){"use strict";function i(n,e,i,o){function u(n){return t.isDefined(n.href)||t.isDefined(n.ngHref)||t.isDefined(n.ngLink)||t.isDefined(n.uiSref)}function a(n,t){return u(t)?'<a class="md-button" ng-transclude></a>':'<button class="md-button" ng-transclude></button>'}function c(a,c,s){var d=c[0];e(c),n.attach(a,c);var r=d.textContent.trim();r||i.expect(c,"aria-label"),u(s)&&t.isDefined(s.ngDisabled)&&a.$watch(s.ngDisabled,function(n){c.attr("tabindex",n?-1:0)}),c.on("click",function(n){s.disabled===!0&&(n.preventDefault(),n.stopImmediatePropagation())}),a.mouseActive=!1,c.on("mousedown",function(){a.mouseActive=!0,o(function(){a.mouseActive=!1},100)}).on("focus",function(){a.mouseActive===!1&&c.addClass("md-focused")}).on("blur",function(){c.removeClass("md-focused")})}return{restrict:"EA",replace:!0,transclude:!0,template:a,link:c}}t.module("material.components.button",["material.core"]).directive("mdButton",i),i.$inject=["$mdButtonInkRipple","$mdTheming","$mdAria","$timeout"]}(window,window.angular);

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-card",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,12 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-card.md-THEME_NAME-theme {
background-color: '{{background-color}}';
border-radius: 2px; }
md-card.md-THEME_NAME-theme .md-card-image {
border-radius: 2px 2px 0 0; }

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-card.md-THEME_NAME-theme{background-color:'{{background-color}}';border-radius:2px}md-card.md-THEME_NAME-theme .md-card-image{border-radius:2px 2px 0 0}

View File

@@ -0,0 +1,34 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-card {
box-sizing: border-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
margin: 8px;
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.14), 0px 2px 2px 0px rgba(0, 0, 0, 0.098), 0px 1px 5px 0px rgba(0, 0, 0, 0.084); }
md-card > img, md-card > :not(md-card-content) img {
width: 100%; }
md-card md-card-content {
padding: 16px; }
md-card .md-actions {
margin: 0; }
md-card .md-actions .md-button {
margin-bottom: 8px;
margin-top: 8px;
margin-right: 4px;
margin-left: 4px; }
md-card md-card-footer {
padding: 16px; }
@media screen and (-ms-high-contrast: active) {
md-card {
border: 1px solid #fff; } }

View File

@@ -0,0 +1,85 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.card
*
* @description
* Card components.
*/
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, while 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 element with the `.md-actions` class, also used in `md-dialog`.
* You can then position buttons using layout attributes.
*
* 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>
* <div class="md-actions" layout="row" layout-align="end center">
* <md-button>Action 1</md-button>
* <md-button>Action 2</md-button>
* </div>
* </md-card>
* </hljs>
*
*/
function mdCardDirective($mdTheming) {
return {
restrict: 'E',
link: function($scope, $element, $attr) {
$mdTheming($element);
}
};
}
mdCardDirective.$inject = ["$mdTheming"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-card{box-sizing:border-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin:8px;box-shadow:0 3px 1px -2px rgba(0,0,0,.14),0 2px 2px 0 rgba(0,0,0,.098),0 1px 5px 0 rgba(0,0,0,.084)}md-card>:not(md-card-content) img,md-card>img{width:100%}md-card md-card-content{padding:16px}md-card .md-actions{margin:0}md-card .md-actions .md-button{margin:8px 4px}md-card md-card-footer{padding:16px}@media screen and (-ms-high-contrast:active){md-card{border:1px solid #fff}}

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(n,i,t){"use strict";function e(n){return{restrict:"E",link:function(i,t,e){n(t)}}}i.module("material.components.card",["material.core"]).directive("mdCard",e),e.$inject=["$mdTheming"]}(window,window.angular);

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-checkbox",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,47 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-checkbox.md-THEME_NAME-theme .md-ripple {
color: '{{accent-600}}'; }
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-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: '{{background-200}}'; }
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-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: '{{background-200}}'; }
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-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] .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-label {
color: '{{foreground-3}}'; }

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-checkbox.md-THEME_NAME-theme .md-ripple{color:'{{accent-600}}'}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-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:'{{background-200}}'}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-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:'{{background-200}}'}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-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] .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-label{color:'{{foreground-3}}'}

View File

@@ -0,0 +1,124 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-checkbox {
box-sizing: border-box;
display: block;
margin: 8px;
white-space: nowrap;
cursor: pointer;
outline: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
padding-left: 18px;
padding-right: 0;
position: relative;
line-height: 26px;
min-width: 18px;
min-height: 18px; }
html[dir=rtl] md-checkbox {
padding-left: 0; }
html[dir=rtl] md-checkbox {
padding-right: 18px; }
md-checkbox *, md-checkbox *:before, md-checkbox *:after {
box-sizing: border-box; }
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-container {
position: absolute;
top: 50%;
display: inline-block;
width: 18px;
height: 18px;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
left: 0;
right: auto; }
html[dir=rtl] md-checkbox .md-container {
left: auto; }
html[dir=rtl] md-checkbox .md-container {
right: 0; }
md-checkbox .md-container:before {
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; }
md-checkbox .md-container:after {
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 {
transition: 240ms;
position: absolute;
top: 0;
left: 0;
width: 18px;
height: 18px;
border-width: 2px;
border-style: solid;
border-radius: 2px; }
md-checkbox.md-checked .md-icon {
border: none; }
md-checkbox[disabled] {
cursor: no-drop; }
md-checkbox.md-checked .md-icon:after {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
left: 6px;
top: 2px;
display: table;
width: 6px;
height: 12px;
border-width: 2px;
border-style: solid;
border-top: 0;
border-left: 0;
content: ''; }
md-checkbox .md-label {
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; }
md-checkbox .md-label span {
margin-left: 10px;
margin-right: 0; }
html[dir=rtl] md-checkbox .md-label span {
margin-left: 0; }
html[dir=rtl] md-checkbox .md-label span {
margin-right: 10px; }

View File

@@ -0,0 +1,167 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.checkbox
* @description Checkbox module!
*/
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-ui-color-application)
* 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 Angular 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.
*
* @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, $mdInkRipple, $mdAria, $mdConstant, $mdTheming, $mdUtil, $timeout) {
inputDirective = inputDirective[0];
var CHECKED_CSS = 'md-checked';
return {
restrict: 'E',
transclude: true,
require: '?ngModel',
priority:210, // Run before ngAria
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.type = 'checkbox';
tAttrs.tabindex = tAttrs.tabindex || '0';
tElement.attr('role', tAttrs.type);
return function postLink(scope, element, attr, ngModelCtrl) {
ngModelCtrl = ngModelCtrl || $mdUtil.fakeNgModel();
$mdTheming(element);
if (attr.ngChecked) {
scope.$watch(
scope.$eval.bind(scope, attr.ngChecked),
ngModelCtrl.$setViewValue.bind(ngModelCtrl)
);
}
$$watchExpr('ngDisabled', 'tabindex', {
true: '-1',
false: attr.tabindex
});
$mdAria.expectWithText(element, 'aria-label');
// Reuse the original input[type=checkbox] directive from Angular 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]);
scope.mouseActive = false;
element.on('click', listener)
.on('keypress', keypressHandler)
.on('mousedown', function() {
scope.mouseActive = true;
$timeout(function(){
scope.mouseActive = false;
}, 100);
})
.on('focus', function() {
if(scope.mouseActive === false) { 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();
if (!element.hasClass('md-focused')) { element.addClass('md-focused'); }
listener(ev);
}
}
function listener(ev) {
if (element[0].hasAttribute('disabled')) return;
scope.$apply(function() {
// Toggle the checkbox value...
var viewValue = attr.ngChecked ? attr.checked : !ngModelCtrl.$viewValue;
ngModelCtrl.$setViewValue( viewValue, ev && ev.type);
ngModelCtrl.$render();
});
}
function render() {
if(ngModelCtrl.$viewValue) {
element.addClass(CHECKED_CSS);
} else {
element.removeClass(CHECKED_CSS);
}
}
};
}
}
MdCheckboxDirective.$inject = ["inputDirective", "$mdInkRipple", "$mdAria", "$mdConstant", "$mdTheming", "$mdUtil", "$timeout"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-checkbox{box-sizing:border-box;display:block;margin:8px;white-space:nowrap;cursor:pointer;outline:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding-left:18px;padding-right:0;position:relative;line-height:26px;min-width:18px;min-height:18px}html[dir=rtl] md-checkbox{padding-left:0;padding-right:18px}md-checkbox *,md-checkbox :after,md-checkbox :before{box-sizing:border-box}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,.12)}md-checkbox .md-container{position:absolute;top:50%;display:inline-block;width:18px;height:18px;-webkit-transform:translateY(-50%);transform:translateY(-50%);left:0;right:auto}html[dir=rtl] md-checkbox .md-container{left:auto;right:0}md-checkbox .md-container:before{background-color:transparent;border-radius:50%;content:'';position:absolute;display:block;height:auto;left:0;top:0;right:0;bottom:0;transition:all .5s;width:auto}md-checkbox .md-container:after{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{transition:240ms;position:absolute;top:0;left:0;width:18px;height:18px;border-width:2px;border-style:solid;border-radius:2px}md-checkbox.md-checked .md-icon{border:none}md-checkbox[disabled]{cursor:no-drop}md-checkbox.md-checked .md-icon:after{-webkit-transform:rotate(45deg);transform:rotate(45deg);position:absolute;left:6px;top:2px;display:table;width:6px;height:12px;border-width:2px;border-style:solid;border-top:0;border-left:0;content:''}md-checkbox .md-label{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}md-checkbox .md-label span{margin-left:10px;margin-right:0}html[dir=rtl] md-checkbox .md-label span{margin-left:0;margin-right:10px}

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(e,n,i){"use strict";function t(e,i,t,c,d,o,a){function s(i,s){return s.type="checkbox",s.tabindex=s.tabindex||"0",i.attr("role",s.type),function(i,s,u,l){function m(e,n,t){u[e]&&i.$watch(u[e],function(e){t[e]&&s.attr(n,t[e])})}function f(e){var n=e.which||e.keyCode;(n===c.KEY_CODE.SPACE||n===c.KEY_CODE.ENTER)&&(e.preventDefault(),s.hasClass("md-focused")||s.addClass("md-focused"),p(e))}function p(e){s[0].hasAttribute("disabled")||i.$apply(function(){var n=u.ngChecked?u.checked:!l.$viewValue;l.$setViewValue(n,e&&e.type),l.$render()})}function v(){l.$viewValue?s.addClass(r):s.removeClass(r)}l=l||o.fakeNgModel(),d(s),u.ngChecked&&i.$watch(i.$eval.bind(i,u.ngChecked),l.$setViewValue.bind(l)),m("ngDisabled","tabindex",{"true":"-1","false":u.tabindex}),t.expectWithText(s,"aria-label"),e.link.pre(i,{on:n.noop,0:{}},u,[l]),i.mouseActive=!1,s.on("click",p).on("keypress",f).on("mousedown",function(){i.mouseActive=!0,a(function(){i.mouseActive=!1},100)}).on("focus",function(){i.mouseActive===!1&&s.addClass("md-focused")}).on("blur",function(){s.removeClass("md-focused")}),l.$render=v}}e=e[0];var r="md-checked";return{restrict:"E",transclude:!0,require:"?ngModel",priority:210,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:s}}n.module("material.components.checkbox",["material.core"]).directive("mdCheckbox",t),t.$inject=["inputDirective","$mdInkRipple","$mdAria","$mdConstant","$mdTheming","$mdUtil","$timeout"]}(window,window.angular);

View File

@@ -0,0 +1,8 @@
{
"name": "angular-material-chips",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0",
"angular-material-autocomplete": "0.10.0"
}
}

View File

@@ -0,0 +1,24 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-chips.md-THEME_NAME-theme .md-chips {
box-shadow: 0 1px '{{background-300}}'; }
md-chips.md-THEME_NAME-theme .md-chips.md-focused {
box-shadow: 0 2px '{{primary-color}}'; }
md-chips.md-THEME_NAME-theme .md-chip {
background: '{{background-300}}';
color: '{{background-800}}'; }
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-remove .md-button md-icon path {
fill: '{{background-500}}'; }
.md-contact-suggestion span.md-contact-email {
color: '{{background-400}}'; }

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-chips.md-THEME_NAME-theme .md-chips{box-shadow:0 1px '{{background-300}}'}md-chips.md-THEME_NAME-theme .md-chips.md-focused{box-shadow:0 2px '{{primary-color}}'}md-chips.md-THEME_NAME-theme .md-chip{background:0 0;color:'{{background-800}}'}md-chips.md-THEME_NAME-theme .md-chip.md-focused{background:0 0;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-remove .md-button md-icon path{fill:'{{background-500}}'}.md-contact-suggestion span.md-contact-email{color:'{{background-400}}'}

View File

@@ -0,0 +1,131 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
.md-contact-chips .md-chips .md-chip {
padding: 0 8px 0 0; }
.md-contact-chips .md-chips .md-chip .md-contact-avatar {
float: left; }
.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; }
.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; }
.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: RobotoDraft, Roboto, 'Helvetica Neue', sans-serif;
font-size: 13px;
padding: 0 0 8px 0;
vertical-align: middle;
cursor: text; }
.md-chips:after {
content: '';
display: table;
clear: both; }
.md-chips .md-chip {
cursor: default;
border-radius: 16px;
display: block;
height: 32px;
line-height: 32px;
margin: 8px 8px 0 0;
padding: 0 8px 0 12px;
float: left; }
.md-chips .md-chip .md-chip-content {
display: block;
padding-right: 4px;
float: left;
white-space: nowrap; }
.md-chips .md-chip .md-chip-content:focus {
outline: none; }
.md-chips .md-chip .md-chip-remove-container {
display: inline-block;
margin-right: -5px; }
.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 8px 0 12px;
float: left; }
.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; }
.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; } }

View File

@@ -0,0 +1,949 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.chips
*/
/*
* @see js folder for chips implementation
*/
angular.module('material.components.chips', [
'material.core',
'material.components.autocomplete'
]);
angular
.module('material.components.chips')
.directive('mdChip', MdChip);
/**
* @ngdoc directive
* @name mdChip
* @module material.components.chips
*
* @description
* `<md-chip>` is a component used within `<md-chips>` and is responsible for rendering individual
* chips.
*
*
* @usage
* <hljs lang="html">
* <md-chip>{{$chip}}</md-chip>
* </hljs>
*
*/
// This hint text is hidden within a chip but used by screen readers to
// inform the user how they can interact with a chip.
var DELETE_HINT_TEMPLATE = '\
<span ng-if="!$mdChipsCtrl.readonly" class="md-visually-hidden">\
{{$mdChipsCtrl.deleteHint}}\
</span>';
/**
* MDChip Directive Definition
*
* @param $mdTheming
* @param $mdInkRipple
* ngInject
*/
function MdChip($mdTheming) {
return {
restrict: 'E',
require: '^?mdChips',
compile: compile
};
function compile(element, attr) {
element.append(DELETE_HINT_TEMPLATE);
return function postLink(scope, element, attr, ctrl) {
element.addClass('md-chip');
$mdTheming(element);
if (ctrl) angular.element(element[0].querySelector('.md-chip-content'))
.on('blur', function () {
ctrl.selectedChip = -1;
});
};
}
}
MdChip.$inject = ["$mdTheming"];
angular
.module('material.components.chips')
.directive('mdChipRemove', MdChipRemove);
/**
* @ngdoc directive
* @name mdChipRemove
* @module material.components.chips
*
* @description
* `<md-chip-remove>`
* Designates an element to be used as the delete button for a chip. This
* element is passed as a child of the `md-chips` element.
*
* @usage
* <hljs lang="html">
* <md-chips><button md-chip-remove>DEL</button></md-chips>
* </hljs>
*/
/**
* MdChipRemove Directive Definition.
*
* @param $compile
* @param $timeout
* @returns {{restrict: string, require: string[], link: Function, scope: boolean}}
* @constructor
*/
function MdChipRemove ($timeout) {
return {
restrict: 'A',
require: '^mdChips',
scope: false,
link: postLink
};
function postLink(scope, element, attr, ctrl) {
element.on('click', function(event) {
scope.$apply(function() {
ctrl.removeChip(scope.$$replacedScope.$index);
});
});
// Child elements aren't available until after a $timeout tick as they are hidden by an
// `ng-if`. see http://goo.gl/zIWfuw
$timeout(function() {
element.attr({ tabindex: -1, ariaHidden: true });
element.find('button').attr('tabindex', '-1');
});
}
}
MdChipRemove.$inject = ["$timeout"];
angular
.module('material.components.chips')
.directive('mdChipTransclude', MdChipTransclude);
function MdChipTransclude ($compile, $mdUtil) {
return {
restrict: 'EA',
terminal: true,
link: link,
scope: false
};
function link (scope, element, attr) {
var ctrl = scope.$parent.$mdChipsCtrl,
newScope = ctrl.parent.$new(false, ctrl.parent);
newScope.$$replacedScope = scope;
newScope.$chip = scope.$chip;
newScope.$mdChipsCtrl = ctrl;
element.html(ctrl.$scope.$eval(attr.mdChipTransclude));
$compile(element.contents())(newScope);
}
}
MdChipTransclude.$inject = ["$compile", "$mdUtil"];
angular
.module('material.components.chips')
.controller('MdChipsCtrl', MdChipsCtrl);
/**
* Controller for the MdChips component. Responsible for adding to and
* removing from the list of chips, marking chips as selected, and binding to
* the models of various input components.
*
* @param $scope
* @param $mdConstant
* @param $log
* @param $element
* @constructor
*/
function MdChipsCtrl ($scope, $mdConstant, $log, $element, $timeout) {
/** @type {$timeout} **/
this.$timeout = $timeout;
/** @type {Object} */
this.$mdConstant = $mdConstant;
/** @type {angular.$scope} */
this.$scope = $scope;
/** @type {angular.$scope} */
this.parent = $scope.$parent;
/** @type {$log} */
this.$log = $log;
/** @type {$element} */
this.$element = $element;
/** @type {angular.NgModelController} */
this.ngModelCtrl = null;
/** @type {angular.NgModelController} */
this.userInputNgModelCtrl = null;
/** @type {Element} */
this.userInputElement = null;
/** @type {Array.<Object>} */
this.items = [];
/** @type {number} */
this.selectedChip = -1;
/**
* Hidden hint text for how to delete a chip. Used to give context to screen readers.
* @type {string}
*/
this.deleteHint = 'Press delete to remove this chip.';
/**
* Hidden label for the delete button. Used to give context to screen readers.
* @type {string}
*/
this.deleteButtonLabel = 'Remove';
/**
* Model used by the input element.
* @type {string}
*/
this.chipBuffer = '';
/**
* Whether to use the mdOnAppend expression to transform the chip buffer
* before appending it to the list.
* @type {boolean}
*/
this.useMdOnAppend = false;
}
MdChipsCtrl.$inject = ["$scope", "$mdConstant", "$log", "$element", "$timeout"];
/**
* Handles the keydown event on the input element: <enter> appends the
* buffer to the chip list, while backspace removes the last chip in the list
* if the current buffer is empty.
* @param event
*/
MdChipsCtrl.prototype.inputKeydown = function(event) {
var chipBuffer = this.getChipBuffer();
switch (event.keyCode) {
case this.$mdConstant.KEY_CODE.ENTER:
if (this.$scope.requireMatch || !chipBuffer) break;
event.preventDefault();
this.appendChip(chipBuffer);
this.resetChipBuffer();
break;
case this.$mdConstant.KEY_CODE.BACKSPACE:
if (chipBuffer) break;
event.stopPropagation();
if (this.items.length) this.selectAndFocusChipSafe(this.items.length - 1);
break;
}
};
/**
* Handles the keydown event on the chip elements: backspace removes the selected chip, arrow
* keys switch which chips is active
* @param event
*/
MdChipsCtrl.prototype.chipKeydown = function (event) {
if (this.getChipBuffer()) return;
switch (event.keyCode) {
case this.$mdConstant.KEY_CODE.BACKSPACE:
case this.$mdConstant.KEY_CODE.DELETE:
if (this.selectedChip < 0) return;
event.preventDefault();
this.removeAndSelectAdjacentChip(this.selectedChip);
break;
case this.$mdConstant.KEY_CODE.LEFT_ARROW:
event.preventDefault();
if (this.selectedChip < 0) this.selectedChip = this.items.length;
if (this.items.length) this.selectAndFocusChipSafe(this.selectedChip - 1);
break;
case this.$mdConstant.KEY_CODE.RIGHT_ARROW:
event.preventDefault();
this.selectAndFocusChipSafe(this.selectedChip + 1);
break;
case this.$mdConstant.KEY_CODE.ESCAPE:
case this.$mdConstant.KEY_CODE.TAB:
if (this.selectedChip < 0) return;
event.preventDefault();
this.onFocus();
break;
}
};
/**
* Get the input's placeholder - uses `placeholder` when list is empty and `secondary-placeholder`
* when the list is non-empty. If `secondary-placeholder` is not provided, `placeholder` is used
* always.
*/
MdChipsCtrl.prototype.getPlaceholder = function() {
// Allow `secondary-placeholder` to be blank.
var useSecondary = (this.items.length &&
(this.secondaryPlaceholder == '' || this.secondaryPlaceholder));
return useSecondary ? this.placeholder : this.secondaryPlaceholder;
};
/**
* Removes chip at {@code index} and selects the adjacent chip.
* @param index
*/
MdChipsCtrl.prototype.removeAndSelectAdjacentChip = function(index) {
var selIndex = this.getAdjacentChipIndex(index);
this.removeChip(index);
this.$timeout(angular.bind(this, function () {
this.selectAndFocusChipSafe(selIndex);
}));
};
/**
* Sets the selected chip index to -1.
*/
MdChipsCtrl.prototype.resetSelectedChip = function() {
this.selectedChip = -1;
};
/**
* Gets the index of an adjacent chip to select after deletion. Adjacency is
* determined as the next chip in the list, unless the target chip is the
* last in the list, then it is the chip immediately preceding the target. If
* there is only one item in the list, -1 is returned (select none).
* The number returned is the index to select AFTER the target has been
* removed.
* If the current chip is not selected, then -1 is returned to select none.
*/
MdChipsCtrl.prototype.getAdjacentChipIndex = function(index) {
var len = this.items.length - 1;
return (len == 0) ? -1 :
(index == len) ? index -1 : index;
};
/**
* Append the contents of the buffer to the chip list. This method will first
* call out to the md-on-append method, if provided
* @param newChip
*/
MdChipsCtrl.prototype.appendChip = function(newChip) {
if (this.items.indexOf(newChip) + 1) return;
if (this.useMdOnAppend && this.mdOnAppend) {
newChip = this.mdOnAppend({'$chip': newChip});
}
this.items.push(newChip);
};
/**
* Sets whether to use the md-on-append expression. This expression is
* bound to scope and controller in {@code MdChipsDirective} as
* {@code mdOnAppend}. Due to the nature of directive scope bindings, the
* controller cannot know on its own/from the scope whether an expression was
* actually provided.
*/
MdChipsCtrl.prototype.useMdOnAppendExpression = function() {
this.useMdOnAppend = true;
};
/**
* Gets the input buffer. The input buffer can be the model bound to the
* default input item {@code this.chipBuffer}, the {@code selectedItem}
* model of an {@code md-autocomplete}, or, through some magic, the model
* bound to any inpput or text area element found within a
* {@code md-input-container} element.
* @return {Object|string}
*/
MdChipsCtrl.prototype.getChipBuffer = function() {
return !this.userInputElement ? this.chipBuffer :
this.userInputNgModelCtrl ? this.userInputNgModelCtrl.$viewValue :
this.userInputElement[0].value;
};
/**
* Resets the input buffer for either the internal input or user provided input element.
*/
MdChipsCtrl.prototype.resetChipBuffer = function() {
if (this.userInputElement) {
if (this.userInputNgModelCtrl) {
this.userInputNgModelCtrl.$setViewValue('');
this.userInputNgModelCtrl.$render();
} else {
this.userInputElement[0].value = '';
}
} else {
this.chipBuffer = '';
}
};
/**
* Removes the chip at the given index.
* @param index
*/
MdChipsCtrl.prototype.removeChip = function(index) {
this.items.splice(index, 1);
};
MdChipsCtrl.prototype.removeChipAndFocusInput = function (index) {
this.removeChip(index);
this.onFocus();
};
/**
* Selects the chip at `index`,
* @param index
*/
MdChipsCtrl.prototype.selectAndFocusChipSafe = function(index) {
if (!this.items.length) {
this.selectChip(-1);
this.onFocus();
return;
}
if (index === this.items.length) return this.onFocus();
index = Math.max(index, 0);
index = Math.min(index, this.items.length - 1);
this.selectChip(index);
this.focusChip(index);
};
/**
* Marks the chip at the given index as selected.
* @param index
*/
MdChipsCtrl.prototype.selectChip = function(index) {
if (index >= -1 && index <= this.items.length) {
this.selectedChip = index;
} else {
this.$log.warn('Selected Chip index out of bounds; ignoring.');
}
};
/**
* Selects the chip at `index` and gives it focus.
* @param index
*/
MdChipsCtrl.prototype.selectAndFocusChip = function(index) {
this.selectChip(index);
if (index != -1) {
this.focusChip(index);
}
};
/**
* Call `focus()` on the chip at `index`
*/
MdChipsCtrl.prototype.focusChip = function(index) {
this.$element[0].querySelector('md-chip[index="' + index + '"] .md-chip-content').focus();
};
/**
* Configures the required interactions with the ngModel Controller.
* Specifically, set {@code this.items} to the {@code NgModelCtrl#$viewVale}.
* @param ngModelCtrl
*/
MdChipsCtrl.prototype.configureNgModel = function(ngModelCtrl) {
this.ngModelCtrl = ngModelCtrl;
var self = this;
ngModelCtrl.$render = function() {
// model is updated. do something.
self.items = self.ngModelCtrl.$viewValue;
};
};
MdChipsCtrl.prototype.onFocus = function () {
var input = this.$element[0].querySelector('input');
input && input.focus();
this.resetSelectedChip();
};
MdChipsCtrl.prototype.onInputFocus = function () {
this.inputHasFocus = true;
this.resetSelectedChip();
};
MdChipsCtrl.prototype.onInputBlur = function () {
this.inputHasFocus = false;
};
/**
* Configure event bindings on a user-provided input element.
* @param inputElement
*/
MdChipsCtrl.prototype.configureUserInput = function(inputElement) {
this.userInputElement = inputElement;
// Find the NgModelCtrl for the input element
var ngModelCtrl = inputElement.controller('ngModel');
// `.controller` will look in the parent as well.
if (ngModelCtrl != this.ngModelCtrl) {
this.userInputNgModelCtrl = ngModelCtrl;
}
// Bind to keydown and focus events of input
var scope = this.$scope;
var ctrl = this;
inputElement
.attr({ tabindex: 0 })
.on('keydown', function(event) { scope.$apply( angular.bind(ctrl, function() { ctrl.inputKeydown(event); })) })
.on('focus', angular.bind(ctrl, ctrl.onInputFocus))
.on('blur', angular.bind(ctrl, ctrl.onInputBlur));
};
MdChipsCtrl.prototype.configureAutocomplete = function(ctrl) {
ctrl.registerSelectedItemWatcher(angular.bind(this, function (item) {
if (item) {
this.appendChip(item);
this.resetChipBuffer();
}
}));
this.$element.find('input')
.on('focus',angular.bind(this, this.onInputFocus) )
.on('blur', angular.bind(this, this.onInputBlur) );
};
MdChipsCtrl.prototype.hasFocus = function () {
return this.inputHasFocus || this.selectedChip >= 0;
};
angular
.module('material.components.chips')
.directive('mdChips', MdChips);
/**
* @ngdoc directive
* @name mdChips
* @module material.components.chips
*
* @description
* `<md-chips>` is an input component for building lists of strings or objects. The list items are
* displayed as 'chips'. This component can make use of an `<input>` element or an
* `<md-autocomplete>` element.
*
* <strong>Custom `<md-chip-template>` template</strong>
* A custom template may be provided to render the content of each chip. This is achieved by
* specifying an `<md-chip-template>` element as a child of `<md-chips>`. Note: Any attributes on
* `<md-chip-template>` will be dropped as only the innerHTML is used for the chip template. The
* variables `$chip` and `$index` are available in the scope of `<md-chip-template>`, representing
* the chip object and its index in the list of chips, respectively.
* To override the chip delete control, include an element (ideally a button) with the attribute
* `md-chip-remove`. A click listener to remove the chip will be added automatically. The element
* is also placed as a sibling to the chip content (on which there are also click listeners) to
* avoid a nested ng-click situation.
*
* <h3> Pending Features </h3>
* <ul style="padding-left:20px;">
*
* <ul>Style
* <li>Colours for hover, press states (ripple?).</li>
* </ul>
*
* <ul>List Manipulation
* <li>delete item via DEL or backspace keys when selected</li>
* </ul>
*
* <ul>Validation
* <li>de-dupe values (or support duplicates, but fix the ng-repeat duplicate key issue)</li>
* <li>allow a validation callback</li>
* <li>hilighting style for invalid chips</li>
* </ul>
*
* <ul>Item mutation
* <li>Support `
* <md-chip-edit>` template, show/hide the edit element on tap/click? double tap/double
* click?
* </li>
* </ul>
*
* <ul>Truncation and Disambiguation (?)
* <li>Truncate chip text where possible, but do not truncate entries such that two are
* indistinguishable.</li>
* </ul>
*
* <ul>Drag and Drop
* <li>Drag and drop chips between related `<md-chips>` elements.
* </li>
* </ul>
* </ul>
*
* <span style="font-size:.8em;text-align:center">
* Warning: This component is a WORK IN PROGRESS. If you use it now,
* it will probably break on you in the future.
* </span>
*
* @param {string=|object=} ng-model A model to bind the list of items to
* @param {string=} placeholder Placeholder text that will be forwarded to the input.
* @param {string=} secondary-placeholder Placeholder text that will be forwarded to the input,
* displayed when there is at least on item in the list
* @param {boolean=} readonly Disables list manipulation (deleting or adding list items), hiding
* the input and delete buttons
* @param {expression} md-on-append An expression expected to convert the input string into an
* object when adding a chip.
* @param {string=} delete-hint A string read by screen readers instructing users that pressing
* the delete key will remove the chip.
* @param {string=} delete-button-label A label for the delete button. Also hidden and read by
* screen readers.
*
* @usage
* <hljs lang="html">
* <md-chips
* ng-model="myItems"
* placeholder="Add an item"
* readonly="isReadOnly">
* </md-chips>
* </hljs>
*
*/
var MD_CHIPS_TEMPLATE = '\
<md-chips-wrap\
ng-if="!$mdChipsCtrl.readonly || $mdChipsCtrl.items.length > 0"\
ng-keydown="$mdChipsCtrl.chipKeydown($event)"\
ng-class="{ \'md-focused\': $mdChipsCtrl.hasFocus() }"\
class="md-chips">\
<md-chip ng-repeat="$chip in $mdChipsCtrl.items"\
index="{{$index}}"\
ng-class="{\'md-focused\': $mdChipsCtrl.selectedChip == $index}">\
<div class="md-chip-content"\
tabindex="-1"\
aria-hidden="true"\
ng-focus="!$mdChipsCtrl.readonly && $mdChipsCtrl.selectChip($index)"\
md-chip-transclude="$mdChipsCtrl.chipContentsTemplate"></div>\
<div class="md-chip-remove-container"\
md-chip-transclude="$mdChipsCtrl.chipRemoveTemplate"></div>\
</md-chip>\
<div ng-if="!$mdChipsCtrl.readonly && $mdChipsCtrl.ngModelCtrl"\
class="md-chip-input-container"\
md-chip-transclude="$mdChipsCtrl.chipInputTemplate"></div>\
</div>\
</md-chips-wrap>';
var CHIP_INPUT_TEMPLATE = '\
<input\
tabindex="0"\
placeholder="{{$mdChipsCtrl.getPlaceholder()}}"\
aria-label="{{$mdChipsCtrl.getPlaceholder()}}"\
ng-model="$mdChipsCtrl.chipBuffer"\
ng-focus="$mdChipsCtrl.onInputFocus()"\
ng-blur="$mdChipsCtrl.onInputBlur()"\
ng-keydown="$mdChipsCtrl.inputKeydown($event)">';
var CHIP_DEFAULT_TEMPLATE = '\
<span>{{$chip}}</span>';
var CHIP_REMOVE_TEMPLATE = '\
<button\
class="md-chip-remove"\
ng-if="!$mdChipsCtrl.readonly"\
ng-click="$mdChipsCtrl.removeChipAndFocusInput($$replacedScope.$index)"\
type="button"\
aria-hidden="true"\
tabindex="-1">\
<md-icon md-svg-icon="md-close"></md-icon>\
<span class="md-visually-hidden">\
{{$mdChipsCtrl.deleteButtonLabel}}\
</span>\
</button>';
/**
* MDChips Directive Definition
*/
function MdChips ($mdTheming, $mdUtil, $compile, $log, $timeout) {
return {
template: function(element, attrs) {
// Clone the element into an attribute. By prepending the attribute
// name with '$', Angular won't write it into the DOM. The cloned
// element propagates to the link function via the attrs argument,
// where various contained-elements can be consumed.
var content = attrs['$mdUserTemplate'] = element.clone();
return MD_CHIPS_TEMPLATE;
},
require: ['mdChips'],
restrict: 'E',
controller: 'MdChipsCtrl',
controllerAs: '$mdChipsCtrl',
bindToController: true,
compile: compile,
scope: {
readonly: '=readonly',
placeholder: '@',
secondaryPlaceholder: '@',
mdOnAppend: '&',
deleteHint: '@',
deleteButtonLabel: '@',
requireMatch: '=?mdRequireMatch'
}
};
/**
* Builds the final template for `md-chips` and returns the postLink function.
*
* Building the template involves 3 key components:
* static chips
* chip template
* input control
*
* If no `ng-model` is provided, only the static chip work needs to be done.
*
* If no user-passed `md-chip-template` exists, the default template is used. This resulting
* template is appended to the chip content element.
*
* The remove button may be overridden by passing an element with an md-chip-remove attribute.
*
* If an `input` or `md-autocomplete` element is provided by the caller, it is set aside for
* transclusion later. The transclusion happens in `postLink` as the parent scope is required.
* If no user input is provided, a default one is appended to the input container node in the
* template.
*
* Static Chips (i.e. `md-chip` elements passed from the caller) are gathered and set aside for
* transclusion in the `postLink` function.
*
*
* @param element
* @param attr
* @returns {Function}
*/
function compile(element, attr) {
// Grab the user template from attr and reset the attribute to null.
var userTemplate = attr['$mdUserTemplate'];
attr['$mdUserTemplate'] = null;
// Set the chip remove, chip contents and chip input templates. The link function will put
// them on the scope for transclusion later.
var chipRemoveTemplate = getTemplateByQuery('md-chips>*[md-chip-remove]') || CHIP_REMOVE_TEMPLATE,
chipContentsTemplate = getTemplateByQuery('md-chips>md-chip-template') || CHIP_DEFAULT_TEMPLATE,
chipInputTemplate = getTemplateByQuery('md-chips>md-autocomplete')
|| getTemplateByQuery('md-chips>input')
|| CHIP_INPUT_TEMPLATE,
staticChips = userTemplate.find('md-chip');
// Warn of malformed template. See #2545
if (userTemplate[0].querySelector('md-chip-template>*[md-chip-remove]')) {
$log.warn('invalid placement of md-chip-remove within md-chip-template.');
}
function getTemplateByQuery (query) {
if (!attr.ngModel) return;
var element = userTemplate[0].querySelector(query);
return element && element.outerHTML;
}
/**
* Configures controller and transcludes.
*/
return function postLink(scope, element, attrs, controllers) {
$mdUtil.initOptionalProperties(scope, attr);
$mdTheming(element);
var mdChipsCtrl = controllers[0];
mdChipsCtrl.chipContentsTemplate = chipContentsTemplate;
mdChipsCtrl.chipRemoveTemplate = chipRemoveTemplate;
mdChipsCtrl.chipInputTemplate = chipInputTemplate;
element
.attr({ ariaHidden: true, tabindex: -1 })
.on('focus', function () { mdChipsCtrl.onFocus(); });
if (attr.ngModel) {
mdChipsCtrl.configureNgModel(element.controller('ngModel'));
// If an `md-on-append` attribute was set, tell the controller to use the expression
// when appending chips.
if (attrs.mdOnAppend) mdChipsCtrl.useMdOnAppendExpression();
// The md-autocomplete and input elements won't be compiled until after this directive
// is complete (due to their nested nature). Wait a tick before looking for them to
// configure the controller.
if (chipInputTemplate != CHIP_INPUT_TEMPLATE) {
$timeout(function() {
if (chipInputTemplate.indexOf('<md-autocomplete') === 0)
mdChipsCtrl
.configureAutocomplete(element.find('md-autocomplete')
.controller('mdAutocomplete'));
mdChipsCtrl.configureUserInput(element.find('input'));
});
}
}
// Compile with the parent's scope and prepend any static chips to the wrapper.
if (staticChips.length > 0) {
var compiledStaticChips = $compile(staticChips)(scope.$parent);
$timeout(function() { element.find('md-chips-wrap').prepend(compiledStaticChips); });
}
};
}
}
MdChips.$inject = ["$mdTheming", "$mdUtil", "$compile", "$log", "$timeout"];
angular
.module('material.components.chips')
.controller('MdContactChipsCtrl', MdContactChipsCtrl);
/**
* Controller for the MdContactChips component
* @constructor
*/
function MdContactChipsCtrl () {
/** @type {Object} */
this.selectedItem = null;
/** @type {string} */
this.searchText = '';
}
MdContactChipsCtrl.prototype.queryContact = function(searchText) {
var results = this.contactQuery({'$query': searchText});
return this.filterSelected ?
results.filter(angular.bind(this, this.filterSelectedContacts)) : results;
};
MdContactChipsCtrl.prototype.filterSelectedContacts = function(contact) {
return this.contacts.indexOf(contact) == -1;
};
angular
.module('material.components.chips')
.directive('mdContactChips', MdContactChips);
/**
* @ngdoc directive
* @name mdContactChips
* @module material.components.chips
*
* @description
* `<md-contact-chips>` is an input component based on `md-chips` and makes use of an
* `md-autocomplete` element. The component allows the caller to supply a query expression
* which returns a list of possible contacts. The user can select one of these and add it to
* the list of chips.
*
* @param {string=|object=} ng-model A model to bind the list of items to
* @param {string=} placeholder Placeholder text that will be forwarded to the input.
* @param {string=} secondary-placeholder Placeholder text that will be forwarded to the input,
* displayed when there is at least on item in the list
* @param {expression} md-contacts An expression expected to return contacts matching the search
* test, `$query`.
* @param {string} md-contact-name The field name of the contact object representing the
* contact's name.
* @param {string} md-contact-email The field name of the contact object representing the
* contact's email address.
* @param {string} md-contact-image The field name of the contact object representing the
* contact's image.
*
*
* // The following attribute has been removed but may come back.
* @param {expression=} filter-selected Whether to filter selected contacts from the list of
* suggestions shown in the autocomplete.
*
*
*
* @usage
* <hljs lang="html">
* <md-contact-chips
* ng-model="ctrl.contacts"
* md-contacts="ctrl.querySearch($query)"
* md-contact-name="name"
* md-contact-image="image"
* md-contact-email="email"
* placeholder="To">
* </md-contact-chips>
* </hljs>
*
*/
var MD_CONTACT_CHIPS_TEMPLATE = '\
<md-chips class="md-contact-chips"\
ng-model="$mdContactChipsCtrl.contacts"\
md-require-match="$mdContactChipsCtrl.requireMatch"\
md-autocomplete-snap>\
<md-autocomplete\
md-menu-class="md-contact-chips-suggestions"\
md-selected-item="$mdContactChipsCtrl.selectedItem"\
md-search-text="$mdContactChipsCtrl.searchText"\
md-items="item in $mdContactChipsCtrl.queryContact($mdContactChipsCtrl.searchText)"\
md-item-text="$mdContactChipsCtrl.mdContactName"\
md-no-cache="true"\
md-autoselect\
placeholder="{{$mdContactChipsCtrl.contacts.length == 0 ?\
$mdContactChipsCtrl.placeholder : $mdContactChipsCtrl.secondaryPlaceholder}}">\
<div class="md-contact-suggestion">\
<img \
ng-src="{{item[$mdContactChipsCtrl.contactImage]}}"\
alt="{{item[$mdContactChipsCtrl.contactName]}}" />\
<span class="md-contact-name" md-highlight-text="$mdContactChipsCtrl.searchText">\
{{item[$mdContactChipsCtrl.contactName]}}\
</span>\
<span class="md-contact-email" >{{item[$mdContactChipsCtrl.contactEmail]}}</span>\
</div>\
</md-autocomplete>\
<md-chip-template>\
<div class="md-contact-avatar">\
<img \
ng-src="{{$chip[$mdContactChipsCtrl.contactImage]}}"\
alt="{{$chip[$mdContactChipsCtrl.contactName]}}" />\
</div>\
<div class="md-contact-name">\
{{$chip[$mdContactChipsCtrl.contactName]}}\
</div>\
</md-chip-template>\
</md-chips>';
/**
* MDContactChips Directive Definition
*
* @param $mdTheming
* @returns {*}
* ngInject
*/
function MdContactChips ($mdTheming, $mdUtil) {
return {
template: function(element, attrs) {
return MD_CONTACT_CHIPS_TEMPLATE;
},
restrict: 'E',
controller: 'MdContactChipsCtrl',
controllerAs: '$mdContactChipsCtrl',
bindToController: true,
compile: compile,
scope: {
contactQuery: '&mdContacts',
placeholder: '@',
secondaryPlaceholder: '@',
contactName: '@mdContactName',
contactImage: '@mdContactImage',
contactEmail: '@mdContactEmail',
contacts: '=ngModel',
requireMatch: '=?mdRequireMatch'
}
};
function compile(element, attr) {
return function postLink(scope, element, attrs, controllers) {
$mdUtil.initOptionalProperties(scope, attr);
$mdTheming(element);
element.attr('tabindex', '-1');
};
}
}
MdContactChips.$inject = ["$mdTheming", "$mdUtil"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/.md-contact-chips .md-chips .md-chip{padding:0 8px 0 0}.md-contact-chips .md-chips .md-chip .md-contact-avatar{float:left}.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}.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}.md-contact-suggestion .md-contact-email,.md-contact-suggestion .md-contact-name{display:inline-block;overflow:hidden;text-overflow:ellipsis}.md-contact-chips-suggestions li{height:100%}.md-chips{display:block;font-family:RobotoDraft,Roboto,'Helvetica Neue',sans-serif;font-size:13px;padding:0 0 8px;vertical-align:middle;cursor:text}.md-chips:after{content:'';display:table;clear:both}.md-chips .md-chip{cursor:default;border-radius:16px;display:block;height:32px;line-height:32px;margin:8px 8px 0 0;padding:0 8px 0 12px;float:left}.md-chips .md-chip .md-chip-content{display:block;padding-right:4px;float:left;white-space:nowrap}.md-chips .md-chip .md-chip-content:focus{outline:0}.md-chips .md-chip .md-chip-remove-container{display:inline-block;margin-right:-5px}.md-chips .md-chip .md-chip-remove{text-align:center;width:32px;height:32px;min-width:0;padding:0;background:0 0;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 8px 0 12px;float:left}.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:0}.md-chips .md-chip-input-container md-autocomplete,.md-chips .md-chip-input-container md-autocomplete-wrap{background:0 0}.md-chips .md-chip-input-container md-autocomplete md-autocomplete-wrap{box-shadow:none}.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:0}.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}.md-chips .md-chip-input-container input{background:0 0;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 one or more lines are too long

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-content",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,9 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-content.md-THEME_NAME-theme {
background-color: '{{background-color}}'; }

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-content.md-THEME_NAME-theme{background-color:'{{background-color}}'}

View File

@@ -0,0 +1,20 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
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; }
md-content.autoScroll {
-webkit-overflow-scrolling: auto; }

View File

@@ -0,0 +1,85 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.content
*
* @description
* Scrollable content
*/
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
*
* @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, attr) {
var node = element[0];
$mdTheming(element);
scope.$broadcast('$mdContentLoaded', element);
iosScrollFix(element[0]);
}
};
function ContentController($scope, $element) {
this.$scope = $scope;
this.$element = $element;
}
}
mdContentDirective.$inject = ["$mdTheming"];
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;
}
});
}
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/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}md-content.autoScroll{-webkit-overflow-scrolling:auto}

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(e,t,o){"use strict";function n(e){function t(e,t){this.$scope=e,this.$element=t}return{restrict:"E",controller:["$scope","$element",t],link:function(t,o,n){o[0];e(o),t.$broadcast("$mdContentLoaded",o),i(o[0])}}}function i(e){t.element(e).on("$md.pressdown",function(t){"t"===t.pointer.type&&(t.$materialScrollFixed||(t.$materialScrollFixed=!0,0===e.scrollTop?e.scrollTop=1:e.scrollHeight===e.scrollTop+e.offsetHeight&&(e.scrollTop-=1)))})}t.module("material.components.content",["material.core"]).directive("mdContent",n),n.$inject=["$mdTheming"]}(window,window.angular);

View File

@@ -0,0 +1,8 @@
{
"name": "angular-material-core",
"version": "0.10.0",
"dependencies": {
"angular-material-gestures": "0.10.0",
"angular-material-theming": "0.10.0"
}
}

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

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,8 @@
{
"name": "angular-material-dialog",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0",
"angular-material-backdrop": "0.10.0"
}
}

View File

@@ -0,0 +1,12 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-dialog.md-THEME_NAME-theme {
border-radius: 4px;
background-color: '{{background-color}}'; }
md-dialog.md-THEME_NAME-theme.md-content-overflow .md-actions {
border-top-color: '{{foreground-4}}'; }

View File

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

View File

@@ -0,0 +1,111 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
.md-dialog-is-showing {
max-height: 100%; }
.md-dialog-container {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 80; }
md-dialog {
opacity: 0;
min-width: 240px;
max-width: 80%;
max-height: 80%;
position: relative;
overflow: hidden;
box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.14), 0px 16px 24px 2px rgba(0, 0, 0, 0.098), 0px 6px 30px 5px rgba(0, 0, 0, 0.084);
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column; }
md-dialog.transition-in {
opacity: 1;
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transform: translate3d(0, 0, 0) scale(1);
transform: translate3d(0, 0, 0) scale(1); }
md-dialog.transition-out {
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-webkit-transform: translate3d(0, 100%, 0) scale(0.2);
transform: translate3d(0, 100%, 0) scale(0.2); }
md-dialog > form {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
overflow: auto; }
md-dialog md-dialog-content {
-webkit-order: 1;
-ms-flex-order: 1;
order: 1;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
padding: 24px;
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-subheader.sticky-clone {
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16); }
md-dialog md-dialog-content.sticky-container {
padding: 0; }
md-dialog md-dialog-content.sticky-container > div {
padding: 24px;
padding-top: 0; }
md-dialog .md-actions {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-order: 2;
-ms-flex-order: 2;
order: 2;
box-sizing: border-box;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
margin-bottom: 0;
padding-right: 8px;
padding-left: 16px;
min-height: 52px; }
md-dialog .md-actions .md-button {
margin-bottom: 8px;
margin-left: 8px;
margin-right: 0;
margin-top: 8px; }
md-dialog.md-content-overflow .md-actions {
border-top-width: 1px;
border-top-style: solid; }
@media screen and (-ms-high-contrast: active) {
md-dialog {
border: 1px solid #fff; } }

View File

@@ -0,0 +1,713 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.dialog
*/
angular.module('material.components.dialog', [
'material.core',
'material.components.backdrop'
])
.directive('mdDialog', MdDialogDirective)
.provider('$mdDialog', MdDialogProvider);
function MdDialogDirective($$rAF, $mdTheming) {
return {
restrict: 'E',
link: function(scope, element, attr) {
$mdTheming(element);
$$rAF(function() {
var content = element[0].querySelector('md-dialog-content');
if (content && content.scrollHeight > content.clientHeight) {
element.addClass('md-content-overflow');
}
});
}
};
}
MdDialogDirective.$inject = ["$$rAF", "$mdTheming"];
/**
* @ngdoc service
* @name $mdDialog
* @module material.components.dialog
*
* @description
* `$mdDialog` opens a dialog over the app to inform users about critical information or require
* them to make decisions. There are two approaches for setup: a simple promise API
* and regular object syntax.
*
* ## Restrictions
*
* - The dialog is always given an isolate scope.
* - The dialog's template must have an outer `<md-dialog>` element.
* Inside, use an `<md-dialog-content>` element for the dialog's content, and use
* an element with class `md-actions` for the dialog's actions.
* - Dialogs must cover the entire application to keep interactions inside of them.
* Use the `parent` option to change where dialogs are appended.
*
* ## Sizing
* - Complex dialogs can be sized with `flex="percentage"`, i.e. `flex="66"`.
* - Default max-width is 80% of the `rootElement` or `parent`.
*
* @usage
* <hljs lang="html">
* <div ng-app="demoApp" ng-controller="EmployeeController">
* <div>
* <md-button ng-click="showAlert()" class="md-raised md-warn">
* Employee Alert!
* </md-button>
* </div>
* <div>
* <md-button ng-click="showDialog($event)" class="md-raised">
* Custom Dialog
* </md-button>
* </div>
* <div>
* <md-button ng-click="closeAlert()" ng-disabled="!hasAlert()" class="md-raised">
* Close Alert
* </md-button>
* </div>
* <div>
* <md-button ng-click="showGreeting($event)" class="md-raised md-primary" >
* Greet Employee
* </md-button>
* </div>
* </div>
* </hljs>
*
* ### JavaScript: object syntax
* <hljs lang="js">
* (function(angular, undefined){
* "use strict";
*
* angular
* .module('demoApp', ['ngMaterial'])
* .controller('AppCtrl', AppController);
*
* function AppController($scope, $mdDialog) {
* var alert;
* $scope.showAlert = showAlert;
* $scope.showDialog = showDialog;
* $scope.items = [1, 2, 3];
*
* // Internal method
* function showAlert() {
* alert = $mdDialog.alert({
* title: 'Attention',
* content: 'This is an example of how easy dialogs can be!',
* ok: 'Close'
* });
*
* $mdDialog
* .show( alert )
* .finally(function() {
* alert = undefined;
* });
* }
*
* function showDialog($event) {
* var parentEl = angular.element(document.body);
* $mdDialog.show({
* parent: parentEl,
* targetEvent: $event,
* template:
* '<md-dialog aria-label="List dialog">' +
* ' <md-dialog-content>'+
* ' <md-list>'+
* ' <md-list-item ng-repeat="item in items">'+
* ' <p>Number {{item}}</p>' +
* ' </md-item>'+
* ' </md-list>'+
* ' </md-dialog-content>' +
* ' <div class="md-actions">' +
* ' <md-button ng-click="closeDialog()" class="md-primary">' +
* ' Close Dialog' +
* ' </md-button>' +
* ' </div>' +
* '</md-dialog>',
* locals: {
* items: $scope.items
* },
* controller: DialogController
* });
* function DialogController($scope, $mdDialog, items) {
* $scope.items = items;
* $scope.closeDialog = function() {
* $mdDialog.hide();
* }
* }
* }
* }
* })(angular);
* </hljs>
*
* ### JavaScript: promise API syntax, custom dialog template
* <hljs lang="js">
* (function(angular, undefined){
* "use strict";
*
* angular
* .module('demoApp', ['ngMaterial'])
* .controller('EmployeeController', EmployeeEditor)
* .controller('GreetingController', GreetingController);
*
* // Fictitious Employee Editor to show how to use simple and complex dialogs.
*
* function EmployeeEditor($scope, $mdDialog) {
* var alert;
*
* $scope.showAlert = showAlert;
* $scope.closeAlert = closeAlert;
* $scope.showGreeting = showCustomGreeting;
*
* $scope.hasAlert = function() { return !!alert };
* $scope.userName = $scope.userName || 'Bobby';
*
* // Dialog #1 - Show simple alert dialog and cache
* // reference to dialog instance
*
* function showAlert() {
* alert = $mdDialog.alert()
* .title('Attention, ' + $scope.userName)
* .content('This is an example of how easy dialogs can be!')
* .ok('Close');
*
* $mdDialog
* .show( alert )
* .finally(function() {
* alert = undefined;
* });
* }
*
* // Close the specified dialog instance and resolve with 'finished' flag
* // Normally this is not needed, just use '$mdDialog.hide()' to close
* // the most recent dialog popup.
*
* function closeAlert() {
* $mdDialog.hide( alert, "finished" );
* alert = undefined;
* }
*
* // Dialog #2 - Demonstrate more complex dialogs construction and popup.
*
* function showCustomGreeting($event) {
* $mdDialog.show({
* targetEvent: $event,
* template:
* '<md-dialog>' +
*
* ' <md-dialog-content>Hello {{ employee }}!</md-dialog-content>' +
*
* ' <div class="md-actions">' +
* ' <md-button ng-click="closeDialog()" class="md-primary">' +
* ' Close Greeting' +
* ' </md-button>' +
* ' </div>' +
* '</md-dialog>',
* controller: 'GreetingController',
* onComplete: afterShowAnimation,
* locals: { employee: $scope.userName }
* });
*
* // When the 'enter' animation finishes...
*
* function afterShowAnimation(scope, element, options) {
* // post-show code here: DOM element focus, etc.
* }
* }
*
* // Dialog #3 - Demonstrate use of ControllerAs and passing $scope to dialog
* // Here we used ng-controller="GreetingController as vm" and
* // $scope.vm === <controller instance>
*
* function showCustomGreeting() {
*
* $mdDialog.show({
* clickOutsideToClose: true,
*
* scope: $scope, // use parent scope in template
* preserveScope: true, // do not forget this if use parent scope
* // Since GreetingController is instantiated with ControllerAs syntax
* // AND we are passing the parent '$scope' to the dialog, we MUST
* // use 'vm.<xxx>' in the template markup
*
* template: '<md-dialog>' +
* ' <md-dialog-content>' +
* ' Hi There {{vm.employee}}' +
* ' </md-dialog-content>' +
* '</md-dialog>',
*
* controller: function DialogController($scope, $mdDialog) {
* $scope.closeDialog = function() {
* $mdDialog.hide();
* }
* }
* });
* }
*
* }
*
* // Greeting controller used with the more complex 'showCustomGreeting()' custom dialog
*
* function GreetingController($scope, $mdDialog, employee) {
* // Assigned from construction <code>locals</code> options...
* $scope.employee = employee;
*
* $scope.closeDialog = function() {
* // Easily hides most recent dialog shown...
* // no specific instance reference is needed.
* $mdDialog.hide();
* };
* }
*
* })(angular);
* </hljs>
*/
/**
* @ngdoc method
* @name $mdDialog#alert
*
* @description
* Builds a preconfigured dialog with the specified message.
*
* @returns {obj} an `$mdDialogPreset` with the chainable configuration methods:
*
* - $mdDialogPreset#title(string) - sets title to string
* - $mdDialogPreset#content(string) - sets content / message to string
* - $mdDialogPreset#ok(string) - sets okay button text to string
* - $mdDialogPreset#theme(string) - sets the theme of the dialog
*
*/
/**
* @ngdoc method
* @name $mdDialog#confirm
*
* @description
* Builds a preconfigured dialog with the specified message. You can call show and the promise returned
* will be resolved only if the user clicks the confirm action on the dialog.
*
* @returns {obj} an `$mdDialogPreset` with the chainable configuration methods:
*
* Additionally, it supports the following methods:
*
* - $mdDialogPreset#title(string) - sets title to string
* - $mdDialogPreset#content(string) - sets content / message to string
* - $mdDialogPreset#ok(string) - sets okay button text to string
* - $mdDialogPreset#cancel(string) - sets cancel button text to string
* - $mdDialogPreset#theme(string) - sets the theme of the dialog
*
*/
/**
* @ngdoc method
* @name $mdDialog#show
*
* @description
* Show a dialog with the specified options.
*
* @param {object} optionsOrPreset Either provide an `$mdDialogPreset` returned from `alert()`, and
* `confirm()`, or an options object with the following properties:
* - `templateUrl` - `{string=}`: The url of a template that will be used as the content
* of the dialog.
* - `template` - `{string=}`: Same as templateUrl, except this is an actual template string.
* - `targetEvent` - `{DOMClickEvent=}`: A click's event object. When passed in as an option,
* the location of the click will be used as the starting point for the opening animation
* of the the dialog.
* - `scope` - `{object=}`: the scope to link the template / controller to. If none is specified,
* it will create a new isolate scope.
* This scope will be destroyed when the dialog is removed unless `preserveScope` is set to true.
* - `preserveScope` - `{boolean=}`: whether to preserve the scope when the element is removed. Default is false
* - `disableParentScroll` - `{boolean=}`: Whether to disable scrolling while the dialog is open.
* Default true.
* - `hasBackdrop` - `{boolean=}`: Whether there should be an opaque backdrop behind the dialog.
* Default true.
* - `clickOutsideToClose` - `{boolean=}`: Whether the user can click outside the dialog to
* close it. Default false.
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to close the dialog.
* Default true.
* - `focusOnOpen` - `{boolean=}`: An option to override focus behavior on open. Only disable if
* focusing some other way, as focus management is required for dialogs to be accessible.
* Defaults to true.
* - `controller` - `{string=}`: The controller to associate with the dialog. The controller
* will be injected with the local `$mdDialog`, which passes along a scope for the dialog.
* - `locals` - `{object=}`: An object containing key/value pairs. The keys will be used as names
* of values to inject into the controller. For example, `locals: {three: 3}` would inject
* `three` into the controller, with the value 3. If `bindToController` is true, they will be
* copied to the controller instead.
* - `bindToController` - `bool`: bind the locals to the controller, instead of passing them in.
* These values will not be available until after initialization.
* - `resolve` - `{object=}`: Similar to locals, except it takes promises as values, and the
* dialog will not open until all of the promises resolve.
* - `controllerAs` - `{string=}`: An alias to assign the controller to on the scope.
* - `parent` - `{element=}`: The element to append the dialog to. Defaults to appending
* to the root element of the application.
* - `onComplete` `{function=}`: Callback function used to announce when the show() action is
* finished.
*
* @returns {promise} A promise that can be resolved with `$mdDialog.hide()` or
* rejected with `$mdDialog.cancel()`.
*/
/**
* @ngdoc method
* @name $mdDialog#hide
*
* @description
* Hide an existing dialog and resolve the promise returned from `$mdDialog.show()`.
*
* @param {*=} response An argument for the resolved promise.
*
* @returns {promise} A promise that is resolved when the dialog has been closed.
*/
/**
* @ngdoc method
* @name $mdDialog#cancel
*
* @description
* Hide an existing dialog and reject the promise returned from `$mdDialog.show()`.
*
* @param {*=} response An argument for the rejected promise.
*
* @returns {promise} A promise that is resolved when the dialog has been closed.
*/
function MdDialogProvider($$interimElementProvider) {
var alertDialogMethods = ['title', 'content', 'ariaLabel', 'ok'];
advancedDialogOptions.$inject = ["$mdDialog", "$mdTheming"];
dialogDefaultOptions.$inject = ["$mdAria", "$document", "$mdUtil", "$mdConstant", "$mdTheming", "$mdDialog", "$timeout", "$rootElement", "$animate", "$$rAF", "$q"];
return $$interimElementProvider('$mdDialog')
.setDefaults({
methods: ['disableParentScroll', 'hasBackdrop', 'clickOutsideToClose', 'escapeToClose', 'targetEvent', 'parent'],
options: dialogDefaultOptions
})
.addPreset('alert', {
methods: ['title', 'content', 'ariaLabel', 'ok', 'theme'],
options: advancedDialogOptions
})
.addPreset('confirm', {
methods: ['title', 'content', 'ariaLabel', 'ok', 'cancel', 'theme'],
options: advancedDialogOptions
});
/* ngInject */
function advancedDialogOptions($mdDialog, $mdTheming) {
return {
template: [
'<md-dialog md-theme="{{ dialog.theme }}" aria-label="{{ dialog.ariaLabel }}">',
'<md-dialog-content role="document" tabIndex="-1">',
'<h2 class="md-title">{{ dialog.title }}</h2>',
'<p>{{ dialog.content }}</p>',
'</md-dialog-content>',
'<div class="md-actions">',
'<md-button ng-if="dialog.$type == \'confirm\'"' +
' ng-click="dialog.abort()" class="md-primary">',
'{{ dialog.cancel }}',
'</md-button>',
'<md-button ng-click="dialog.hide()" class="md-primary">',
'{{ dialog.ok }}',
'</md-button>',
'</div>',
'</md-dialog>'
].join(''),
controller: function mdDialogCtrl() {
this.hide = function() {
$mdDialog.hide(true);
};
this.abort = function() {
$mdDialog.cancel();
};
},
controllerAs: 'dialog',
bindToController: true,
theme: $mdTheming.defaultTheme()
};
}
/* ngInject */
function dialogDefaultOptions($mdAria, $document, $mdUtil, $mdConstant, $mdTheming, $mdDialog, $timeout, $rootElement, $animate, $$rAF, $q) {
return {
hasBackdrop: true,
isolateScope: true,
onShow: onShow,
onRemove: onRemove,
clickOutsideToClose: false,
escapeToClose: true,
targetEvent: null,
focusOnOpen: true,
disableParentScroll: true,
transformTemplate: function(template) {
return '<div class="md-dialog-container">' + template + '</div>';
}
};
function trapFocus(ev) {
var dialog = document.querySelector('md-dialog');
if (dialog && !dialog.contains(ev.target)) {
ev.stopImmediatePropagation();
dialog.focus();
}
}
// On show method for dialogs
function onShow(scope, element, options) {
angular.element($document[0].body).addClass('md-dialog-is-showing');
element = $mdUtil.extractElementByName(element, 'md-dialog');
// Incase the user provides a raw dom element, always wrap it in jqLite
options.parent = angular.element(options.parent);
options.popInTarget = angular.element((options.targetEvent || {}).target);
var closeButton = findCloseButton();
if (options.hasBackdrop) {
// Fix for IE 10
var computeFrom = (options.parent[0] == $document[0].body && $document[0].documentElement
&& $document[0].documentElement.scrollTop) ? angular.element($document[0].documentElement) : options.parent;
var parentOffset = computeFrom.prop('scrollTop');
options.backdrop = angular.element('<md-backdrop class="md-dialog-backdrop md-opaque">');
options.backdrop.css('top', parentOffset +'px');
$mdTheming.inherit(options.backdrop, options.parent);
$animate.enter(options.backdrop, options.parent);
element.css('top', parentOffset +'px');
}
var role = 'dialog',
elementToFocus = closeButton;
if (options.$type === 'alert') {
role = 'alertdialog';
elementToFocus = element.find('md-dialog-content');
}
configureAria(element.find('md-dialog'), role, options);
document.addEventListener('focus', trapFocus, true);
if (options.disableParentScroll) {
options.lastOverflow = options.parent.css('overflow');
options.parent.css('overflow', 'hidden');
}
return dialogPopIn(
element,
options.parent,
options.popInTarget && options.popInTarget.length && options.popInTarget
)
.then(function() {
applyAriaToSiblings(element, true);
if (options.escapeToClose) {
options.rootElementKeyupCallback = function(e) {
if (e.keyCode === $mdConstant.KEY_CODE.ESCAPE) {
$timeout($mdDialog.cancel);
}
};
$rootElement.on('keyup', options.rootElementKeyupCallback);
}
if (options.clickOutsideToClose) {
options.dialogClickOutsideCallback = function(ev) {
// Only close if we click the flex container outside the backdrop
if (ev.target === element[0]) {
$timeout($mdDialog.cancel);
}
};
element.on('click', options.dialogClickOutsideCallback);
}
if (options.focusOnOpen) {
elementToFocus.focus();
}
});
function findCloseButton() {
//If no element with class dialog-close, try to find the last
//button child in md-actions and assume it is a close button
var closeButton = element[0].querySelector('.dialog-close');
if (!closeButton) {
var actionButtons = element[0].querySelectorAll('.md-actions button');
closeButton = actionButtons[ actionButtons.length - 1 ];
}
return angular.element(closeButton);
}
}
// On remove function for all dialogs
function onRemove(scope, element, options) {
angular.element($document[0].body).removeClass('md-dialog-is-showing');
if (options.backdrop) {
$animate.leave(options.backdrop);
}
if (options.disableParentScroll) {
options.parent.css('overflow', options.lastOverflow);
delete options.lastOverflow;
}
if (options.escapeToClose) {
$rootElement.off('keyup', options.rootElementKeyupCallback);
}
if (options.clickOutsideToClose) {
element.off('click', options.dialogClickOutsideCallback);
}
applyAriaToSiblings(element, false);
document.removeEventListener('focus', trapFocus, true);
return dialogPopOut(
element,
options.parent,
options.popInTarget && options.popInTarget.length && options.popInTarget
).then(function() {
element.remove();
options.popInTarget && options.popInTarget.focus();
});
}
/**
* Inject ARIA-specific attributes appropriate for Dialogs
*/
function configureAria(element, role, options) {
element.attr({
'role': role,
'tabIndex': '-1'
});
var dialogContent = element.find('md-dialog-content');
if (dialogContent.length === 0){
dialogContent = element;
}
var dialogId = element.attr('id') || ('dialog_' + $mdUtil.nextUid());
dialogContent.attr('id', dialogId);
element.attr('aria-describedby', dialogId);
if (options.ariaLabel) {
$mdAria.expect(element, 'aria-label', options.ariaLabel);
}
else {
$mdAria.expectAsync(element, 'aria-label', function() {
var words = dialogContent.text().split(/\s+/);
if (words.length > 3) words = words.slice(0,3).concat('...');
return words.join(' ');
});
}
}
/**
* Utility function to filter out raw DOM nodes
*/
function isNodeOneOf(elem, nodeTypeArray) {
if (nodeTypeArray.indexOf(elem.nodeName) !== -1) {
return true;
}
}
/**
* Walk DOM to apply or remove aria-hidden on sibling nodes
* and parent sibling nodes
*
* Prevents screen reader interaction behind modal window
* on swipe interfaces
*/
function applyAriaToSiblings(element, value) {
var attribute = 'aria-hidden';
// get raw DOM node
element = element[0];
function walkDOM(element) {
while (element.parentNode) {
if (element === document.body) {
return;
}
var children = element.parentNode.children;
for (var i = 0; i < children.length; i++) {
// skip over child if it is an ascendant of the dialog
// or a script or style tag
if (element !== children[i] && !isNodeOneOf(children[i], ['SCRIPT', 'STYLE'])) {
children[i].setAttribute(attribute, value);
}
}
walkDOM(element = element.parentNode);
}
}
walkDOM(element);
}
function dialogPopIn(container, parentElement, clickElement) {
var dialogEl = container.find('md-dialog');
parentElement.append(container);
transformToClickElement(dialogEl, clickElement);
$$rAF(function() {
dialogEl.addClass('transition-in')
.css($mdConstant.CSS.TRANSFORM, '');
});
return $mdUtil.transitionEndPromise(dialogEl);
}
function dialogPopOut(container, parentElement, clickElement) {
var dialogEl = container.find('md-dialog');
dialogEl.addClass('transition-out').removeClass('transition-in');
transformToClickElement(dialogEl, clickElement);
return $mdUtil.transitionEndPromise(dialogEl);
}
function transformToClickElement(dialogEl, clickElement) {
if (clickElement) {
var clickRect = clickElement[0].getBoundingClientRect();
var dialogRect = dialogEl[0].getBoundingClientRect();
var scaleX = Math.min(0.5, clickRect.width / dialogRect.width);
var scaleY = Math.min(0.5, clickRect.height / dialogRect.height);
dialogEl.css($mdConstant.CSS.TRANSFORM, 'translate3d(' +
(-dialogRect.left + clickRect.left + clickRect.width/2 - dialogRect.width/2) + 'px,' +
(-dialogRect.top + clickRect.top + clickRect.height/2 - dialogRect.height/2) + 'px,' +
'0) scale(' + scaleX + ',' + scaleY + ')'
);
}
}
function dialogTransitionEnd(dialogEl) {
var deferred = $q.defer();
dialogEl.on($mdConstant.CSS.TRANSITIONEND, finished);
function finished(ev) {
//Make sure this transitionend didn't bubble up from a child
if (ev.target === dialogEl[0]) {
dialogEl.off($mdConstant.CSS.TRANSITIONEND, finished);
deferred.resolve();
}
}
return deferred.promise;
}
}
}
MdDialogProvider.$inject = ["$$interimElementProvider"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/.md-dialog-is-showing{max-height:100%}.md-dialog-container{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;position:absolute;top:0;left:0;width:100%;height:100%;z-index:80}md-dialog{opacity:0;min-width:240px;max-width:80%;max-height:80%;position:relative;overflow:hidden;box-shadow:0 8px 10px -5px rgba(0,0,0,.14),0 16px 24px 2px rgba(0,0,0,.098),0 6px 30px 5px rgba(0,0,0,.084);display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}md-dialog.transition-in{opacity:1;transition:all .4s cubic-bezier(.25,.8,.25,1);-webkit-transform:translate3d(0,0,0) scale(1);transform:translate3d(0,0,0) scale(1)}md-dialog.transition-out{transition:all .4s cubic-bezier(.25,.8,.25,1);-webkit-transform:translate3d(0,100%,0) scale(.2);transform:translate3d(0,100%,0) scale(.2)}md-dialog>form{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:auto}md-dialog md-dialog-content{-webkit-order:1;-ms-flex-order:1;order:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:24px;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:0}md-dialog md-dialog-content .md-subheader{margin:0}md-dialog md-dialog-content .md-subheader.sticky-clone{box-shadow:0 2px 4px 0 rgba(0,0,0,.16)}md-dialog md-dialog-content.sticky-container{padding:0}md-dialog md-dialog-content.sticky-container>div{padding:0 24px 24px}md-dialog .md-actions{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-order:2;-ms-flex-order:2;order:2;box-sizing:border-box;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;margin-bottom:0;padding-right:8px;padding-left:16px;min-height:52px}md-dialog .md-actions .md-button{margin:8px 0 8px 8px}md-dialog.md-content-overflow .md-actions{border-top-width:1px;border-top-style:solid}@media screen and (-ms-high-contrast:active){md-dialog{border:1px solid #fff}}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-divider",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,9 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-divider.md-THEME_NAME-theme {
border-top-color: '{{foreground-4}}'; }

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-divider.md-THEME_NAME-theme{border-top-color:'{{foreground-4}}'}

View File

@@ -0,0 +1,14 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-divider {
display: block;
border-top-width: 1px;
border-top-style: solid;
margin: 0; }
md-divider[md-inset] {
margin-left: 80px; }

View File

@@ -0,0 +1,46 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.divider
* @description Divider module!
*/
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
};
}
MdDividerDirective.$inject = ["$mdTheming"];
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-divider{display:block;border-top-width:1px;border-top-style:solid;margin:0}md-divider[md-inset]{margin-left:80px}

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(i,e,n){"use strict";function r(i){return{restrict:"E",link:i}}e.module("material.components.divider",["material.core"]).directive("mdDivider",r),r.$inject=["$mdTheming"]}(window,window.angular);

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-fabActions",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,58 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
(function() {
'use strict';
angular
.module('material.components.fabActions', ['material.core'])
.directive('mdFabActions', MdFabActionsDirective);
/**
* @ngdoc directive
* @name mdFabActions
* @module material.components.fabSpeedDial
*
* @restrict E
*
* @description
* The `<md-fab-actions>` directive is used inside of a `<md-fab-speed-dial>` or
* `<md-fab-toolbar>` directive to mark the 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() {
return {
restrict: 'E',
require: ['^?mdFabSpeedDial', '^?mdFabToolbar'],
link: function(scope, element, attributes, controllers) {
// Grab whichever parent controller is used
var controller = controllers[0] || controllers[1];
// Make the children open/close their parent directive
if (controller) {
angular.forEach(element.children(), function(child) {
angular.element(child).on('focus', controller.open);
angular.element(child).on('blur', controller.close);
});
}
// After setting up the listeners, wrap every child in a new div and add a class that we can
// scale/fling independently
element.children().wrap('<div class="md-fab-action-item">');
}
}
}
})();
})(window, window.angular);

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(n,e,i){"use strict";!function(){function n(){return{restrict:"E",require:["^?mdFabSpeedDial","^?mdFabToolbar"],link:function(n,i,o,t){var c=t[0]||t[1];c&&e.forEach(i.children(),function(n){e.element(n).on("focus",c.open),e.element(n).on("blur",c.close)}),i.children().wrap('<div class="md-fab-action-item">')}}}e.module("material.components.fabActions",["material.core"]).directive("mdFabActions",n)}()}(window,window.angular);

View File

@@ -0,0 +1,9 @@
{
"name": "angular-material-fabSpeedDial",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0",
"angular-material-fabTrigger": "0.10.0",
"angular-material-fabActions": "0.10.0"
}
}

View File

@@ -0,0 +1,100 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-fab-speed-dial {
position: relative;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
/*
* Handle the animations
*/ }
md-fab-speed-dial .md-css-variables {
z-index: 20; }
md-fab-speed-dial.md-is-open .md-fab-action-item {
visibility: visible; }
md-fab-speed-dial md-fab-actions {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
height: 100%; }
md-fab-speed-dial md-fab-actions .md-fab-action-item {
visibility: hidden;
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-fab-speed-dial.md-down {
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column; }
md-fab-speed-dial.md-down md-fab-trigger {
-webkit-order: 1;
-ms-flex-order: 1;
order: 1; }
md-fab-speed-dial.md-down md-fab-actions {
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-order: 2;
-ms-flex-order: 2;
order: 2; }
md-fab-speed-dial.md-up {
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column; }
md-fab-speed-dial.md-up md-fab-trigger {
-webkit-order: 2;
-ms-flex-order: 2;
order: 2; }
md-fab-speed-dial.md-up md-fab-actions {
-webkit-flex-direction: column-reverse;
-ms-flex-direction: column-reverse;
flex-direction: column-reverse;
-webkit-order: 1;
-ms-flex-order: 1;
order: 1; }
md-fab-speed-dial.md-left {
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row; }
md-fab-speed-dial.md-left md-fab-trigger {
-webkit-order: 2;
-ms-flex-order: 2;
order: 2; }
md-fab-speed-dial.md-left md-fab-actions {
-webkit-flex-direction: row-reverse;
-ms-flex-direction: row-reverse;
flex-direction: row-reverse;
-webkit-order: 1;
-ms-flex-order: 1;
order: 1; }
md-fab-speed-dial.md-left md-fab-actions .md-fab-action-item {
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-fab-speed-dial.md-right {
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row; }
md-fab-speed-dial.md-right md-fab-trigger {
-webkit-order: 1;
-ms-flex-order: 1;
order: 1; }
md-fab-speed-dial.md-right md-fab-actions {
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-order: 2;
-ms-flex-order: 2;
order: 2; }
md-fab-speed-dial.md-right md-fab-actions .md-fab-action-item {
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2); }
md-fab-speed-dial.md-scale .md-fab-action-item {
opacity: 0;
-webkit-transform: scale(0);
transform: scale(0);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
transition-duration: 0.14286s; }

View File

@@ -0,0 +1,235 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
(function() {
'use strict';
angular
.module('material.components.fabSpeedDial', [
'material.core',
'material.components.fabTrigger',
'material.components.fabActions'
])
.directive('mdFabSpeedDial', MdFabSpeedDialDirective)
.animation('.md-fling', MdFabSpeedDialFlingAnimation)
.animation('.md-scale', 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%.
*
* @usage
* <hljs lang="html">
* <md-fab-speed-dial direction="up" class="md-fling">
* <md-fab-trigger>
* <md-button aria-label="Add..."><md-icon icon="/img/icons/plus.svg"></md-icon></md-button>
* </md-fab-trigger>
*
* <md-fab-actions>
* <md-button aria-label="Add User">
* <md-icon icon="/img/icons/user.svg"></md-icon>
* </md-button>
*
* <md-button aria-label="Add Group">
* <md-icon icon="/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() {
FabSpeedDialController.$inject = ["$scope", "$element", "$animate"];
return {
restrict: 'E',
scope: {
direction: '@?mdDirection',
isOpen: '=?mdOpen'
},
bindToController: true,
controller: FabSpeedDialController,
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 FabSpeedDialController($scope, $element, $animate) {
var vm = this;
// Define our open/close functions
// Note: Used by fabTrigger and fabActions directives
vm.open = function() {
$scope.$apply('vm.isOpen = true');
};
vm.close = function() {
$scope.$apply('vm.isOpen = false');
};
setupDefaults();
setupListeners();
setupWatchers();
// Set our default variables
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;
}
// Setup our event listeners
function setupListeners() {
$element.on('mouseenter', vm.open);
$element.on('mouseleave', vm.close);
}
// Setup our watchers
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);
});
// Watch for changes to md-open
$scope.$watch('vm.isOpen', function(isOpen) {
var toAdd = isOpen ? 'md-is-open' : '';
var toRemove = isOpen ? '' : 'md-is-open';
$animate.setClass($element, toAdd, toRemove);
});
}
}
}
function MdFabSpeedDialFlingAnimation() {
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 = variablesElement.style.zIndex;
// Always reset the items to their natural position/state
angular.forEach(items, function(item, index) {
var styles = item.style;
styles.transform = '';
styles.transitionDelay = '';
styles.opacity = 1;
// Make the items closest to the trigger have the highest z-index
item.style.zIndex = (items.length - index) + startZIndex;
});
// If the control is closed, hide the items behind the trigger
if (!ctrl.isOpen) {
angular.forEach(items, function(item, index) {
var newPosition, axis;
switch (ctrl.direction) {
case 'up':
newPosition = item.scrollHeight * (index + 1);
axis = 'Y';
break;
case 'down':
newPosition = -item.scrollHeight * (index + 1);
axis = 'Y';
break;
case 'left':
newPosition = item.scrollWidth * (index + 1);
axis = 'X';
break;
case 'right':
newPosition = -item.scrollWidth * (index + 1);
axis = 'X';
break;
}
item.style.transform = 'translate' + axis + '(' + newPosition + 'px)';
});
}
}
return {
addClass: function(element, className, done) {
if (element.hasClass('md-fling')) {
runAnimation(element);
}
},
removeClass: function(element, className, done) {
runAnimation(element);
}
}
}
function MdFabSpeedDialScaleAnimation() {
var delay = 65;
function runAnimation(element) {
var el = element[0];
var ctrl = element.controller('mdFabSpeedDial');
var items = el.querySelectorAll('.md-fab-action-item');
// 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 = ctrl.isOpen ? 'scale(1)' : 'scale(0)';
styles.transitionDelay = (ctrl.isOpen ? offsetDelay : (items.length - offsetDelay)) + 'ms';
});
}
return {
addClass: function(element, className, done) {
runAnimation(element);
},
removeClass: function(element, className, done) {
runAnimation(element);
}
}
}
})();
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-fab-speed-dial{position:relative;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center}md-fab-speed-dial .md-css-variables{z-index:20}md-fab-speed-dial.md-is-open .md-fab-action-item{visibility:visible}md-fab-speed-dial md-fab-actions{display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%}md-fab-speed-dial md-fab-actions .md-fab-action-item{visibility:hidden;transition:all .3s cubic-bezier(.55,0,.55,.2)}md-fab-speed-dial.md-down{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}md-fab-speed-dial.md-down md-fab-trigger{-webkit-order:1;-ms-flex-order:1;order:1}md-fab-speed-dial.md-down md-fab-actions{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-order:2;-ms-flex-order:2;order:2}md-fab-speed-dial.md-up{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}md-fab-speed-dial.md-up md-fab-trigger{-webkit-order:2;-ms-flex-order:2;order:2}md-fab-speed-dial.md-up md-fab-actions{-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;-webkit-order:1;-ms-flex-order:1;order:1}md-fab-speed-dial.md-left{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}md-fab-speed-dial.md-left md-fab-trigger{-webkit-order:2;-ms-flex-order:2;order:2}md-fab-speed-dial.md-left md-fab-actions{-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;-webkit-order:1;-ms-flex-order:1;order:1}md-fab-speed-dial.md-left md-fab-actions .md-fab-action-item{transition:all .3s cubic-bezier(.55,0,.55,.2)}md-fab-speed-dial.md-right{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}md-fab-speed-dial.md-right md-fab-trigger{-webkit-order:1;-ms-flex-order:1;order:1}md-fab-speed-dial.md-right md-fab-actions{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-order:2;-ms-flex-order:2;order:2}md-fab-speed-dial.md-right md-fab-actions .md-fab-action-item{transition:all .3s cubic-bezier(.55,0,.55,.2)}md-fab-speed-dial.md-scale .md-fab-action-item{opacity:0;-webkit-transform:scale(0);transform:scale(0);transition:all .3s cubic-bezier(.55,0,.55,.2);transition-duration:.14286s}

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(n,e,i){"use strict";!function(){function n(){function n(n,e){e.prepend('<div class="md-css-variables"></div>')}function e(n,e,i){function t(){s.direction=s.direction||"down",s.isOpen=s.isOpen||!1}function o(){e.on("mouseenter",s.open),e.on("mouseleave",s.close)}function a(){n.$watch("vm.direction",function(n,t){i.removeClass(e,"md-"+t),i.addClass(e,"md-"+n)}),n.$watch("vm.isOpen",function(n){var t=n?"md-is-open":"",o=n?"":"md-is-open";i.setClass(e,t,o)})}var s=this;s.open=function(){n.$apply("vm.isOpen = true")},s.close=function(){n.$apply("vm.isOpen = false")},t(),o(),a()}return e.$inject=["$scope","$element","$animate"],{restrict:"E",scope:{direction:"@?mdDirection",isOpen:"=?mdOpen"},bindToController:!0,controller:e,controllerAs:"vm",link:n}}function i(){function n(n){var i=n[0],t=n.controller("mdFabSpeedDial"),o=i.querySelectorAll(".md-fab-action-item"),a=i.querySelector(".md-css-variables"),s=a.style.zIndex;e.forEach(o,function(n,e){var i=n.style;i.transform="",i.transitionDelay="",i.opacity=1,n.style.zIndex=o.length-e+s}),t.isOpen||e.forEach(o,function(n,e){var i,o;switch(t.direction){case"up":i=n.scrollHeight*(e+1),o="Y";break;case"down":i=-n.scrollHeight*(e+1),o="Y";break;case"left":i=n.scrollWidth*(e+1),o="X";break;case"right":i=-n.scrollWidth*(e+1),o="X"}n.style.transform="translate"+o+"("+i+"px)"})}return{addClass:function(e,i,t){e.hasClass("md-fling")&&n(e)},removeClass:function(e,i,t){n(e)}}}function t(){function n(n){var t=n[0],o=n.controller("mdFabSpeedDial"),a=t.querySelectorAll(".md-fab-action-item");e.forEach(a,function(n,e){var t=n.style,s=e*i;t.opacity=o.isOpen?1:0,t.transform=o.isOpen?"scale(1)":"scale(0)",t.transitionDelay=(o.isOpen?s:a.length-s)+"ms"})}var i=65;return{addClass:function(e,i,t){n(e)},removeClass:function(e,i,t){n(e)}}}e.module("material.components.fabSpeedDial",["material.core","material.components.fabTrigger","material.components.fabActions"]).directive("mdFabSpeedDial",n).animation(".md-fling",i).animation(".md-scale",t)}()}(window,window.angular);

View File

@@ -0,0 +1,9 @@
{
"name": "angular-material-fabToolbar",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0",
"angular-material-fabTrigger": "0.10.0",
"angular-material-fabActions": "0.10.0"
}
}

View File

@@ -0,0 +1,74 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-fab-toolbar {
display: block;
/*
* Closed styling
*/
/*
* Hover styling
*/ }
md-fab-toolbar .md-fab-toolbar-wrapper {
display: block;
position: relative;
overflow: hidden;
height: 6.8rem; }
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;
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;
transition: all 200ms ease-in; }
md-fab-toolbar.md-left md-fab-trigger {
left: 0; }
md-fab-toolbar.md-left .md-toolbar-tools {
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row; }
md-fab-toolbar.md-right md-fab-trigger {
right: 0; }
md-fab-toolbar.md-right .md-toolbar-tools {
-webkit-flex-direction: row-reverse;
-ms-flex-direction: row-reverse;
flex-direction: row-reverse; }
md-fab-toolbar.md-right .md-toolbar-tools > .md-button:first-child {
margin-left: 0.6rem; }
md-fab-toolbar.md-right .md-toolbar-tools > .md-button:first-child {
margin-right: -0.8rem; }
md-fab-toolbar.md-right .md-toolbar-tools > .md-button:last-child {
margin-right: 8px; }
md-fab-toolbar md-toolbar {
background-color: transparent !important;
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);
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
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,217 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
(function() {
'use strict';
angular
.module('material.components.fabToolbar', [
'material.core',
'material.components.fabTrigger',
'material.components.fabActions'
])
.directive('mdFabToolbar', MdFabToolbarDirective)
.animation('.md-fab-toolbar', MdFabToolbarAnimation);
/**
* @ngdoc directive
* @name mdFabToolbar
* @module material.components.fabToolbar
*
* @restrict E
*
* @description
*
* The `<md-fab-toolbar>` directive is used present a toolbar of elements (usually `<md-button>`s)
* for quick access to common actions when a floating action button is activated (via hover or
* keyboard navigation).
*
* @usage
*
* <hljs lang="html">
* <md-fab-toolbar>
* <md-fab-trigger>
* <md-button aria-label="Add..."><md-icon icon="/img/icons/plus.svg"></md-icon></md-button>
* </md-fab-trigger>
*
* <md-fab-actions>
* <md-button aria-label="Add User">
* <md-icon icon="/img/icons/user.svg"></md-icon>
* </md-button>
*
* <md-button aria-label="Add Group">
* <md-icon icon="/img/icons/group.svg"></md-icon>
* </md-button>
* </md-fab-actions>
* </md-fab-toolbar>
* </hljs>
*
* @param {expression=} md-open Programmatically control whether or not the toolbar is visible.
*/
function MdFabToolbarDirective() {
FabToolbarController.$inject = ["$scope", "$element", "$animate"];
return {
restrict: 'E',
transclude: true,
template:
'<div class="md-fab-toolbar-wrapper">' +
' <div class="md-fab-toolbar-content" ng-transclude></div>' +
'</div>',
scope: {
isOpen: '=?mdOpen'
},
bindToController: true,
controller: FabToolbarController,
controllerAs: 'vm',
link: link
};
function FabToolbarController($scope, $element, $animate) {
var vm = this;
// Set the default to be closed
vm.isOpen = vm.isOpen || false;
vm.open = function() {
vm.isOpen = true;
$scope.$apply();
};
vm.close = function() {
vm.isOpen = false;
$scope.$apply();
};
// Add our class so we can trigger the animation on start
$element.addClass('md-fab-toolbar');
// Setup some mouse events so the hover effect can be triggered
// anywhere over the toolbar
$element.on('mouseenter', vm.open);
$element.on('mouseleave', vm.close);
// Watch for changes to md-open and toggle our class
$scope.$watch('vm.isOpen', function(isOpen) {
var toAdd = isOpen ? 'md-is-open' : '';
var toRemove = isOpen ? '' : 'md-is-open';
$animate.setClass($element, toAdd, toRemove);
});
}
function link(scope, element, attributes) {
// Don't allow focus on the trigger
element.find('md-fab-trigger').find('button').attr('tabindex', '-1');
// 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() {
var originalIconDelay;
function runAnimation(element, className, done) {
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 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 a square
var scale = width * 2;
// 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) {
// Set the width/height to take up the full toolbar width
backgroundElement.style.width = scale + 'px';
backgroundElement.style.height = scale + 'px';
// Set the top/left to move up/left (or right) by the scale width/height
backgroundElement.style.top = -(scale / 2) + 'px';
if (element.hasClass('md-left')) {
backgroundElement.style.left = -(scale / 2) + 'px';
backgroundElement.style.right = null;
}
if (element.hasClass('md-right')) {
backgroundElement.style.right = -(scale / 2) + 'px';
backgroundElement.style.left = null;
}
// Set the next close animation to have the proper delays
backgroundElement.style.transitionDelay = '0ms';
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 {
// Otherwise, set the width/height to the trigger's width/height
backgroundElement.style.width = triggerElement.offsetWidth + 'px';
backgroundElement.style.height = triggerElement.offsetHeight + 'px';
// Reset the position
backgroundElement.style.top = '0px';
if (element.hasClass('md-left')) {
backgroundElement.style.left = '0px';
backgroundElement.style.right = null;
}
if (element.hasClass('md-right')) {
backgroundElement.style.right = '0px';
backgroundElement.style.left = null;
}
// Set the next open animation to have the proper delays
backgroundElement.style.transitionDelay = '200ms';
iconElement.style.transitionDelay = '0ms';
// Apply a transition delay to actions
angular.forEach(actions, function(action, index) {
action.style.transitionDelay = (index * 25) + 'ms';
});
}
}
}
return {
addClass: function(element, className, done) {
runAnimation(element, className, done);
},
removeClass: function(element, className, done) {
runAnimation(element, className, done);
}
}
}
})();
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-fab-toolbar{display:block}md-fab-toolbar .md-fab-toolbar-wrapper{display:block;position:relative;overflow:hidden;height:6.8rem}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;transition:all .3s cubic-bezier(.55,0,.55,.2)}md-fab-toolbar md-fab-trigger md-icon{position:relative;z-index:22;opacity:1;transition:all 200ms ease-in}md-fab-toolbar.md-left md-fab-trigger{left:0}md-fab-toolbar.md-left .md-toolbar-tools{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}md-fab-toolbar.md-right md-fab-trigger{right:0}md-fab-toolbar.md-right .md-toolbar-tools{-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}md-fab-toolbar.md-right .md-toolbar-tools>.md-button:first-child{margin-left:.6rem;margin-right:-.8rem}md-fab-toolbar.md-right .md-toolbar-tools>.md-button:last-child{margin-right:8px}md-fab-toolbar md-toolbar{background-color:transparent!important;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);transition:all .3s cubic-bezier(.55,0,.55,.2);transition-duration:.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,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(t,e,n){"use strict";!function(){function n(){function t(t,e,n){var o=this;o.isOpen=o.isOpen||!1,o.open=function(){o.isOpen=!0,t.$apply()},o.close=function(){o.isOpen=!1,t.$apply()},e.addClass("md-fab-toolbar"),e.on("mouseenter",o.open),e.on("mouseleave",o.close),t.$watch("vm.isOpen",function(t){var o=t?"md-is-open":"",l=t?"":"md-is-open";n.setClass(e,o,l)})}function e(t,e,n){e.find("md-fab-trigger").find("button").attr("tabindex","-1"),e.find("md-fab-trigger").find("button").prepend('<div class="md-fab-toolbar-background"></div>')}return t.$inject=["$scope","$element","$animate"],{restrict:"E",transclude:!0,template:'<div class="md-fab-toolbar-wrapper"> <div class="md-fab-toolbar-content" ng-transclude></div></div>',scope:{isOpen:"=?mdOpen"},bindToController:!0,controller:t,controllerAs:"vm",link:e}}function o(){function n(n,o,l){var s=n[0],a=n.controller("mdFabToolbar"),i=s.querySelector(".md-fab-toolbar-background"),r=s.querySelector("md-fab-trigger button"),d=s.querySelector("md-fab-trigger button md-icon"),c=n.find("md-fab-actions").children();if(r&&i){var f=t.getComputedStyle(r).getPropertyValue("background-color"),m=s.offsetWidth,p=(s.offsetHeight,2*m);i.style.backgroundColor=f,i.style.borderRadius=m+"px",a.isOpen?(i.style.width=p+"px",i.style.height=p+"px",i.style.top=-(p/2)+"px",n.hasClass("md-left")&&(i.style.left=-(p/2)+"px",i.style.right=null),n.hasClass("md-right")&&(i.style.right=-(p/2)+"px",i.style.left=null),i.style.transitionDelay="0ms",d.style.transitionDelay=".3s",e.forEach(c,function(t,e){t.style.transitionDelay=25*(c.length-e)+"ms"})):(i.style.width=r.offsetWidth+"px",i.style.height=r.offsetHeight+"px",i.style.top="0px",n.hasClass("md-left")&&(i.style.left="0px",i.style.right=null),n.hasClass("md-right")&&(i.style.right="0px",i.style.left=null),i.style.transitionDelay="200ms",d.style.transitionDelay="0ms",e.forEach(c,function(t,e){t.style.transitionDelay=25*e+"ms"}))}}return{addClass:function(t,e,o){n(t,e,o)},removeClass:function(t,e,o){n(t,e,o)}}}e.module("material.components.fabToolbar",["material.core","material.components.fabTrigger","material.components.fabActions"]).directive("mdFabToolbar",n).animation(".md-fab-toolbar",o)}()}(window,window.angular);

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-fabTrigger",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,55 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
(function() {
'use strict';
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 the 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() {
return {
restrict: 'E',
require: ['^?mdFabSpeedDial', '^?mdFabToolbar'],
link: function(scope, element, attributes, controllers) {
// Grab whichever parent controller is used
var controller = controllers[0] || controllers[1];
// Make the children open/close their parent directive
if (controller) {
angular.forEach(element.children(), function(child) {
angular.element(child).on('focus', controller.open);
angular.element(child).on('blur', controller.close);
});
}
}
}
}
})();
})(window, window.angular);

View File

@@ -0,0 +1,7 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
!function(e,n,r){"use strict";!function(){function e(){return{restrict:"E",require:["^?mdFabSpeedDial","^?mdFabToolbar"],link:function(e,r,i,o){var t=o[0]||o[1];t&&n.forEach(r.children(),function(e){n.element(e).on("focus",t.open),n.element(e).on("blur",t.close)})}}}n.module("material.components.fabTrigger",["material.core"]).directive("mdFabTrigger",e)}()}(window,window.angular);

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-gridList",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,68 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
md-grid-list {
box-sizing: border-box;
display: block;
position: relative; }
md-grid-list *, md-grid-list *:before, md-grid-list *:after {
box-sizing: border-box; }
md-grid-list md-grid-tile {
display: block;
position: absolute; }
md-grid-list md-grid-tile figure {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
-webkit-justify-content: center;
-ms-flex-pack: 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-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-ms-flex-align: 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,763 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
(function( window, angular, undefined ){
"use strict";
/**
* @ngdoc module
* @name material.components.gridList
*/
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 (as defined in `$mdConstant.MEDIA`).
*
* 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) {
// 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'], 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, props.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 style = {
left: 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 = {
height: '',
paddingBottom: ''
};
switch(rowMode) {
case 'fixed':
style.height = DIMENSION({ unit: rowHeight, span: rowCount, gutter: gutter });
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.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';
});
}
/**
* 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');
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 == 'fit') {
return 'fit';
} else if (rowHeight.indexOf(':') !== -1) {
return 'ratio';
} else {
return 'fixed';
}
}
function applyDefaultUnit(val) {
return /\D$/.test(val) ? val : val + 'px';
}
}
}
GridListDirective.$inject = ["$interpolate", "$mdConstant", "$mdGridLayout", "$mdMedia"];
/* ngInject */
function GridListController($timeout) {
this.layoutInvalidated = false;
this.tilesInvalidated = false;
this.$timeout_ = $timeout;
this.layoutDelegate = angular.noop;
}
GridListController.$inject = ["$timeout"];
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;
}
}
}
GridLayoutFactory.$inject = ["$mdUtil"];
/**
* @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 (as defined in `$mdConstant.MEDIA`).
*
* 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() {
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();
});
}
}
}
GridTileDirective.$inject = ["$mdMedia"];
function GridTileCaptionDirective() {
return {
template: '<figcaption ng-transclude></figcaption>',
transclude: true
};
}
})(window, window.angular);

View File

@@ -0,0 +1,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/md-grid-list{box-sizing:border-box;display:block;position:relative}md-grid-list *,md-grid-list :after,md-grid-list :before{box-sizing:border-box}md-grid-list md-grid-tile{display:block;position:absolute}md-grid-list md-grid-tile figure{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-ms-flex-pack: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-footer,md-grid-list md-grid-tile md-grid-tile-header{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:48px;color:#fff;background:rgba(0,0,0,.18);overflow:hidden;position:absolute;left:0;right:0}md-grid-list md-grid-tile md-grid-tile-footer h3,md-grid-list md-grid-tile md-grid-tile-footer h4,md-grid-list md-grid-tile md-grid-tile-header h3,md-grid-list md-grid-tile md-grid-tile-header h4{font-weight:400;margin:0 0 0 16px}md-grid-list md-grid-tile md-grid-tile-footer h3,md-grid-list md-grid-tile md-grid-tile-header h3{font-size:14px}md-grid-list md-grid-tile md-grid-tile-footer h4,md-grid-list md-grid-tile md-grid-tile-header 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}}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
{
"name": "angular-material-icon",
"version": "0.10.0",
"dependencies": {
"angular-material-core": "0.10.0"
}
}

View File

@@ -0,0 +1,15 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/
/* mixin definition ; sets LTR and RTL within the same style call */
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,6 @@
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.10.0
*/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}}'}

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