nexus site path corrected
[portal.git] / ecomp-portal-FE / client / bower_components / angular-material / modules / closure / radioButton / radioButton.js
1 /*!
2  * Angular Material Design
3  * https://github.com/angular/material
4  * @license MIT
5  * v0.9.8
6  */
7 goog.provide('ng.material.components.radioButton');
8 goog.require('ng.material.core');
9 /**
10  * @ngdoc module
11  * @name material.components.radioButton
12  * @description radioButton module!
13  */
14 angular.module('material.components.radioButton', [
15   'material.core'
16 ])
17   .directive('mdRadioGroup', mdRadioGroupDirective)
18   .directive('mdRadioButton', mdRadioButtonDirective);
19
20 /**
21  * @ngdoc directive
22  * @module material.components.radioButton
23  * @name mdRadioGroup
24  *
25  * @restrict E
26  *
27  * @description
28  * The `<md-radio-group>` directive identifies a grouping
29  * container for the 1..n grouped radio buttons; specified using nested
30  * `<md-radio-button>` tags.
31  *
32  * As per the [material design spec](http://www.google.com/design/spec/style/color.html#color-ui-color-application)
33  * the radio button is in the accent color by default. The primary color palette may be used with
34  * the `md-primary` class.
35  *
36  * Note: `<md-radio-group>` and `<md-radio-button>` handle tabindex differently
37  * than the native `<input type='radio'>` controls. Whereas the native controls
38  * force the user to tab through all the radio buttons, `<md-radio-group>`
39  * is focusable, and by default the `<md-radio-button>`s are not.
40  *
41  * @param {string} ng-model Assignable angular expression to data-bind to.
42  * @param {boolean=} md-no-ink Use of attribute indicates flag to disable ink ripple effects.
43  *
44  * @usage
45  * <hljs lang="html">
46  * <md-radio-group ng-model="selected">
47  *
48  *   <md-radio-button
49  *        ng-repeat="d in colorOptions"
50  *        ng-value="d.value" aria-label="{{ d.label }}">
51  *
52  *          {{ d.label }}
53  *
54  *   </md-radio-button>
55  *
56  * </md-radio-group>
57  * </hljs>
58  *
59  */
60 function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming, $timeout) {
61   RadioGroupController.prototype = createRadioGroupControllerProto();
62
63   return {
64     restrict: 'E',
65     controller: ['$element', RadioGroupController],
66     require: ['mdRadioGroup', '?ngModel'],
67     link: { pre: linkRadioGroup }
68   };
69
70   function linkRadioGroup(scope, element, attr, ctrls) {
71     $mdTheming(element);
72     var rgCtrl = ctrls[0];
73     var ngModelCtrl = ctrls[1] || $mdUtil.fakeNgModel();
74
75     function setFocus() {
76       if (!element.hasClass('md-focused')) { element.addClass('md-focused'); }
77     }
78
79     function keydownListener(ev) {
80       var keyCode = ev.which || ev.keyCode;
81       switch(keyCode) {
82         case $mdConstant.KEY_CODE.LEFT_ARROW:
83         case $mdConstant.KEY_CODE.UP_ARROW:
84           ev.preventDefault();
85           rgCtrl.selectPrevious();
86           setFocus();
87           break;
88
89         case $mdConstant.KEY_CODE.RIGHT_ARROW:
90         case $mdConstant.KEY_CODE.DOWN_ARROW:
91           ev.preventDefault();
92           rgCtrl.selectNext();
93           setFocus();
94           break;
95
96         case $mdConstant.KEY_CODE.ENTER:
97           var form = angular.element($mdUtil.getClosest(element[0], 'form'));
98           if (form.length > 0) {
99             form.triggerHandler('submit');
100           }
101           break;
102       }
103     }
104
105     rgCtrl.init(ngModelCtrl);
106
107     scope.mouseActive = false;
108     element.attr({
109               'role': 'radiogroup',
110               'tabIndex': element.attr('tabindex') || '0'
111             })
112             .on('keydown', keydownListener)
113             .on('mousedown', function(event) {
114               scope.mouseActive = true;
115               $timeout(function() {
116                 scope.mouseActive = false;
117               }, 100);
118             })
119             .on('focus', function() {
120               if(scope.mouseActive === false) { rgCtrl.$element.addClass('md-focused'); }
121             })
122             .on('blur', function() { rgCtrl.$element.removeClass('md-focused'); });
123   }
124
125   function RadioGroupController($element) {
126     this._radioButtonRenderFns = [];
127     this.$element = $element;
128   }
129
130   function createRadioGroupControllerProto() {
131     return {
132       init: function(ngModelCtrl) {
133         this._ngModelCtrl = ngModelCtrl;
134         this._ngModelCtrl.$render = angular.bind(this, this.render);
135       },
136       add: function(rbRender) {
137         this._radioButtonRenderFns.push(rbRender);
138       },
139       remove: function(rbRender) {
140         var index = this._radioButtonRenderFns.indexOf(rbRender);
141         if (index !== -1) {
142           this._radioButtonRenderFns.splice(index, 1);
143         }
144       },
145       render: function() {
146         this._radioButtonRenderFns.forEach(function(rbRender) {
147           rbRender();
148         });
149       },
150       setViewValue: function(value, eventType) {
151         this._ngModelCtrl.$setViewValue(value, eventType);
152         // update the other radio buttons as well
153         this.render();
154       },
155       getViewValue: function() {
156         return this._ngModelCtrl.$viewValue;
157       },
158       selectNext: function() {
159         return changeSelectedButton(this.$element, 1);
160       },
161       selectPrevious: function() {
162         return changeSelectedButton(this.$element, -1);
163       },
164       setActiveDescendant: function (radioId) {
165         this.$element.attr('aria-activedescendant', radioId);
166       }
167     };
168   }
169   /**
170    * Change the radio group's selected button by a given increment.
171    * If no button is selected, select the first button.
172    */
173   function changeSelectedButton(parent, increment) {
174     // Coerce all child radio buttons into an array, then wrap then in an iterator
175     var buttons = $mdUtil.iterator(parent[0].querySelectorAll('md-radio-button'), true);
176
177     if (buttons.count()) {
178       var validate = function (button) {
179         // If disabled, then NOT valid
180         return !angular.element(button).attr("disabled");
181       };
182       var selected = parent[0].querySelector('md-radio-button.md-checked');
183       var target = buttons[increment < 0 ? 'previous' : 'next'](selected, validate) || buttons.first();
184       // Activate radioButton's click listener (triggerHandler won't create a real click event)
185       angular.element(target).triggerHandler('click');
186
187
188     }
189   }
190
191 }
192 mdRadioGroupDirective.$inject = ["$mdUtil", "$mdConstant", "$mdTheming", "$timeout"];
193
194 /**
195  * @ngdoc directive
196  * @module material.components.radioButton
197  * @name mdRadioButton
198  *
199  * @restrict E
200  *
201  * @description
202  * The `<md-radio-button>`directive is the child directive required to be used within `<md-radio-group>` elements.
203  *
204  * While similar to the `<input type="radio" ng-model="" value="">` directive,
205  * the `<md-radio-button>` directive provides ink effects, ARIA support, and
206  * supports use within named radio groups.
207  *
208  * @param {string} ngModel Assignable angular expression to data-bind to.
209  * @param {string=} ngChange Angular expression to be executed when input changes due to user
210  *    interaction with the input element.
211  * @param {string} ngValue Angular expression which sets the value to which the expression should
212  *    be set when selected.*
213  * @param {string} value The value to which the expression should be set when selected.
214  * @param {string=} name Property name of the form under which the control is published.
215  * @param {string=} aria-label Adds label to radio button for accessibility.
216  * Defaults to radio button's text. If no text content is available, a warning will be logged.
217  *
218  * @usage
219  * <hljs lang="html">
220  *
221  * <md-radio-button value="1" aria-label="Label 1">
222  *   Label 1
223  * </md-radio-button>
224  *
225  * <md-radio-button ng-model="color" ng-value="specialValue" aria-label="Green">
226  *   Green
227  * </md-radio-button>
228  *
229  * </hljs>
230  *
231  */
232 function mdRadioButtonDirective($mdAria, $mdUtil, $mdTheming) {
233
234   var CHECKED_CSS = 'md-checked';
235
236   return {
237     restrict: 'E',
238     require: '^mdRadioGroup',
239     transclude: true,
240     template: '<div class="md-container" md-ink-ripple md-ink-ripple-checkbox>' +
241                 '<div class="md-off"></div>' +
242                 '<div class="md-on"></div>' +
243               '</div>' +
244               '<div ng-transclude class="md-label"></div>',
245     link: link
246   };
247
248   function link(scope, element, attr, rgCtrl) {
249     var lastChecked;
250
251     $mdTheming(element);
252     configureAria(element, scope);
253
254     rgCtrl.add(render);
255     attr.$observe('value', render);
256
257     element
258       .on('click', listener)
259       .on('$destroy', function() {
260         rgCtrl.remove(render);
261       });
262
263     function listener(ev) {
264       if (element[0].hasAttribute('disabled')) return;
265
266       scope.$apply(function() {
267         rgCtrl.setViewValue(attr.value, ev && ev.type);
268       });
269     }
270
271     function render() {
272       var checked = (rgCtrl.getViewValue() == attr.value);
273       if (checked === lastChecked) {
274         return;
275       }
276       lastChecked = checked;
277       element.attr('aria-checked', checked);
278       if (checked) {
279         element.addClass(CHECKED_CSS);
280         rgCtrl.setActiveDescendant(element.attr('id'));
281       } else {
282         element.removeClass(CHECKED_CSS);
283       }
284     }
285     /**
286      * Inject ARIA-specific attributes appropriate for each radio button
287      */
288     function configureAria( element, scope ){
289       scope.ariaId = buildAriaID();
290
291       element.attr({
292         'id' :  scope.ariaId,
293         'role' : 'radio',
294         'aria-checked' : 'false'
295       });
296
297       $mdAria.expectWithText(element, 'aria-label');
298
299       /**
300        * Build a unique ID for each radio button that will be used with aria-activedescendant.
301        * Preserve existing ID if already specified.
302        * @returns {*|string}
303        */
304       function buildAriaID() {
305         return attr.id || ( 'radio' + "_" + $mdUtil.nextUid() );
306       }
307     }
308   }
309 }
310 mdRadioButtonDirective.$inject = ["$mdAria", "$mdUtil", "$mdTheming"];
311
312 ng.material.components.radioButton = angular.module("material.components.radioButton");