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