UNPKG

22.3 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms'), require('@angular2-material/core')) :
3 typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/forms', '@angular2-material/core'], factory) :
4 (factory((global.md = global.md || {}, global.md.radio = global.md.radio || {}),global.ng.core,global.ng.forms,global.md.core));
5}(this, (function (exports,_angular_core,_angular_forms,_angular2Material_core) { 'use strict';
6
7var __decorate = (window && window.__decorate) || function (decorators, target, key, desc) {
8 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
9 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
10 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
11 return c > 3 && r && Object.defineProperty(target, key, r), r;
12};
13var __metadata = (window && window.__metadata) || function (k, v) {
14 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
15};
16var __param = (window && window.__param) || function (paramIndex, decorator) {
17 return function (target, key) { decorator(target, key, paramIndex); }
18};
19/**
20 * Provider Expression that allows md-radio-group to register as a ControlValueAccessor. This
21 * allows it to support [(ngModel)] and ngControl.
22 */
23var MD_RADIO_GROUP_CONTROL_VALUE_ACCESSOR = {
24 provide: _angular_forms.NG_VALUE_ACCESSOR,
25 useExisting: _angular_core.forwardRef(function () { return MdRadioGroup; }),
26 multi: true
27};
28// TODO(mtlin):
29// Ink ripple is currently placeholder.
30// Determine motion spec for button transitions.
31// Design review.
32// RTL
33// Support forms API.
34// Use ChangeDetectionStrategy.OnPush
35var _uniqueIdCounter = 0;
36/** A simple change event emitted by either MdRadioButton or MdRadioGroup. */
37var MdRadioChange = (function () {
38 function MdRadioChange() {
39 }
40 return MdRadioChange;
41}());
42var MdRadioGroup = (function () {
43 function MdRadioGroup() {
44 /**
45 * Selected value for group. Should equal the value of the selected radio button if there *is*
46 * a corresponding radio button with a matching value. If there is *not* such a corresponding
47 * radio button, this value persists to be applied in case a new radio button is added with a
48 * matching value.
49 */
50 this._value = null;
51 /** The HTML name attribute applied to radio buttons in this group. */
52 this._name = "md-radio-group-" + _uniqueIdCounter++;
53 /** Disables all individual radio buttons assigned to this group. */
54 this._disabled = false;
55 /** The currently selected radio button. Should match value. */
56 this._selected = null;
57 /** Whether the `value` has been set to its initial value. */
58 this._isInitialized = false;
59 /** The method to be called in order to update ngModel */
60 this._controlValueAccessorChangeFn = function (value) { };
61 /** onTouch function registered via registerOnTouch (ControlValueAccessor). */
62 this.onTouched = function () { };
63 /** Event emitted when the group value changes. */
64 this.change = new _angular_core.EventEmitter();
65 /** Child radio buttons. */
66 this._radios = null;
67 }
68 Object.defineProperty(MdRadioGroup.prototype, "name", {
69 get: function () {
70 return this._name;
71 },
72 set: function (value) {
73 this._name = value;
74 this._updateRadioButtonNames();
75 },
76 enumerable: true,
77 configurable: true
78 });
79 Object.defineProperty(MdRadioGroup.prototype, "disabled", {
80 get: function () {
81 return this._disabled;
82 },
83 set: function (value) {
84 // The presence of *any* disabled value makes the component disabled, *except* for false.
85 this._disabled = (value != null && value !== false) ? true : null;
86 },
87 enumerable: true,
88 configurable: true
89 });
90 Object.defineProperty(MdRadioGroup.prototype, "value", {
91 get: function () {
92 return this._value;
93 },
94 set: function (newValue) {
95 if (this._value != newValue) {
96 // Set this before proceeding to ensure no circular loop occurs with selection.
97 this._value = newValue;
98 this._updateSelectedRadioFromValue();
99 // Only fire a change event if this isn't the first time the value is ever set.
100 if (this._isInitialized) {
101 this._emitChangeEvent();
102 }
103 }
104 },
105 enumerable: true,
106 configurable: true
107 });
108 Object.defineProperty(MdRadioGroup.prototype, "selected", {
109 get: function () {
110 return this._selected;
111 },
112 set: function (selected) {
113 this._selected = selected;
114 this.value = selected ? selected.value : null;
115 if (selected && !selected.checked) {
116 selected.checked = true;
117 }
118 },
119 enumerable: true,
120 configurable: true
121 });
122 /**
123 * Initialize properties once content children are available.
124 * This allows us to propagate relevant attributes to associated buttons.
125 * TODO: internal
126 */
127 MdRadioGroup.prototype.ngAfterContentInit = function () {
128 // Mark this component as initialized in AfterContentInit because the initial value can
129 // possibly be set by NgModel on MdRadioGroup, and it is possible that the OnInit of the
130 // NgModel occurs *after* the OnInit of the MdRadioGroup.
131 this._isInitialized = true;
132 };
133 /**
134 * Mark this group as being "touched" (for ngModel). Meant to be called by the contained
135 * radio buttons upon their blur.
136 */
137 MdRadioGroup.prototype._touch = function () {
138 if (this.onTouched) {
139 this.onTouched();
140 }
141 };
142 MdRadioGroup.prototype._updateRadioButtonNames = function () {
143 var _this = this;
144 if (this._radios) {
145 this._radios.forEach(function (radio) {
146 radio.name = _this.name;
147 });
148 }
149 };
150 /** Updates the `selected` radio button from the internal _value state. */
151 MdRadioGroup.prototype._updateSelectedRadioFromValue = function () {
152 var _this = this;
153 // If the value already matches the selected radio, do nothing.
154 var isAlreadySelected = this._selected != null && this._selected.value == this._value;
155 if (this._radios != null && !isAlreadySelected) {
156 var matchingRadio = this._radios.filter(function (radio) { return radio.value == _this._value; })[0];
157 if (matchingRadio) {
158 this.selected = matchingRadio;
159 }
160 else if (this.value == null) {
161 this.selected = null;
162 this._radios.forEach(function (radio) { radio.checked = false; });
163 }
164 }
165 };
166 /** Dispatch change event with current selection and group value. */
167 MdRadioGroup.prototype._emitChangeEvent = function () {
168 var event = new MdRadioChange();
169 event.source = this._selected;
170 event.value = this._value;
171 this._controlValueAccessorChangeFn(event.value);
172 this.change.emit(event);
173 };
174 /**
175 * Implemented as part of ControlValueAccessor.
176 * TODO: internal
177 */
178 MdRadioGroup.prototype.writeValue = function (value) {
179 this.value = value;
180 };
181 /**
182 * Implemented as part of ControlValueAccessor.
183 * TODO: internal
184 */
185 MdRadioGroup.prototype.registerOnChange = function (fn) {
186 this._controlValueAccessorChangeFn = fn;
187 };
188 /**
189 * Implemented as part of ControlValueAccessor.
190 * TODO: internal
191 */
192 MdRadioGroup.prototype.registerOnTouched = function (fn) {
193 this.onTouched = fn;
194 };
195 __decorate([
196 _angular_core.Output(),
197 __metadata('design:type', _angular_core.EventEmitter)
198 ], MdRadioGroup.prototype, "change", void 0);
199 __decorate([
200 _angular_core.ContentChildren(_angular_core.forwardRef(function () { return MdRadioButton; })),
201 __metadata('design:type', _angular_core.QueryList)
202 ], MdRadioGroup.prototype, "_radios", void 0);
203 __decorate([
204 _angular_core.Input(),
205 __metadata('design:type', String)
206 ], MdRadioGroup.prototype, "name", null);
207 __decorate([
208 _angular_core.Input(),
209 __metadata('design:type', Object)
210 ], MdRadioGroup.prototype, "align", void 0);
211 __decorate([
212 _angular_core.Input(),
213 __metadata('design:type', Boolean)
214 ], MdRadioGroup.prototype, "disabled", null);
215 __decorate([
216 _angular_core.Input(),
217 __metadata('design:type', Object)
218 ], MdRadioGroup.prototype, "value", null);
219 __decorate([
220 _angular_core.Input(),
221 __metadata('design:type', Object)
222 ], MdRadioGroup.prototype, "selected", null);
223 MdRadioGroup = __decorate([
224 _angular_core.Directive({
225 selector: 'md-radio-group',
226 providers: [MD_RADIO_GROUP_CONTROL_VALUE_ACCESSOR],
227 host: {
228 'role': 'radiogroup',
229 },
230 }),
231 __metadata('design:paramtypes', [])
232 ], MdRadioGroup);
233 return MdRadioGroup;
234}());
235var MdRadioButton = (function () {
236 function MdRadioButton(radioGroup, radioDispatcher) {
237 // Assertions. Ideally these should be stripped out by the compiler.
238 // TODO(jelbourn): Assert that there's no name binding AND a parent radio group.
239 var _this = this;
240 this.radioDispatcher = radioDispatcher;
241 /** Whether this radio is checked. */
242 this._checked = false;
243 /** The unique ID for the radio button. */
244 this.id = "md-radio-" + _uniqueIdCounter++;
245 /** Value assigned to this radio.*/
246 this._value = null;
247 /** Event emitted when the group value changes. */
248 this.change = new _angular_core.EventEmitter();
249 this.radioGroup = radioGroup;
250 radioDispatcher.listen(function (id, name) {
251 if (id != _this.id && name == _this.name) {
252 _this.checked = false;
253 }
254 });
255 }
256 Object.defineProperty(MdRadioButton.prototype, "inputId", {
257 get: function () {
258 return this.id + "-input";
259 },
260 enumerable: true,
261 configurable: true
262 });
263 Object.defineProperty(MdRadioButton.prototype, "checked", {
264 get: function () {
265 return this._checked;
266 },
267 set: function (newCheckedState) {
268 if (newCheckedState) {
269 // Notify all radio buttons with the same name to un-check.
270 this.radioDispatcher.notify(this.id, this.name);
271 }
272 this._checked = newCheckedState;
273 if (newCheckedState && this.radioGroup && this.radioGroup.value != this.value) {
274 this.radioGroup.selected = this;
275 }
276 },
277 enumerable: true,
278 configurable: true
279 });
280 Object.defineProperty(MdRadioButton.prototype, "value", {
281 /** MdRadioGroup reads this to assign its own value. */
282 get: function () {
283 return this._value;
284 },
285 set: function (value) {
286 if (this._value != value) {
287 if (this.radioGroup != null && this.checked) {
288 this.radioGroup.value = value;
289 }
290 this._value = value;
291 }
292 },
293 enumerable: true,
294 configurable: true
295 });
296 Object.defineProperty(MdRadioButton.prototype, "align", {
297 get: function () {
298 return this._align || (this.radioGroup != null && this.radioGroup.align) || 'start';
299 },
300 set: function (value) {
301 this._align = value;
302 },
303 enumerable: true,
304 configurable: true
305 });
306 Object.defineProperty(MdRadioButton.prototype, "disabled", {
307 get: function () {
308 return this._disabled || (this.radioGroup != null && this.radioGroup.disabled);
309 },
310 set: function (value) {
311 // The presence of *any* disabled value makes the component disabled, *except* for false.
312 this._disabled = (value != null && value !== false) ? true : null;
313 },
314 enumerable: true,
315 configurable: true
316 });
317 /** TODO: internal */
318 MdRadioButton.prototype.ngOnInit = function () {
319 if (this.radioGroup) {
320 // If the radio is inside a radio group, determine if it should be checked
321 this.checked = this.radioGroup.value === this._value;
322 // Copy name from parent radio group
323 this.name = this.radioGroup.name;
324 }
325 };
326 /** Dispatch change event with current value. */
327 MdRadioButton.prototype._emitChangeEvent = function () {
328 var event = new MdRadioChange();
329 event.source = this;
330 event.value = this._value;
331 this.change.emit(event);
332 };
333 /**
334 * We use a hidden native input field to handle changes to focus state via keyboard navigation,
335 * with visual rendering done separately. The native element is kept in sync with the overall
336 * state of the component.
337 */
338 MdRadioButton.prototype._onInputFocus = function () {
339 this._isFocused = true;
340 };
341 /** TODO: internal */
342 MdRadioButton.prototype._onInputBlur = function () {
343 this._isFocused = false;
344 if (this.radioGroup) {
345 this.radioGroup._touch();
346 }
347 };
348 /** TODO: internal */
349 MdRadioButton.prototype._onInputClick = function (event) {
350 // We have to stop propagation for click events on the visual hidden input element.
351 // By default, when a user clicks on a label element, a generated click event will be
352 // dispatched on the associated input element. Since we are using a label element as our
353 // root container, the click event on the `radio-button` will be executed twice.
354 // The real click event will bubble up, and the generated click event also tries to bubble up.
355 // This will lead to multiple click events.
356 // Preventing bubbling for the second event will solve that issue.
357 event.stopPropagation();
358 };
359 /**
360 * Triggered when the radio button received a click or the input recognized any change.
361 * Clicking on a label element, will trigger a change event on the associated input.
362 * TODO: internal
363 */
364 MdRadioButton.prototype._onInputChange = function (event) {
365 // We always have to stop propagation on the change event.
366 // Otherwise the change event, from the input element, will bubble up and
367 // emit its event object to the `change` output.
368 event.stopPropagation();
369 this.checked = true;
370 this._emitChangeEvent();
371 if (this.radioGroup) {
372 this.radioGroup._touch();
373 }
374 };
375 __decorate([
376 _angular_core.HostBinding('class.md-radio-focused'),
377 __metadata('design:type', Boolean)
378 ], MdRadioButton.prototype, "_isFocused", void 0);
379 __decorate([
380 _angular_core.HostBinding('id'),
381 _angular_core.Input(),
382 __metadata('design:type', String)
383 ], MdRadioButton.prototype, "id", void 0);
384 __decorate([
385 _angular_core.Input(),
386 __metadata('design:type', String)
387 ], MdRadioButton.prototype, "name", void 0);
388 __decorate([
389 _angular_core.Input('aria-label'),
390 __metadata('design:type', String)
391 ], MdRadioButton.prototype, "ariaLabel", void 0);
392 __decorate([
393 _angular_core.Input('aria-labelledby'),
394 __metadata('design:type', String)
395 ], MdRadioButton.prototype, "ariaLabelledby", void 0);
396 __decorate([
397 _angular_core.Output(),
398 __metadata('design:type', _angular_core.EventEmitter)
399 ], MdRadioButton.prototype, "change", void 0);
400 __decorate([
401 _angular_core.HostBinding('class.md-radio-checked'),
402 _angular_core.Input(),
403 __metadata('design:type', Boolean)
404 ], MdRadioButton.prototype, "checked", null);
405 __decorate([
406 _angular_core.Input(),
407 __metadata('design:type', Object)
408 ], MdRadioButton.prototype, "value", null);
409 __decorate([
410 _angular_core.Input(),
411 __metadata('design:type', Object)
412 ], MdRadioButton.prototype, "align", null);
413 __decorate([
414 _angular_core.HostBinding('class.md-radio-disabled'),
415 _angular_core.Input(),
416 __metadata('design:type', Boolean)
417 ], MdRadioButton.prototype, "disabled", null);
418 MdRadioButton = __decorate([
419 _angular_core.Component({selector: 'md-radio-button',
420 template: "<!-- TODO(jelbourn): render the radio on either side of the content --> <!-- TODO(mtlin): Evaluate trade-offs of using native radio vs. cost of additional bindings. --> <label [attr.for]=\"inputId\" class=\"md-radio-label\"> <!-- The actual 'radio' part of the control. --> <div class=\"md-radio-container\"> <div class=\"md-radio-outer-circle\"></div> <div class=\"md-radio-inner-circle\"></div> <div class=\"md-ink-ripple\"></div> </div> <input #input class=\"md-radio-input\" type=\"radio\" [id]=\"inputId\" [checked]=\"checked\" [disabled]=\"disabled\" [name]=\"name\" [attr.aria-label]=\"ariaLabel\" [attr.aria-labelledby]=\"ariaLabelledby\" (change)=\"_onInputChange($event)\" (focus)=\"_onInputFocus()\" (blur)=\"_onInputBlur()\" (click)=\"_onInputClick($event)\"> <!-- The label content for radio control. --> <div class=\"md-radio-label-content\" [class.md-radio-align-end]=\"align == 'end'\"> <ng-content></ng-content> </div> </label> ",
421 styles: ["/** * Mixin that creates a new stacking context. * see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context */ /** * This mixin hides an element visually. * That means it's still accessible for screen-readers but not visible in view. */ /** * Forces an element to grow to fit floated contents; used as as an alternative to * `overflow: hidden;` because it doesn't cut off contents. */ /** * A mixin, which generates temporary ink ripple on a given component. * When $bindToParent is set to true, it will check for the focused class on the same selector as you included * that mixin. * It is also possible to specify the color palette of the temporary ripple. By default it uses the * accent palette for its background. */ md-radio-button { display: inline-block; } .md-radio-label { cursor: pointer; display: inline-flex; align-items: baseline; white-space: nowrap; } .md-radio-container { box-sizing: border-box; display: inline-block; height: 20px; position: relative; width: 20px; top: 2px; } .md-radio-outer-circle { border-color: rgba(0, 0, 0, 0.54); border: solid 2px; border-radius: 50%; box-sizing: border-box; height: 20px; left: 0; position: absolute; top: 0; transition: border-color ease 280ms; width: 20px; } .md-radio-checked .md-radio-outer-circle { border-color: #9c27b0; } .md-radio-disabled .md-radio-outer-circle { border-color: rgba(0, 0, 0, 0.38); } .md-radio-inner-circle { background-color: #9c27b0; border-radius: 50%; box-sizing: border-box; height: 20px; left: 0; position: absolute; top: 0; transition: transform ease 280ms, background-color ease 280ms; transform: scale(0); width: 20px; } .md-radio-checked .md-radio-inner-circle { transform: scale(0.5); } .md-radio-disabled .md-radio-inner-circle { background-color: rgba(0, 0, 0, 0.38); } .md-radio-label-content { display: inline-block; order: 0; line-height: inherit; padding-left: 8px; padding-right: 0; } [dir='rtl'] .md-radio-label-content { padding-right: 8px; padding-left: 0; } .md-radio-label-content.md-radio-align-end { order: -1; padding-left: 0; padding-right: 8px; } [dir='rtl'] .md-radio-label-content.md-radio-align-end { padding-right: 0; padding-left: 8px; } .md-radio-input { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; text-transform: none; width: 1px; } .md-radio-disabled, .md-radio-disabled .md-radio-label { cursor: default; } .md-ink-ripple { border-radius: 50%; opacity: 0; height: 48px; left: 50%; overflow: hidden; pointer-events: none; position: absolute; top: 50%; transform: translate(-50%, -50%); transition: opacity ease 280ms, background-color ease 280ms; width: 48px; } .md-radio-focused .md-ink-ripple { opacity: 1; background-color: rgba(156, 39, 176, 0.26); } .md-radio-disabled .md-ink-ripple { background-color: #000; } /*# sourceMappingURL=radio.css.map */ "],
422 encapsulation: _angular_core.ViewEncapsulation.None
423 }),
424 __param(0, _angular_core.Optional()),
425 __metadata('design:paramtypes', [MdRadioGroup, _angular2Material_core.MdUniqueSelectionDispatcher])
426 ], MdRadioButton);
427 return MdRadioButton;
428}());
429var MdRadioModule = (function () {
430 function MdRadioModule() {
431 }
432 MdRadioModule.forRoot = function () {
433 return {
434 ngModule: MdRadioModule,
435 providers: [_angular2Material_core.MdUniqueSelectionDispatcher],
436 };
437 };
438 MdRadioModule = __decorate([
439 _angular_core.NgModule({
440 exports: [MdRadioGroup, MdRadioButton],
441 declarations: [MdRadioGroup, MdRadioButton],
442 }),
443 __metadata('design:paramtypes', [])
444 ], MdRadioModule);
445 return MdRadioModule;
446}());
447
448exports.MD_RADIO_GROUP_CONTROL_VALUE_ACCESSOR = MD_RADIO_GROUP_CONTROL_VALUE_ACCESSOR;
449exports.MdRadioChange = MdRadioChange;
450exports.MdRadioGroup = MdRadioGroup;
451exports.MdRadioButton = MdRadioButton;
452exports.MdRadioModule = MdRadioModule;
453exports.MdUniqueSelectionDispatcher = _angular2Material_core.MdUniqueSelectionDispatcher;
454
455Object.defineProperty(exports, '__esModule', { value: true });
456
457})));
\No newline at end of file