{I" class:ETI"ProcessedAsset;FI"logical_path;TI"angular-material.js;FI" pathname;TI"V/home/sindre/Code/hyper/hyper_admin/vendor/assets/javascripts/angular-material.js;FI"content_type;TI"application/javascript;TI" mtime;Tl+“â!TI" length;Ti\ÛI" digest;TI"%483ce69c224bf6e199e4425cc25394c8;FI" source;TI"\Û/*! * Angular Material Design * https://github.com/angular/material * @license MIT * v0.0.3 */ (function(){ angular.module('ngMaterial', [ 'ng', 'ngAnimate', 'material.services.attrBind', 'material.services.compiler', 'material.services.registry', 'material.decorators', 'material.services.aria', "material.components.button","material.components.card","material.components.checkbox","material.components.content","material.components.dialog","material.components.divider","material.components.icon","material.components.linearProgress","material.components.list","material.components.radioButton","material.components.sidenav","material.components.slider","material.components.switch","material.components.tabs","material.components.textField","material.components.toast","material.components.toolbar","material.components.whiteframe"]); var Constant = { KEY_CODE: { ESCAPE: 27, SPACE: 32, LEFT_ARROW: 37, RIGHT_ARROW: 39, ENTER: 13 } }; /* * iterator is a list facade to easily support iteration and accessors * * @param items Array list which this iterator will enumerate * @param reloop Boolean enables iterator to consider the list as an endless reloop */ function iterator(items, reloop) { var trueFn = function() { return true; }; reloop = !!reloop; var _items = items || [ ]; // Published API return { items: getItems, count: count, inRange: inRange, contains: contains, indexOf: indexOf, itemAt: itemAt, findBy: findBy, add: add, remove: remove, first: first, last: last, next: next, previous: previous, hasPrevious: hasPrevious, hasNext: hasNext }; /* * Publish copy of the enumerable set * @returns {Array|*} */ function getItems() { return [].concat(_items); } /* * Determine length of the list * @returns {Array.length|*|number} */ function count() { return _items.length; } /* * Is the index specified valid * @param index * @returns {Array.length|*|number|boolean} */ function inRange(index) { return _items.length && ( index > -1 ) && (index < _items.length ); } /* * Can the iterator proceed to the next item in the list; relative to * the specified item. * * @param item * @returns {Array.length|*|number|boolean} */ function hasNext(item) { return item ? inRange(indexOf(item) + 1) : false; } /* * Can the iterator proceed to the previous item in the list; relative to * the specified item. * * @param item * @returns {Array.length|*|number|boolean} */ function hasPrevious(item) { return item ? inRange(indexOf(item) - 1) : false; } /* * Get item at specified index/position * @param index * @returns {*} */ function itemAt(index) { return inRange(index) ? _items[index] : null; } /* * Find all elements matching the key/value pair * otherwise return null * * @param val * @param key * * @return array */ function findBy(key, val) { return _items.filter(function(item) { return item[key] === val; }); } /* * Add item to list * @param item * @param index * @returns {*} */ function add(item, index) { if ( !item ) return -1; if (!angular.isNumber(index)) { index = _items.length; } _items.splice(index, 0, item); return indexOf(item); } /* * Remove item from list... * @param item */ function remove(item) { if ( contains(item) ){ _items.splice(indexOf(item), 1); } } /* * Get the zero-based index of the target item * @param item * @returns {*} */ function indexOf(item) { return _items.indexOf(item); } /* * Boolean existence check * @param item * @returns {boolean} */ function contains(item) { return item && (indexOf(item) > -1); } /* * Find the next item. If reloop is true and at the end of the list, it will * go back to the first item. If given ,the `validate` callback will be used * determine whether the next item is valid. If not valid, it will try to find the * next item again. * @param item * @param {optional} validate * @returns {*} */ function next(item, validate) { validate = validate || trueFn; if (contains(item)) { var index = indexOf(item) + 1, found = inRange(index) ? _items[ index ] : (reloop ? first() : null); return validate(found) ? found : next(found, validate); } return null; } /* * Find the previous item. If reloop is true and at the beginning of the list, it will * go back to the last item. If given ,the `validate` callback will be used * determine whether the previous item is valid. If not valid, it will try to find the * previous item again. * @param item * @param {optional} validate * @returns {*} */ function previous(item, validate) { validate = validate || trueFn; if (contains(item)) { var index = indexOf(item) - 1, found = inRange(index) ? _items[ index ] : (reloop ? last() : null); return validate(found) ? found : previous(found, validate); } return null; } /* * Return first item in the list * @returns {*} */ function first() { return _items.length ? _items[0] : null; } /* * Return last item in the list... * @returns {*} */ function last() { return _items.length ? _items[_items.length - 1] : null; } } var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; /* for nextUid() function below */ var uid = ['0','0','0']; var Util = { now: window.performance ? angular.bind(performance, performance.now) : Date.now, /** * Checks if the specified element has an ancestor (ancestor being parent, grandparent, etc) * with the given attribute defined. * * Also pass in an optional `limit` (levels of ancestry to scan), default 4. */ ancestorHasAttribute: function ancestorHasAttribute(element, attrName, limit) { limit = limit || 4; var current = element; while (limit-- && current.length) { if (current[0].hasAttribute && current[0].hasAttribute(attrName)) { return true; } current = current.parent(); } return false; }, /** * Checks to see if the element or its parents are disabled. * @param element DOM element to start scanning for `disabled` attribute * @param limit Number of parent levels that should be scanned; defaults to 4 * @returns {*} Boolean */ isParentDisabled: function isParentDisabled(element, limit) { return Util.ancestorHasAttribute(element, 'disabled', limit); }, /** * Checks if two elements have the same parent */ elementIsSibling: function elementIsSibling(element, otherElement) { return element.parent().length && (element.parent()[0] === otherElement.parent()[0]); }, /** * Converts snake_case to camelCase. * @param name Name to normalize */ camelCase: function camelCase(name) { return name .replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { return offset ? letter.toUpperCase() : letter; }); }, /** * Selects 'n' words from a string * for use in an HTML attribute */ stringFromTextBody: function stringFromTextBody(textBody, numWords) { var string = textBody.trim(); if(string.split(/\s+/).length > numWords){ string = textBody.split(/\s+/).slice(1, (numWords + 1)).join(" ") + '...'; } return string; }, /** * Publish the iterator facade to easily support iteration and accessors * @see iterator.js */ iterator: iterator, // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. debounce: function debounce(func, wait, immediate) { var timeout; return function debounced() { var context = this, args = arguments; clearTimeout(timeout); timeout = setTimeout(function() { timeout = null; if (!immediate) func.apply(context, args); }, wait); if (immediate && !timeout) func.apply(context, args); }; }, // Returns a function that can only be triggered every `delay` milliseconds. // In other words, the function will not be called unless it has been more // than `delay` milliseconds since the last call. throttle: function throttle(func, delay) { var recent; return function throttled() { var context = this; var args = arguments; var now = Util.now(); if (!recent || recent - now > delay) { func.apply(context, args); recent = now; } }; }, /** * nextUid, from angular.js. * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric * characters such as '012ABC'. The reason why we are not using simply a number counter is that * the number string gets longer over time, and it can also overflow, where as the nextId * will grow much slower, it is a string, and it will never overflow. * * @returns an unique alpha-numeric string */ nextUid: function() { var index = uid.length; var digit; while(index) { index--; digit = uid[index].charCodeAt(0); if (digit == 57 /*'9'*/) { uid[index] = 'A'; return uid.join(''); } if (digit == 90 /*'Z'*/) { uid[index] = '0'; } else { uid[index] = String.fromCharCode(digit + 1); return uid.join(''); } } uid.unshift('0'); return uid.join(''); }, // Stop watchers and events from firing on a scope without destroying it, // by disconnecting it from its parent and its siblings' linked lists. disconnectScope: function disconnectScope(scope) { if (!scope) return; // we can't destroy the root scope or a scope that has been already destroyed if (scope.$root === scope) return; if (scope.$$destroyed ) return; var parent = scope.$parent; scope.$$disconnected = true; // See Scope.$destroy if (parent.$$childHead === scope) parent.$$childHead = scope.$$nextSibling; if (parent.$$childTail === scope) parent.$$childTail = scope.$$prevSibling; if (scope.$$prevSibling) scope.$$prevSibling.$$nextSibling = scope.$$nextSibling; if (scope.$$nextSibling) scope.$$nextSibling.$$prevSibling = scope.$$prevSibling; scope.$$nextSibling = scope.$$prevSibling = null; }, // Undo the effects of disconnectScope above. reconnectScope: function reconnectScope(scope) { if (!scope) return; // we can't disconnect the root node or scope already disconnected if (scope.$root === scope) return; if (!scope.$$disconnected) return; var child = scope; var parent = child.$parent; child.$$disconnected = false; // See Scope.$new for this logic... child.$$prevSibling = parent.$$childTail; if (parent.$$childHead) { parent.$$childTail.$$nextSibling = child; parent.$$childTail = child; } else { parent.$$childHead = parent.$$childTail = child; } } }; /* * Since removing jQuery from the demos, some code that uses `element.focus()` is broken. * * We need to add `element.focus()`, because it's testable unlike `element[0].focus`. * * TODO(ajoslin): This should be added in a better place later. */ angular.element.prototype.focus = angular.element.prototype.focus || function() { if (this.length) { this[0].focus(); } return this; }; angular.element.prototype.blur = angular.element.prototype.blur || function() { if (this.length) { this[0].blur(); } return this; }; /** * @ngdoc module * @name material.components.animate * @description * * Ink and Popup Effects */ angular.module('material.animations', []) .service('$materialEffects', [ '$rootElement', '$$rAF', '$sniffer', '$q', MaterialEffects ]); /** * @ngdoc service * @name $materialEffects * @module material.components.animate * * @description * The `$materialEffects` service provides a simple API for various * Material Design effects. * * @returns A `$materialEffects` object with the following properties: * - `{function(element,styles,duration)}` `inkBar` - starts ink bar * animation on specified DOM element * - `{function(element,parentElement,clickElement)}` `popIn` - animated show of element overlayed on parent element * - `{function(element,parentElement)}` `popOut` - animated close of popup overlay * */ function MaterialEffects($rootElement, $$rAF, $sniffer, $q) { var webkit = /webkit/i.test($sniffer.vendorPrefix); function vendorProperty(name) { return webkit ? ('webkit' + name.charAt(0).toUpperCase() + name.substring(1)) : name; } var self; // Publish API for effects... return self = { popIn: popIn, /* Constants */ TRANSITIONEND_EVENT: 'transitionend' + (webkit ? ' webkitTransitionEnd' : ''), ANIMATIONEND_EVENT: 'animationend' + (webkit ? ' webkitAnimationEnd' : ''), TRANSFORM: vendorProperty('transform'), TRANSITION: vendorProperty('transition'), TRANSITION_DURATION: vendorProperty('transitionDuration'), ANIMATION_PLAY_STATE: vendorProperty('animationPlayState'), ANIMATION_DURATION: vendorProperty('animationDuration'), ANIMATION_NAME: vendorProperty('animationName'), ANIMATION_TIMING: vendorProperty('animationTimingFunction'), ANIMATION_DIRECTION: vendorProperty('animationDirection') }; // ********************************************************** // API Methods // ********************************************************** function popIn(element, parentElement, clickElement) { var deferred = $q.defer(); parentElement.append(element); var startPos; if (clickElement) { var clickRect = clickElement[0].getBoundingClientRect(); startPos = translateString( clickRect.left - element[0].offsetWidth, clickRect.top - element[0].offsetHeight, 0 ) + ' scale(0.2)'; } else { startPos = 'translate3d(0,100%,0) scale(0.5)'; } element .css(self.TRANSFORM, startPos) .css('opacity', 0); $$rAF(function() { $$rAF(function() { element .addClass('active') .css(self.TRANSFORM, '') .css('opacity', '') .on(self.TRANSITIONEND_EVENT, finished); }); }); function finished(ev) { //Make sure this transitionend didn't bubble up from a child if (ev.target === element[0]) { element.off(self.TRANSITIONEND_EVENT, finished); deferred.resolve(); } } return deferred.promise; } // ********************************************************** // Utility Methods // ********************************************************** function translateString(x, y, z) { return 'translate3d(' + Math.floor(x) + 'px,' + Math.floor(y) + 'px,' + Math.floor(z) + 'px)'; } } (function() { angular.module('material.animations') /** * noink/nobar/nostretch directive: make any element that has one of * these attributes be given a controller, so that other directives can * `require:` these and see if there is a `no` parent attribute. * * @usage * * * * * * * * * myApp.directive('detectNo', function() { * return { * require: ['^?noink', ^?nobar'], * link: function(scope, element, attr, ctrls) { * var noinkCtrl = ctrls[0]; * var nobarCtrl = ctrls[1]; * if (noInkCtrl) { * alert("the noink flag has been specified on an ancestor!"); * } * if (nobarCtrl) { * alert("the nobar flag has been specified on an ancestor!"); * } * } * }; * }); * */ .directive({ noink: attrNoDirective(), nobar: attrNoDirective(), nostretch: attrNoDirective() }); function attrNoDirective() { return function() { return { controller: angular.noop }; }; } })(); angular.module('material.animations') .directive('inkRipple', [ '$materialInkRipple', InkRippleDirective ]) .factory('$materialInkRipple', [ '$window', '$$rAF', '$materialEffects', '$timeout', InkRippleService ]); function InkRippleDirective($materialInkRipple) { return function(scope, element, attr) { if (attr.inkRipple == 'checkbox') { $materialInkRipple.attachCheckboxBehavior(element); } else { $materialInkRipple.attachButtonBehavior(element); } }; } function InkRippleService($window, $$rAF, $materialEffects, $timeout) { // TODO fix this. doesn't support touch AND click devices (eg chrome pixel) var hasTouch = !!('ontouchend' in document); var POINTERDOWN_EVENT = hasTouch ? 'touchstart' : 'mousedown'; var POINTERUP_EVENT = hasTouch ? 'touchend touchcancel' : 'mouseup mouseleave'; return { attachButtonBehavior: attachButtonBehavior, attachCheckboxBehavior: attachCheckboxBehavior, attach: attach }; function attachButtonBehavior(element) { return attach(element, { mousedown: true, center: false, animationDuration: 350, mousedownPauseTime: 175, animationName: 'inkRippleButton', animationTimingFunction: 'linear' }); } function attachCheckboxBehavior(element) { return attach(element, { mousedown: true, center: true, animationDuration: 300, mousedownPauseTime: 180, animationName: 'inkRippleCheckbox', animationTimingFunction: 'linear' }); } function attach(element, options) { // Parent element with noink attr? Abort. if (element.controller('noink')) return angular.noop; options = angular.extend({ mousedown: true, hover: true, focus: true, center: false, animationDuration: 300, mousedownPauseTime: 150, animationName: '', animationTimingFunction: 'linear' }, options || {}); var rippleContainer; var node = element[0]; if (options.mousedown) { enableMousedown(); } // Publish self-detach method if desired... return function detach() { enableMousedown(false); rippleContainer .parent .remove( rippleContainer ); } function enableMousedown(active) { if ( !!active) element.on(POINTERDOWN_EVENT, onPointerDown); else element.off(POINTERDOWN_EVENT, onPointerDown); } function rippleIsAllowed() { return !Util.isParentDisabled(element); } function createRipple(left, top, positionsAreAbsolute) { var rippleEl = angular.element('
') .css($materialEffects.ANIMATION_DURATION, options.animationDuration + 'ms') .css($materialEffects.ANIMATION_NAME, options.animationName) .css($materialEffects.ANIMATION_TIMING, options.animationTimingFunction) .on($materialEffects.ANIMATIONEND_EVENT, function() { rippleEl.remove(); }); if (!rippleContainer) { rippleContainer = angular.element('
'); element.append(rippleContainer); } rippleContainer.append(rippleEl); var containerWidth = rippleContainer.prop('offsetWidth'); if (options.center) { left = containerWidth / 2; top = rippleContainer.prop('offsetHeight') / 2; } else if (positionsAreAbsolute) { var elementRect = node.getBoundingClientRect(); left -= elementRect.left; top -= elementRect.top; } var css = { 'background-color': $window.getComputedStyle(rippleEl[0]).color || $window.getComputedStyle(node).color, 'border-radius': (containerWidth / 2) + 'px', left: (left - containerWidth / 2) + 'px', width: containerWidth + 'px', top: (top - containerWidth / 2) + 'px', height: containerWidth + 'px' }; css[$materialEffects.ANIMATION_DURATION] = options.fadeoutDuration + 'ms'; rippleEl.css(css); return rippleEl; } function onPointerDown(ev) { if (!rippleIsAllowed()) return; var rippleEl = createRippleFromEvent(ev); var ripplePauseTimeout = $timeout(pauseRipple, options.mousedownPauseTime, false); rippleEl.on('$destroy', cancelRipplePause); // Stop listening to pointer down for now, until the user lifts their finger/mouse element.off(POINTERDOWN_EVENT, onPointerDown); element.on(POINTERUP_EVENT, onPointerUp); function onPointerUp() { cancelRipplePause(); rippleEl.css($materialEffects.ANIMATION_PLAY_STATE, 'running'); element.off(POINTERUP_EVENT, onPointerUp); element.on(POINTERDOWN_EVENT, onPointerDown); } function pauseRipple() { rippleEl.css($materialEffects.ANIMATION_PLAY_STATE, 'paused'); } function cancelRipplePause() { $timeout.cancel(ripplePauseTimeout); } function createRippleFromEvent(ev) { ev = ev.touches ? ev.touches[0] : ev; return createRipple(ev.pageX, ev.pageY, true); } } } } /** * @ngdoc module * @name material.components.buttons * @description * * Button */ angular.module('material.components.button', [ 'material.animations', 'material.services.aria' ]) .directive('materialButton', [ 'ngHrefDirective', '$materialInkRipple', '$aria', MaterialButtonDirective ]); /** * @ngdoc directive * @name materialButton * @order 0 * * @restrict E * * @description * `` is a button directive with optional ink ripples (default enabled). * * @param {boolean=} noink Flag indicates use of ripple ink effects * @param {boolean=} disabled Flag indicates if the tab is disabled: not selectable with no ink effects * @param {string=} type Optional attribute to specific button types (useful for forms); such as 'submit', etc. * @param {string=} ng-href Optional attribute to support both ARIA and link navigation * @param {string=} href Optional attribute to support both ARIA and link navigation * @param {string=} ariaLabel Publish the button label used by screen-readers for accessibility. Defaults to the radio button's text. * * @usage * * Button *
* * Button (noInk) * *
* * Colored (disabled) * *
*/ function MaterialButtonDirective(ngHrefDirectives, $materialInkRipple, $aria ) { var ngHrefDirective = ngHrefDirectives[0]; return { restrict: 'E', compile: function(element, attr) { var innerElement; var attributesToCopy; // Add an inner anchor if the element has a `href` or `ngHref` attribute, // so this element can be clicked like a normal ``. if (attr.ngHref || attr.href) { innerElement = angular.element(''); attributesToCopy = ['ng-href', 'href', 'rel', 'target']; // Otherwise, just add an inner button element (for form submission etc) } else { innerElement = angular.element('