/*! * Angular Material Design * https://github.com/angular/material * @license MIT * v0.9.8 */ goog.provide('ng.material.components.select'); goog.require('ng.material.components.backdrop'); goog.require('ng.material.core'); /** * @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) * * * {{ opt }} * * * * With an explicit label * * * Select a state * {{ opt }} * * */ 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(''); } else { if (!labelEl[0].firstElementChild) { var spanWrapper = angular.element(''); spanWrapper.append(labelEl.contents()); labelEl.append(spanWrapper); } } labelEl.append(''); 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('').append(element.contents()) ); } // Add progress spinner for md-options-loading if (attr.mdOnOpen) { element.find('md-content').prepend( angular.element('') .attr('md-mode', 'indeterminate') .attr('ng-hide', '$$loadingAsyncDone') .wrap('
') .parent() ); } if (attr.name) { var autofillClone = angular.element('