summaryrefslogtreecommitdiffstats
path: root/ecomp-portal-FE/client/bower_components/angular-material/modules/js/select/select.js
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-portal-FE/client/bower_components/angular-material/modules/js/select/select.js')
-rw-r--r--ecomp-portal-FE/client/bower_components/angular-material/modules/js/select/select.js1056
1 files changed, 0 insertions, 1056 deletions
diff --git a/ecomp-portal-FE/client/bower_components/angular-material/modules/js/select/select.js b/ecomp-portal-FE/client/bower_components/angular-material/modules/js/select/select.js
deleted file mode 100644
index 969e06b7..00000000
--- a/ecomp-portal-FE/client/bower_components/angular-material/modules/js/select/select.js
+++ /dev/null
@@ -1,1056 +0,0 @@
-/*!
- * Angular Material Design
- * https://github.com/angular/material
- * @license MIT
- * v0.9.8
- */
-(function( window, angular, undefined ){
-"use strict";
-
-/**
- * @ngdoc module
- * @name material.components.select
- */
-
-/***************************************************
-
-### TODO ###
-**DOCUMENTATION AND DEMOS**
-
-- [ ] ng-model with child mdOptions (basic)
-- [ ] ng-model="foo" ng-model-options="{ trackBy: '$value.id' }" for objects
-- [ ] mdOption with value
-- [ ] Usage with input inside
-
-### TODO - POST RC1 ###
-- [ ] Abstract placement logic in $mdSelect service to $mdMenu service
-
-***************************************************/
-
-var SELECT_EDGE_MARGIN = 8;
-var selectNextId = 0;
-
-angular.module('material.components.select', [
- 'material.core',
- 'material.components.backdrop'
-])
-.directive('mdSelect', SelectDirective)
-.directive('mdSelectMenu', SelectMenuDirective)
-.directive('mdOption', OptionDirective)
-.directive('mdOptgroup', OptgroupDirective)
-.provider('$mdSelect', SelectProvider);
-
-
-/**
- * @ngdoc directive
- * @name mdSelect
- * @restrict E
- * @module material.components.select
- *
- * @description Displays a select box, bound to an ng-model.
- *
- * @param {expression} ng-model The model!
- * @param {boolean=} multiple Whether it's multiple.
- * @param {string=} placeholder Placeholder hint text.
- * @param {string=} aria-label Optional label for accessibility. Only necessary if no placeholder or
- * explicit label is present.
- *
- * @usage
- * With a placeholder (label and aria-label are added dynamically)
- * <hljs lang="html">
- * <md-select
- * ng-model="someModel"
- * placeholder="Select a state">
- * <md-option ng-value="opt" ng-repeat="opt in neighborhoods2">{{ opt }}</md-option>
- * </md-select>
- * </hljs>
- *
- * With an explicit label
- * <hljs lang="html">
- * <md-select
- * ng-model="someModel">
- * <md-select-label>Select a state</md-select-label>
- * <md-option ng-value="opt" ng-repeat="opt in neighborhoods2">{{ opt }}</md-option>
- * </md-select>
- * </hljs>
- */
-function SelectDirective($mdSelect, $mdUtil, $mdTheming, $mdAria, $interpolate, $compile, $parse) {
- return {
- restrict: 'E',
- require: ['mdSelect', 'ngModel', '?^form'],
- compile: compile,
- controller: function() { } // empty placeholder controller to be initialized in link
- };
-
- function compile(element, attr) {
- // The user is allowed to provide a label for the select as md-select-label child
- var labelEl = element.find('md-select-label').remove();
-
- // If not provided, we automatically make one
- if (!labelEl.length) {
- labelEl = angular.element('<md-select-label><span></span></md-select-label>');
- } else {
- if (!labelEl[0].firstElementChild) {
- var spanWrapper = angular.element('<span>');
- spanWrapper.append(labelEl.contents());
- labelEl.append(spanWrapper);
- }
- }
- labelEl.append('<span class="md-select-icon" aria-hidden="true"></span>');
- labelEl.addClass('md-select-label');
- if (!labelEl[0].hasAttribute('id')) {
- labelEl.attr('id', 'select_label_' + $mdUtil.nextUid());
- }
-
- // There's got to be an md-content inside. If there's not one, let's add it.
- if (!element.find('md-content').length) {
- element.append( angular.element('<md-content>').append(element.contents()) );
- }
-
- // Add progress spinner for md-options-loading
- if (attr.mdOnOpen) {
- element.find('md-content').prepend(
- angular.element('<md-progress-circular>')
- .attr('md-mode', 'indeterminate')
- .attr('ng-hide', '$$loadingAsyncDone')
- .wrap('<div>')
- .parent()
- );
- }
-
- if (attr.name) {
- var autofillClone = angular.element('<select class="md-visually-hidden">');
- autofillClone.attr({
- 'name': '.' + attr.name,
- 'ng-model': attr.ngModel,
- 'aria-hidden': 'true',
- 'tabindex': '-1'
- });
- var opts = element.find('md-option');
- angular.forEach(opts, function(el) {
- var newEl = angular.element('<option>' + el.innerHTML + '</option>');
- if (el.hasAttribute('ng-value')) newEl.attr('ng-value', el.getAttribute('ng-value'));
- else if (el.hasAttribute('value')) newEl.attr('value', el.getAttribute('value'));
- autofillClone.append(newEl);
- });
-
- element.parent().append(autofillClone);
- }
-
- // Use everything that's left inside element.contents() as the contents of the menu
- var selectTemplate = '<div class="md-select-menu-container">' +
- '<md-select-menu ' +
- (angular.isDefined(attr.multiple) ? 'multiple' : '') + '>' +
- element.html() +
- '</md-select-menu></div>';
-
- element.empty().append(labelEl);
-
- attr.tabindex = attr.tabindex || '0';
-
- return function postLink(scope, element, attr, ctrls) {
- var isOpen;
- var isDisabled;
-
- var mdSelectCtrl = ctrls[0];
- var ngModel = ctrls[1];
- var formCtrl = ctrls[2];
-
- var labelEl = element.find('md-select-label');
- var customLabel = labelEl.text().length !== 0;
- var selectContainer, selectScope, selectMenuCtrl;
- createSelect();
-
- $mdTheming(element);
-
- if (attr.name && formCtrl) {
- var selectEl = element.parent()[0].querySelector('select[name=".' + attr.name + '"]')
- formCtrl.$removeControl(angular.element(selectEl).controller());
- }
-
- var originalRender = ngModel.$render;
- ngModel.$render = function() {
- originalRender();
- syncLabelText();
- };
-
- mdSelectCtrl.setLabelText = function(text) {
- if (customLabel) return; // Assume that user is handling it on their own
- mdSelectCtrl.setIsPlaceholder(!text);
- text = text || attr.placeholder || '';
- var target = customLabel ? labelEl : labelEl.children().eq(0);
- target.text(text);
- };
-
- mdSelectCtrl.setIsPlaceholder = function(val) {
- val ? labelEl.addClass('md-placeholder') : labelEl.removeClass('md-placeholder');
- };
-
- scope.$$postDigest(function() {
- setAriaLabel();
- syncLabelText();
- });
-
- function setAriaLabel() {
- var labelText = element.attr('placeholder');
- if (!labelText) {
- labelText = element.find('md-select-label').text();
- }
- $mdAria.expect(element, 'aria-label', labelText);
- }
-
- function syncLabelText() {
- if (selectContainer) {
- selectMenuCtrl = selectMenuCtrl || selectContainer.find('md-select-menu').controller('mdSelectMenu');
- mdSelectCtrl.setLabelText(selectMenuCtrl.selectedLabels());
- }
- }
-
- var deregisterWatcher;
- attr.$observe('ngMultiple', function(val) {
- if (deregisterWatcher) deregisterWatcher();
- var parser = $parse(val);
- deregisterWatcher = scope.$watch(function() { return parser(scope); }, function(multiple, prevVal) {
- if (multiple === undefined && prevVal === undefined) return; // assume compiler did a good job
- if (multiple) {
- element.attr('multiple', 'multiple');
- } else {
- element.removeAttr('multiple');
- }
- if (selectContainer) {
- selectMenuCtrl.setMultiple(multiple);
- originalRender = ngModel.$render;
- ngModel.$render = function() {
- originalRender();
- syncLabelText();
- };
- selectMenuCtrl.refreshViewValue();
- ngModel.$render();
- }
- });
- });
-
- attr.$observe('disabled', function(disabled) {
- if (typeof disabled == "string") {
- disabled = true;
- }
- // Prevent click event being registered twice
- if (isDisabled !== undefined && isDisabled === disabled) {
- return;
- }
- isDisabled = disabled;
- if (disabled) {
- element.attr({'tabindex': -1, 'aria-disabled': 'true'});
- element.off('click', openSelect);
- element.off('keydown', handleKeypress);
- } else {
- element.attr({'tabindex': attr.tabindex, 'aria-disabled': 'false'});
- element.on('click', openSelect);
- element.on('keydown', handleKeypress);
- }
- });
- if (!attr.disabled && !attr.ngDisabled) {
- element.attr({'tabindex': attr.tabindex, 'aria-disabled': 'false'});
- element.on('click', openSelect);
- element.on('keydown', handleKeypress);
- }
-
- var ariaAttrs = {
- role: 'combobox',
- 'aria-expanded': 'false'
- };
- if (!element[0].hasAttribute('id')) {
- ariaAttrs.id = 'select_' + $mdUtil.nextUid();
- }
- element.attr(ariaAttrs);
-
- scope.$on('$destroy', function() {
- if (isOpen) {
- $mdSelect.cancel().then(function() {
- selectContainer.remove();
- });
- } else {
- selectContainer.remove();
- }
- });
-
-
- // Create a fake select to find out the label value
- function createSelect() {
- selectContainer = angular.element(selectTemplate);
- var selectEl = selectContainer.find('md-select-menu');
- selectEl.data('$ngModelController', ngModel);
- selectEl.data('$mdSelectController', mdSelectCtrl);
- selectScope = scope.$new();
- selectContainer = $compile(selectContainer)(selectScope);
- selectMenuCtrl = selectContainer.find('md-select-menu').controller('mdSelectMenu');
- }
-
- function handleKeypress(e) {
- var allowedCodes = [32, 13, 38, 40];
- if (allowedCodes.indexOf(e.keyCode) != -1 ) {
- // prevent page scrolling on interaction
- e.preventDefault();
- openSelect(e);
- } else {
- if (e.keyCode <= 90 && e.keyCode >= 31) {
- e.preventDefault();
- var node = selectMenuCtrl.optNodeForKeyboardSearch(e);
- if (!node) return;
- var optionCtrl = angular.element(node).controller('mdOption');
- if (!selectMenuCtrl.isMultiple) {
- selectMenuCtrl.deselect( Object.keys(selectMenuCtrl.selected)[0] );
- }
- selectMenuCtrl.select(optionCtrl.hashKey, optionCtrl.value);
- selectMenuCtrl.refreshViewValue();
- ngModel.$render();
- }
- }
- }
-
- function openSelect() {
- scope.$evalAsync(function() {
- isOpen = true;
- $mdSelect.show({
- scope: selectScope,
- preserveScope: true,
- skipCompile: true,
- element: selectContainer,
- target: element[0],
- hasBackdrop: true,
- loadingAsync: attr.mdOnOpen ? scope.$eval(attr.mdOnOpen) || true : false,
- }).then(function(selectedText) {
- isOpen = false;
- });
- });
- }
- };
- }
-}
-SelectDirective.$inject = ["$mdSelect", "$mdUtil", "$mdTheming", "$mdAria", "$interpolate", "$compile", "$parse"];
-
-function SelectMenuDirective($parse, $mdUtil, $mdTheming) {
-
- SelectMenuController.$inject = ["$scope", "$attrs", "$element"];
- return {
- restrict: 'E',
- require: ['mdSelectMenu', '?ngModel'],
- controller: SelectMenuController,
- link: { pre: preLink }
- };
-
- // We use preLink instead of postLink to ensure that the select is initialized before
- // its child options run postLink.
- function preLink(scope, element, attr, ctrls) {
- var selectCtrl = ctrls[0];
- var ngModel = ctrls[1];
-
- $mdTheming(element);
- element.on('click', clickListener);
- element.on('keypress', keyListener);
- if (ngModel) selectCtrl.init(ngModel);
- configureAria();
-
- function configureAria() {
- element.attr({
- 'id': 'select_menu_' + $mdUtil.nextUid(),
- 'role': 'listbox',
- 'aria-multiselectable': (selectCtrl.isMultiple ? 'true' : 'false')
- });
- }
-
- function keyListener(e) {
- if (e.keyCode == 13 || e.keyCode == 32) {
- clickListener(e);
- }
- }
-
- function clickListener(ev) {
- var option = $mdUtil.getClosest(ev.target, 'md-option');
- var optionCtrl = option && angular.element(option).data('$mdOptionController');
- if (!option || !optionCtrl) return;
-
- var optionHashKey = selectCtrl.hashGetter(optionCtrl.value);
- var isSelected = angular.isDefined(selectCtrl.selected[optionHashKey]);
-
- scope.$apply(function() {
- if (selectCtrl.isMultiple) {
- if (isSelected) {
- selectCtrl.deselect(optionHashKey);
- } else {
- selectCtrl.select(optionHashKey, optionCtrl.value);
- }
- } else {
- if (!isSelected) {
- selectCtrl.deselect( Object.keys(selectCtrl.selected)[0] );
- selectCtrl.select( optionHashKey, optionCtrl.value );
- }
- }
- selectCtrl.refreshViewValue();
- });
- }
- }
-
-
-
- function SelectMenuController($scope, $attrs, $element) {
- var self = this;
- self.isMultiple = angular.isDefined($attrs.multiple);
- // selected is an object with keys matching all of the selected options' hashed values
- self.selected = {};
- // options is an object with keys matching every option's hash value,
- // and values matching every option's controller.
- self.options = {};
-
- $scope.$watch(function() { return self.options; }, function() {
- self.ngModel.$render();
- }, true);
-
- var deregisterCollectionWatch;
- self.setMultiple = function(isMultiple) {
- var ngModel = self.ngModel;
- self.isMultiple = isMultiple;
- if (deregisterCollectionWatch) deregisterCollectionWatch();
-
- if (self.isMultiple) {
- ngModel.$validators['md-multiple'] = validateArray;
- ngModel.$render = renderMultiple;
-
- // watchCollection on the model because by default ngModel only watches the model's
- // reference. This allowed the developer to also push and pop from their array.
- $scope.$watchCollection($attrs.ngModel, function(value) {
- if (validateArray(value)) renderMultiple(value);
- });
- } else {
- delete ngModel.$validators['md-multiple'];
- ngModel.$render = renderSingular;
- }
-
- function validateArray(modelValue, viewValue) {
- // If a value is truthy but not an array, reject it.
- // If value is undefined/falsy, accept that it's an empty array.
- return angular.isArray(modelValue || viewValue || []);
- }
- };
-
- var searchStr = '';
- var clearSearchTimeout, optNodes, optText;
- var CLEAR_SEARCH_AFTER = 300;
- self.optNodeForKeyboardSearch = function(e) {
- clearSearchTimeout && clearTimeout(clearSearchTimeout);
- clearSearchTimeout = setTimeout(function() {
- clearSearchTimeout = undefined;
- searchStr = '';
- optText = undefined;
- optNodes = undefined;
- }, CLEAR_SEARCH_AFTER);
- searchStr += String.fromCharCode(e.keyCode);
- var search = new RegExp('^' + searchStr, 'i');
- if (!optNodes) {
- optNodes = $element.find('md-option');
- optText = new Array(optNodes.length);
- angular.forEach(optNodes, function(el, i) {
- optText[i] = el.textContent.trim();
- });
- }
- for (var i = 0; i < optText.length; ++i) {
- if (search.test(optText[i])) {
- return optNodes[i];
- }
- }
- };
-
-
- self.init = function(ngModel) {
- self.ngModel = ngModel;
-
- // Allow users to provide `ng-model="foo" ng-model-options="{trackBy: 'foo.id'}"` so
- // that we can properly compare objects set on the model to the available options
- if (ngModel.$options && ngModel.$options.trackBy) {
- var trackByLocals = {};
- var trackByParsed = $parse(ngModel.$options.trackBy);
- self.hashGetter = function(value, valueScope) {
- trackByLocals.$value = value;
- return trackByParsed(valueScope || $scope, trackByLocals);
- };
- // If the user doesn't provide a trackBy, we automatically generate an id for every
- // value passed in
- } else {
- self.hashGetter = function getHashValue(value) {
- if (angular.isObject(value)) {
- return 'object_' + (value.$$mdSelectId || (value.$$mdSelectId = ++selectNextId));
- }
- return value;
- };
- }
- self.setMultiple(self.isMultiple);
- };
-
- self.selectedLabels = function() {
- var selectedOptionEls = nodesToArray($element[0].querySelectorAll('md-option[selected]'));
- if (selectedOptionEls.length) {
- return selectedOptionEls.map(function(el) { return el.textContent; }).join(', ');
- } else {
- return '';
- }
- };
-
- self.select = function(hashKey, hashedValue) {
- var option = self.options[hashKey];
- option && option.setSelected(true);
- self.selected[hashKey] = hashedValue;
- };
- self.deselect = function(hashKey) {
- var option = self.options[hashKey];
- option && option.setSelected(false);
- delete self.selected[hashKey];
- };
-
- self.addOption = function(hashKey, optionCtrl) {
- if (angular.isDefined(self.options[hashKey])) {
- throw new Error('Duplicate md-option values are not allowed in a select. ' +
- 'Duplicate value "' + optionCtrl.value + '" found.');
- }
- self.options[hashKey] = optionCtrl;
-
- // If this option's value was already in our ngModel, go ahead and select it.
- if (angular.isDefined(self.selected[hashKey])) {
- self.select(hashKey, optionCtrl.value);
- self.refreshViewValue();
- }
- };
- self.removeOption = function(hashKey) {
- delete self.options[hashKey];
- // Don't deselect an option when it's removed - the user's ngModel should be allowed
- // to have values that do not match a currently available option.
- };
-
- self.refreshViewValue = function() {
- var values = [];
- var option;
- for (var hashKey in self.selected) {
- // If this hashKey has an associated option, push that option's value to the model.
- if ((option = self.options[hashKey])) {
- values.push(option.value);
- } else {
- // Otherwise, the given hashKey has no associated option, and we got it
- // from an ngModel value at an earlier time. Push the unhashed value of
- // this hashKey to the model.
- // This allows the developer to put a value in the model that doesn't yet have
- // an associated option.
- values.push(self.selected[hashKey]);
- }
- }
- self.ngModel.$setViewValue(self.isMultiple ? values : values[0]);
- };
-
- function renderMultiple() {
- var newSelectedValues = self.ngModel.$modelValue || self.ngModel.$viewValue;
- if (!angular.isArray(newSelectedValues)) return;
-
- var oldSelected = Object.keys(self.selected);
-
- var newSelectedHashes = newSelectedValues.map(self.hashGetter);
- var deselected = oldSelected.filter(function(hash) {
- return newSelectedHashes.indexOf(hash) === -1;
- });
-
- deselected.forEach(self.deselect);
- newSelectedHashes.forEach(function(hashKey, i) {
- self.select(hashKey, newSelectedValues[i]);
- });
- }
- function renderSingular() {
- var value = self.ngModel.$viewValue || self.ngModel.$modelValue;
- Object.keys(self.selected).forEach(self.deselect);
- self.select( self.hashGetter(value), value );
- }
- }
-
-}
-SelectMenuDirective.$inject = ["$parse", "$mdUtil", "$mdTheming"];
-
-function OptionDirective($mdButtonInkRipple, $mdUtil) {
-
- OptionController.$inject = ["$element"];
- return {
- restrict: 'E',
- require: ['mdOption', '^^mdSelectMenu'],
- controller: OptionController,
- compile: compile
- };
-
- function compile(element, attr) {
- // Manual transclusion to avoid the extra inner <span> that ng-transclude generates
- element.append( angular.element('<div class="md-text">').append(element.contents()) );
-
- element.attr('tabindex', attr.tabindex || '0');
- return postLink;
- }
-
- function postLink(scope, element, attr, ctrls) {
- var optionCtrl = ctrls[0];
- var selectCtrl = ctrls[1];
-
- if (angular.isDefined(attr.ngValue)) {
- scope.$watch(attr.ngValue, setOptionValue);
- } else if (angular.isDefined(attr.value)) {
- setOptionValue(attr.value);
- } else {
- scope.$watch(function() { return element.text(); }, setOptionValue);
- }
-
- scope.$$postDigest(function() {
- attr.$observe('selected', function(selected) {
- if (!angular.isDefined(selected)) return;
- if (selected) {
- if (!selectCtrl.isMultiple) {
- selectCtrl.deselect( Object.keys(selectCtrl.selected)[0] );
- }
- selectCtrl.select(optionCtrl.hashKey, optionCtrl.value);
- } else {
- selectCtrl.deselect(optionCtrl.hashKey);
- }
- selectCtrl.refreshViewValue();
- selectCtrl.ngModel.$render();
- });
- });
-
- $mdButtonInkRipple.attach(scope, element);
- configureAria();
-
- function setOptionValue(newValue, oldValue) {
- var oldHashKey = selectCtrl.hashGetter(oldValue, scope);
- var newHashKey = selectCtrl.hashGetter(newValue, scope);
-
- optionCtrl.hashKey = newHashKey;
- optionCtrl.value = newValue;
-
- selectCtrl.removeOption(oldHashKey, optionCtrl);
- selectCtrl.addOption(newHashKey, optionCtrl);
- }
-
- scope.$on('$destroy', function() {
- selectCtrl.removeOption(optionCtrl.hashKey, optionCtrl);
- });
-
- function configureAria() {
- var ariaAttrs = {
- 'role': 'option',
- 'aria-selected': 'false'
- };
-
- if (!element[0].hasAttribute('id')) {
- ariaAttrs.id = 'select_option_' + $mdUtil.nextUid();
- }
- element.attr(ariaAttrs);
- }
- }
-
- function OptionController($element) {
- this.selected = false;
- this.setSelected = function(isSelected) {
- if (isSelected && !this.selected) {
- $element.attr({
- 'selected': 'selected',
- 'aria-selected': 'true'
- });
- } else if (!isSelected && this.selected) {
- $element.removeAttr('selected');
- $element.attr('aria-selected', 'false');
- }
- this.selected = isSelected;
- };
- }
-
-}
-OptionDirective.$inject = ["$mdButtonInkRipple", "$mdUtil"];
-
-function OptgroupDirective() {
- return {
- restrict: 'E',
- compile: compile
- };
- function compile(el, attrs) {
- var labelElement = el.find('label');
- if (!labelElement.length) {
- labelElement = angular.element('<label>');
- el.prepend(labelElement);
- }
- if (attrs.label) labelElement.text(attrs.label);
- }
-}
-
-function SelectProvider($$interimElementProvider) {
- selectDefaultOptions.$inject = ["$mdSelect", "$mdConstant", "$$rAF", "$mdUtil", "$mdTheming", "$timeout", "$window"];
- return $$interimElementProvider('$mdSelect')
- .setDefaults({
- methods: ['target'],
- options: selectDefaultOptions
- });
-
- /* ngInject */
- function selectDefaultOptions($mdSelect, $mdConstant, $$rAF, $mdUtil, $mdTheming, $timeout, $window ) {
- return {
- parent: 'body',
- onShow: onShow,
- onRemove: onRemove,
- hasBackdrop: true,
- disableParentScroll: true,
- themable: true
- };
-
- function onShow(scope, element, opts) {
- if (!opts.target) {
- throw new Error('$mdSelect.show() expected a target element in options.target but got ' +
- '"' + opts.target + '"!');
- }
-
- angular.extend(opts, {
- isRemoved: false,
- target: angular.element(opts.target), //make sure it's not a naked dom node
- parent: angular.element(opts.parent),
- selectEl: element.find('md-select-menu'),
- contentEl: element.find('md-content'),
- backdrop: opts.hasBackdrop && angular.element('<md-backdrop class="md-select-backdrop md-click-catcher">')
- });
-
- opts.resizeFn = function() {
- $$rAF(function() {
- $$rAF(function() {
- animateSelect(scope, element, opts);
- });
- });
- };
-
- angular.element($window).on('resize', opts.resizeFn);
- angular.element($window).on('orientationchange', opts.resizeFn);
-
-
- configureAria();
-
- element.removeClass('md-leave');
-
- var optionNodes = opts.selectEl[0].getElementsByTagName('md-option');
-
- if (opts.loadingAsync && opts.loadingAsync.then) {
- opts.loadingAsync.then(function() {
- scope.$$loadingAsyncDone = true;
- // Give ourselves two frames for the progress loader to clear out.
- $$rAF(function() {
- $$rAF(function() {
- // Don't go forward if the select has been removed in this time...
- if (opts.isRemoved) return;
- animateSelect(scope, element, opts);
- });
- });
- });
- } else if (opts.loadingAsync) {
- scope.$$loadingAsyncDone = true;
- }
-
- if (opts.disableParentScroll && !$mdUtil.getClosest(opts.target, 'MD-DIALOG')) {
- opts.restoreScroll = $mdUtil.disableScrollAround(opts.target);
- } else {
- opts.disableParentScroll = false;
- }
- // Only activate click listeners after a short time to stop accidental double taps/clicks
- // from clicking the wrong item
- $timeout(activateInteraction, 75, false);
-
- if (opts.backdrop) {
- $mdTheming.inherit(opts.backdrop, opts.parent);
- opts.parent.append(opts.backdrop);
- }
- opts.parent.append(element);
-
- // Give the select a frame to 'initialize' in the DOM,
- // so we can read its height/width/position
- $$rAF(function() {
- $$rAF(function() {
- if (opts.isRemoved) return;
- animateSelect(scope, element, opts);
- });
- });
-
- return $mdUtil.transitionEndPromise(opts.selectEl, {timeout: 350});
-
- function configureAria() {
- opts.target.attr('aria-expanded', 'true');
- }
-
- function activateInteraction() {
- if (opts.isRemoved) return;
- var selectCtrl = opts.selectEl.controller('mdSelectMenu') || {};
- element.addClass('md-clickable');
-
- opts.backdrop && opts.backdrop.on('click', function(e) {
- e.preventDefault();
- e.stopPropagation();
- opts.restoreFocus = false;
- scope.$apply($mdSelect.cancel);
- });
-
- // Escape to close
- opts.selectEl.on('keydown', function(ev) {
- switch (ev.keyCode) {
- case $mdConstant.KEY_CODE.SPACE:
- case $mdConstant.KEY_CODE.ENTER:
- var option = $mdUtil.getClosest(ev.target, 'md-option');
- if (option) {
- opts.selectEl.triggerHandler({
- type: 'click',
- target: option
- });
- ev.preventDefault();
- }
- break;
- case $mdConstant.KEY_CODE.TAB:
- case $mdConstant.KEY_CODE.ESCAPE:
- ev.preventDefault();
- opts.restoreFocus = true;
- scope.$apply($mdSelect.cancel);
- }
- });
-
- // Cycling of options, and closing on enter
- opts.selectEl.on('keydown', function(ev) {
- switch (ev.keyCode) {
- case $mdConstant.KEY_CODE.UP_ARROW: return focusPrevOption();
- case $mdConstant.KEY_CODE.DOWN_ARROW: return focusNextOption();
- default:
- if (ev.keyCode >= 31 && ev.keyCode <= 90) {
- var optNode = opts.selectEl.controller('mdSelectMenu').optNodeForKeyboardSearch(ev);
- optNode && optNode.focus();
- }
- }
- });
-
-
- function focusOption(direction) {
- var optionsArray = nodesToArray(optionNodes);
- var index = optionsArray.indexOf(opts.focusedNode);
- if (index === -1) {
- // We lost the previously focused element, reset to first option
- index = 0;
- } else if (direction === 'next' && index < optionsArray.length - 1) {
- index++;
- } else if (direction === 'prev' && index > 0) {
- index--;
- }
- var newOption = opts.focusedNode = optionsArray[index];
- newOption && newOption.focus();
- }
- function focusNextOption() {
- focusOption('next');
- }
- function focusPrevOption() {
- focusOption('prev');
- }
-
- opts.selectEl.on('click', checkCloseMenu);
- opts.selectEl.on('keydown', function(e) {
- if (e.keyCode == 32 || e.keyCode == 13) {
- checkCloseMenu();
- }
- });
-
- function checkCloseMenu() {
- if (!selectCtrl.isMultiple) {
- opts.restoreFocus = true;
- scope.$evalAsync(function() {
- $mdSelect.hide(selectCtrl.ngModel.$viewValue);
- });
- }
- }
- }
-
- }
-
- function onRemove(scope, element, opts) {
- opts.isRemoved = true;
- element.addClass('md-leave')
- .removeClass('md-clickable');
- opts.target.attr('aria-expanded', 'false');
-
-
- angular.element($window).off('resize', opts.resizeFn);
- angular.element($window).off('orientationchange', opts.resizefn);
- opts.resizeFn = undefined;
-
- var mdSelect = opts.selectEl.controller('mdSelect');
- if (mdSelect) {
- mdSelect.setLabelText(opts.selectEl.controller('mdSelectMenu').selectedLabels());
- }
-
- return $mdUtil.transitionEndPromise(element, { timeout: 350 }).then(function() {
- element.removeClass('md-active');
- opts.backdrop && opts.backdrop.remove();
- if (element[0].parentNode === opts.parent[0]) {
- opts.parent[0].removeChild(element[0]); // use browser to avoid $destroy event
- }
- if (opts.disableParentScroll) {
- opts.restoreScroll();
- }
- if (opts.restoreFocus) opts.target.focus();
- });
- }
-
- function animateSelect(scope, element, opts) {
- var containerNode = element[0],
- targetNode = opts.target[0].firstElementChild.firstElementChild, // target the first span, functioning as the label
- parentNode = opts.parent[0],
- selectNode = opts.selectEl[0],
- contentNode = opts.contentEl[0],
- parentRect = parentNode.getBoundingClientRect(),
- targetRect = targetNode.getBoundingClientRect(),
- shouldOpenAroundTarget = false,
- bounds = {
- left: parentRect.left + SELECT_EDGE_MARGIN,
- top: SELECT_EDGE_MARGIN,
- bottom: parentRect.height - SELECT_EDGE_MARGIN,
- right: parentRect.width - SELECT_EDGE_MARGIN - ($mdUtil.floatingScrollbars() ? 16 : 0)
- },
- spaceAvailable = {
- top: targetRect.top - bounds.top,
- left: targetRect.left - bounds.left,
- right: bounds.right - (targetRect.left + targetRect.width),
- bottom: bounds.bottom - (targetRect.top + targetRect.height)
- },
- maxWidth = parentRect.width - SELECT_EDGE_MARGIN * 2,
- isScrollable = contentNode.scrollHeight > contentNode.offsetHeight,
- selectedNode = selectNode.querySelector('md-option[selected]'),
- optionNodes = selectNode.getElementsByTagName('md-option'),
- optgroupNodes = selectNode.getElementsByTagName('md-optgroup');
-
-
- var centeredNode;
- // If a selected node, center around that
- if (selectedNode) {
- centeredNode = selectedNode;
- // If there are option groups, center around the first option group
- } else if (optgroupNodes.length) {
- centeredNode = optgroupNodes[0];
- // Otherwise, center around the first optionNode
- } else if (optionNodes.length){
- centeredNode = optionNodes[0];
- // In case there are no options, center on whatever's in there... (eg progress indicator)
- } else {
- centeredNode = contentNode.firstElementChild || contentNode;
- }
-
- if (contentNode.offsetWidth > maxWidth) {
- contentNode.style['max-width'] = maxWidth + 'px';
- }
- if (shouldOpenAroundTarget) {
- contentNode.style['min-width'] = targetRect.width + 'px';
- }
-
- // Remove padding before we compute the position of the menu
- if (isScrollable) {
- selectNode.classList.add('md-overflow');
- }
-
- // Get the selectMenuRect *after* max-width is possibly set above
- var selectMenuRect = selectNode.getBoundingClientRect();
- var centeredRect = getOffsetRect(centeredNode);
-
- if (centeredNode) {
- var centeredStyle = $window.getComputedStyle(centeredNode);
- centeredRect.paddingLeft = parseInt(centeredStyle.paddingLeft, 10) || 0;
- centeredRect.paddingRight = parseInt(centeredStyle.paddingRight, 10) || 0;
- }
-
- var focusedNode = centeredNode;
- if ((focusedNode.tagName || '').toUpperCase() === 'MD-OPTGROUP') {
- focusedNode = optionNodes[0] || contentNode.firstElementChild || contentNode;
- }
-
- if (isScrollable) {
- var scrollBuffer = contentNode.offsetHeight / 2;
- contentNode.scrollTop = centeredRect.top + centeredRect.height / 2 - scrollBuffer;
-
- if (spaceAvailable.top < scrollBuffer) {
- contentNode.scrollTop = Math.min(
- centeredRect.top,
- contentNode.scrollTop + scrollBuffer - spaceAvailable.top
- );
- } else if (spaceAvailable.bottom < scrollBuffer) {
- contentNode.scrollTop = Math.max(
- centeredRect.top + centeredRect.height - selectMenuRect.height,
- contentNode.scrollTop - scrollBuffer + spaceAvailable.bottom
- );
- }
- }
-
- var left, top, transformOrigin;
- if (shouldOpenAroundTarget) {
- left = targetRect.left;
- top = targetRect.top + targetRect.height;
- transformOrigin = '50% 0';
- if (top + selectMenuRect.height > bounds.bottom) {
- top = targetRect.top - selectMenuRect.height;
- transformOrigin = '50% 100%';
- }
- } else {
- left = targetRect.left + centeredRect.left - centeredRect.paddingLeft;
- top = Math.floor(targetRect.top + targetRect.height / 2 - centeredRect.height / 2 -
- centeredRect.top + contentNode.scrollTop);
-
-
- transformOrigin = (centeredRect.left + targetRect.width / 2) + 'px ' +
- (centeredRect.top + centeredRect.height / 2 - contentNode.scrollTop) + 'px 0px';
-
- containerNode.style.minWidth = targetRect.width + centeredRect.paddingLeft +
- centeredRect.paddingRight + 'px';
- }
-
- // Keep left and top within the window
- var containerRect = containerNode.getBoundingClientRect();
- containerNode.style.left = clamp(bounds.left, left, bounds.right - containerRect.width) + 'px';
- containerNode.style.top = clamp(bounds.top, top, bounds.bottom - containerRect.height) + 'px';
- selectNode.style[$mdConstant.CSS.TRANSFORM_ORIGIN] = transformOrigin;
-
- selectNode.style[$mdConstant.CSS.TRANSFORM] = 'scale(' +
- Math.min(targetRect.width / selectMenuRect.width, 1.0) + ',' +
- Math.min(targetRect.height / selectMenuRect.height, 1.0) +
- ')';
-
-
- $$rAF(function() {
- element.addClass('md-active');
- selectNode.style[$mdConstant.CSS.TRANSFORM] = '';
- if (focusedNode) {
- opts.focusedNode = focusedNode;
- focusedNode.focus();
- }
- });
- }
-
- }
-
- function clamp(min, n, max) {
- return Math.max(min, Math.min(n, max));
- }
-
- function getOffsetRect(node) {
- return node ? {
- left: node.offsetLeft,
- top: node.offsetTop,
- width: node.offsetWidth,
- height: node.offsetHeight
- } : { left: 0, top: 0, width: 0, height: 0 };
- }
-}
-SelectProvider.$inject = ["$$interimElementProvider"];
-
-// Annoying method to copy nodes to an array, thanks to IE
-function nodesToArray(nodes) {
- var results = [];
- for (var i = 0; i < nodes.length; ++i) {
- results.push(nodes.item(i));
- }
- return results;
-}
-
-})(window, window.angular); \ No newline at end of file