material_design_lite-sass 1.0.4.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/lib/material_design_lite/sass/engine.rb +2 -1
  4. data/lib/material_design_lite/sass/version.rb +1 -1
  5. data/vendor/assets/images/buffer.svg +9 -0
  6. data/vendor/assets/images/tick-mask.svg +30 -0
  7. data/vendor/assets/images/tick.svg +15 -0
  8. data/vendor/assets/javascripts/material.js +363 -139
  9. data/vendor/assets/javascripts/material/button.js +5 -3
  10. data/vendor/assets/javascripts/material/checkbox.js +14 -6
  11. data/vendor/assets/javascripts/material/data-table.js +23 -19
  12. data/vendor/assets/javascripts/material/icon-toggle.js +16 -6
  13. data/vendor/assets/javascripts/material/layout.js +32 -11
  14. data/vendor/assets/javascripts/material/mdlComponentHandler.js +160 -51
  15. data/vendor/assets/javascripts/material/menu.js +13 -9
  16. data/vendor/assets/javascripts/material/progress.js +10 -5
  17. data/vendor/assets/javascripts/material/rAF.js +19 -7
  18. data/vendor/assets/javascripts/material/radio.js +15 -7
  19. data/vendor/assets/javascripts/material/ripple.js +28 -3
  20. data/vendor/assets/javascripts/material/slider.js +10 -6
  21. data/vendor/assets/javascripts/material/spinner.js +8 -4
  22. data/vendor/assets/javascripts/material/switch.js +14 -5
  23. data/vendor/assets/javascripts/material/tabs.js +11 -3
  24. data/vendor/assets/javascripts/material/textfield.js +19 -6
  25. data/vendor/assets/javascripts/material/tooltip.js +4 -3
  26. data/vendor/assets/stylesheets/_material.scss +0 -0
  27. data/vendor/assets/stylesheets/material/_checkbox.scss +3 -3
  28. data/vendor/assets/stylesheets/material/_layout.scss +2 -2
  29. data/vendor/assets/stylesheets/material/_progress.scss +1 -1
  30. data/vendor/assets/stylesheets/material/_variables.scss +5 -0
  31. metadata +5 -2
@@ -31,12 +31,12 @@
31
31
  // Initialize instance.
32
32
  this.init();
33
33
  };
34
- window.MaterialButton = MaterialButton;
34
+ window['MaterialButton'] = MaterialButton;
35
35
 
36
36
  /**
37
37
  * Store constants in one place so they can be updated easily.
38
38
  *
39
- * @enum {String | Number}
39
+ * @enum {string | number}
40
40
  * @private
41
41
  */
42
42
  MaterialButton.prototype.Constant_ = {
@@ -48,7 +48,7 @@
48
48
  * JavaScript. This allows us to simply change it in one place should we
49
49
  * decide to modify at a later date.
50
50
  *
51
- * @enum {String}
51
+ * @enum {string}
52
52
  * @private
53
53
  */
54
54
  MaterialButton.prototype.CssClasses_ = {
@@ -79,6 +79,7 @@
79
79
  MaterialButton.prototype.disable = function() {
80
80
  this.element_.disabled = true;
81
81
  };
82
+ MaterialButton.prototype['disable'] = MaterialButton.prototype.disable;
82
83
 
83
84
  /**
84
85
  * Enable button.
@@ -88,6 +89,7 @@
88
89
  MaterialButton.prototype.enable = function() {
89
90
  this.element_.disabled = false;
90
91
  };
92
+ MaterialButton.prototype['enable'] = MaterialButton.prototype.enable;
91
93
 
92
94
  /**
93
95
  * Initialize element.
@@ -23,6 +23,7 @@
23
23
  * Implements MDL component design pattern defined at:
24
24
  * https://github.com/jasonmayes/mdl-component-design-pattern
25
25
  *
26
+ * @constructor
26
27
  * @param {HTMLElement} element The element that will be upgraded.
27
28
  */
28
29
  var MaterialCheckbox = function MaterialCheckbox(element) {
@@ -31,12 +32,12 @@
31
32
  // Initialize instance.
32
33
  this.init();
33
34
  };
34
- window.MaterialCheckbox = MaterialCheckbox;
35
+ window['MaterialCheckbox'] = MaterialCheckbox;
35
36
 
36
37
  /**
37
38
  * Store constants in one place so they can be updated easily.
38
39
  *
39
- * @enum {String | Number}
40
+ * @enum {string | number}
40
41
  * @private
41
42
  */
42
43
  MaterialCheckbox.prototype.Constant_ = {
@@ -48,7 +49,7 @@
48
49
  * JavaScript. This allows us to simply change it in one place should we
49
50
  * decide to modify at a later date.
50
51
  *
51
- * @enum {String}
52
+ * @enum {string}
52
53
  * @private
53
54
  */
54
55
  MaterialCheckbox.prototype.CssClasses_ = {
@@ -120,15 +121,14 @@
120
121
  /**
121
122
  * Add blur.
122
123
  *
123
- * @param {Event} event The event that fired.
124
124
  * @private
125
125
  */
126
- MaterialCheckbox.prototype.blur_ = function(event) {
126
+ MaterialCheckbox.prototype.blur_ = function() {
127
127
  // TODO: figure out why there's a focus event being fired after our blur,
128
128
  // so that we can avoid this hack.
129
129
  window.setTimeout(function() {
130
130
  this.inputElement_.blur();
131
- }.bind(this), this.Constant_.TINY_TIMEOUT);
131
+ }.bind(this), /** @type {number} */ (this.Constant_.TINY_TIMEOUT));
132
132
  };
133
133
 
134
134
  // Public methods.
@@ -145,6 +145,8 @@
145
145
  this.element_.classList.remove(this.CssClasses_.IS_CHECKED);
146
146
  }
147
147
  };
148
+ MaterialCheckbox.prototype['checkToggleState'] =
149
+ MaterialCheckbox.prototype.checkToggleState;
148
150
 
149
151
  /**
150
152
  * Check the inputs disabled state and update display.
@@ -158,6 +160,8 @@
158
160
  this.element_.classList.remove(this.CssClasses_.IS_DISABLED);
159
161
  }
160
162
  };
163
+ MaterialCheckbox.prototype['checkDisabled'] =
164
+ MaterialCheckbox.prototype.checkDisabled;
161
165
 
162
166
  /**
163
167
  * Disable checkbox.
@@ -168,6 +172,7 @@
168
172
  this.inputElement_.disabled = true;
169
173
  this.updateClasses_();
170
174
  };
175
+ MaterialCheckbox.prototype['disable'] = MaterialCheckbox.prototype.disable;
171
176
 
172
177
  /**
173
178
  * Enable checkbox.
@@ -178,6 +183,7 @@
178
183
  this.inputElement_.disabled = false;
179
184
  this.updateClasses_();
180
185
  };
186
+ MaterialCheckbox.prototype['enable'] = MaterialCheckbox.prototype.enable;
181
187
 
182
188
  /**
183
189
  * Check checkbox.
@@ -188,6 +194,7 @@
188
194
  this.inputElement_.checked = true;
189
195
  this.updateClasses_();
190
196
  };
197
+ MaterialCheckbox.prototype['check'] = MaterialCheckbox.prototype.check;
191
198
 
192
199
  /**
193
200
  * Uncheck checkbox.
@@ -198,6 +205,7 @@
198
205
  this.inputElement_.checked = false;
199
206
  this.updateClasses_();
200
207
  };
208
+ MaterialCheckbox.prototype['uncheck'] = MaterialCheckbox.prototype.uncheck;
201
209
 
202
210
  /**
203
211
  * Initialize element.
@@ -23,6 +23,7 @@
23
23
  * Implements MDL component design pattern defined at:
24
24
  * https://github.com/jasonmayes/mdl-component-design-pattern
25
25
  *
26
+ * @constructor
26
27
  * @param {HTMLElement} element The element that will be upgraded.
27
28
  */
28
29
  var MaterialDataTable = function MaterialDataTable(element) {
@@ -31,12 +32,13 @@
31
32
  // Initialize instance.
32
33
  this.init();
33
34
  };
34
- window.MaterialDataTable = MaterialDataTable;
35
+
36
+ window['MaterialDataTable'] = MaterialDataTable;
35
37
 
36
38
  /**
37
39
  * Store constants in one place so they can be updated easily.
38
40
  *
39
- * @enum {String | Number}
41
+ * @enum {string | number}
40
42
  * @private
41
43
  */
42
44
  MaterialDataTable.prototype.Constant_ = {
@@ -48,7 +50,7 @@
48
50
  * JavaScript. This allows us to simply change it in one place should we
49
51
  * decide to modify at a later date.
50
52
  *
51
- * @enum {String}
53
+ * @enum {string}
52
54
  * @private
53
55
  */
54
56
  MaterialDataTable.prototype.CssClasses_ = {
@@ -62,12 +64,12 @@
62
64
  * Generates and returns a function that toggles the selection state of a
63
65
  * single row (or multiple rows).
64
66
  *
65
- * @param {HTMLElement} checkbox Checkbox that toggles the selection state.
67
+ * @param {Element} checkbox Checkbox that toggles the selection state.
66
68
  * @param {HTMLElement} row Row to toggle when checkbox changes.
67
- * @param {HTMLElement[]} rows Rows to toggle when checkbox changes.
69
+ * @param {(Array<Object>|NodeList)=} opt_rows Rows to toggle when checkbox changes.
68
70
  * @private
69
71
  */
70
- MaterialDataTable.prototype.selectRow_ = function(checkbox, row, rows) {
72
+ MaterialDataTable.prototype.selectRow_ = function(checkbox, row, opt_rows) {
71
73
  if (row) {
72
74
  return function() {
73
75
  if (checkbox.checked) {
@@ -78,21 +80,21 @@
78
80
  }.bind(this);
79
81
  }
80
82
 
81
- if (rows) {
83
+ if (opt_rows) {
82
84
  return function() {
83
85
  var i;
84
86
  var el;
85
87
  if (checkbox.checked) {
86
- for (i = 0; i < rows.length; i++) {
87
- el = rows[i].querySelector('td').querySelector('.mdl-checkbox');
88
- el.MaterialCheckbox.check();
89
- rows[i].classList.add(this.CssClasses_.IS_SELECTED);
88
+ for (i = 0; i < opt_rows.length; i++) {
89
+ el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox');
90
+ el['MaterialCheckbox'].check();
91
+ opt_rows[i].classList.add(this.CssClasses_.IS_SELECTED);
90
92
  }
91
93
  } else {
92
- for (i = 0; i < rows.length; i++) {
93
- el = rows[i].querySelector('td').querySelector('.mdl-checkbox');
94
- el.MaterialCheckbox.uncheck();
95
- rows[i].classList.remove(this.CssClasses_.IS_SELECTED);
94
+ for (i = 0; i < opt_rows.length; i++) {
95
+ el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox');
96
+ el['MaterialCheckbox'].uncheck();
97
+ opt_rows[i].classList.remove(this.CssClasses_.IS_SELECTED);
96
98
  }
97
99
  }
98
100
  }.bind(this);
@@ -104,10 +106,10 @@
104
106
  * event handling.
105
107
  *
106
108
  * @param {HTMLElement} row Row to toggle when checkbox changes.
107
- * @param {HTMLElement[]} rows Rows to toggle when checkbox changes.
109
+ * @param {(Array<Object>|NodeList)=} opt_rows Rows to toggle when checkbox changes.
108
110
  * @private
109
111
  */
110
- MaterialDataTable.prototype.createCheckbox_ = function(row, rows) {
112
+ MaterialDataTable.prototype.createCheckbox_ = function(row, opt_rows) {
111
113
  var label = document.createElement('label');
112
114
  label.classList.add('mdl-checkbox');
113
115
  label.classList.add('mdl-js-checkbox');
@@ -118,9 +120,11 @@
118
120
  checkbox.classList.add('mdl-checkbox__input');
119
121
  if (row) {
120
122
  checkbox.addEventListener('change', this.selectRow_(checkbox, row));
121
- } else if (rows) {
122
- checkbox.addEventListener('change', this.selectRow_(checkbox, null, rows));
123
+ } else if (opt_rows) {
124
+ checkbox.addEventListener('change',
125
+ this.selectRow_(checkbox, null, opt_rows));
123
126
  }
127
+
124
128
  label.appendChild(checkbox);
125
129
  componentHandler.upgradeElement(label, 'MaterialCheckbox');
126
130
  return label;
@@ -23,6 +23,7 @@
23
23
  * Implements MDL component design pattern defined at:
24
24
  * https://github.com/jasonmayes/mdl-component-design-pattern
25
25
  *
26
+ * @constructor
26
27
  * @param {HTMLElement} element The element that will be upgraded.
27
28
  */
28
29
  var MaterialIconToggle = function MaterialIconToggle(element) {
@@ -31,12 +32,12 @@
31
32
  // Initialize instance.
32
33
  this.init();
33
34
  };
34
- window.MaterialIconToggle = MaterialIconToggle;
35
+ window['MaterialIconToggle'] = MaterialIconToggle;
35
36
 
36
37
  /**
37
38
  * Store constants in one place so they can be updated easily.
38
39
  *
39
- * @enum {String | Number}
40
+ * @enum {string | number}
40
41
  * @private
41
42
  */
42
43
  MaterialIconToggle.prototype.Constant_ = {
@@ -48,7 +49,7 @@
48
49
  * JavaScript. This allows us to simply change it in one place should we
49
50
  * decide to modify at a later date.
50
51
  *
51
- * @enum {String}
52
+ * @enum {string}
52
53
  * @private
53
54
  */
54
55
  MaterialIconToggle.prototype.CssClasses_ = {
@@ -116,15 +117,14 @@
116
117
  /**
117
118
  * Add blur.
118
119
  *
119
- * @param {Event} event The event that fired.
120
120
  * @private
121
121
  */
122
- MaterialIconToggle.prototype.blur_ = function(event) {
122
+ MaterialIconToggle.prototype.blur_ = function() {
123
123
  // TODO: figure out why there's a focus event being fired after our blur,
124
124
  // so that we can avoid this hack.
125
125
  window.setTimeout(function() {
126
126
  this.inputElement_.blur();
127
- }.bind(this), this.Constant_.TINY_TIMEOUT);
127
+ }.bind(this), /** @type {number} */ (this.Constant_.TINY_TIMEOUT));
128
128
  };
129
129
 
130
130
  // Public methods.
@@ -141,6 +141,8 @@
141
141
  this.element_.classList.remove(this.CssClasses_.IS_CHECKED);
142
142
  }
143
143
  };
144
+ MaterialIconToggle.prototype['checkToggleState'] =
145
+ MaterialIconToggle.prototype.checkToggleState;
144
146
 
145
147
  /**
146
148
  * Check the inputs disabled state and update display.
@@ -154,6 +156,8 @@
154
156
  this.element_.classList.remove(this.CssClasses_.IS_DISABLED);
155
157
  }
156
158
  };
159
+ MaterialIconToggle.prototype['checkDisabled'] =
160
+ MaterialIconToggle.prototype.checkDisabled;
157
161
 
158
162
  /**
159
163
  * Disable icon toggle.
@@ -164,6 +168,8 @@
164
168
  this.inputElement_.disabled = true;
165
169
  this.updateClasses_();
166
170
  };
171
+ MaterialIconToggle.prototype['disable'] =
172
+ MaterialIconToggle.prototype.disable;
167
173
 
168
174
  /**
169
175
  * Enable icon toggle.
@@ -174,6 +180,7 @@
174
180
  this.inputElement_.disabled = false;
175
181
  this.updateClasses_();
176
182
  };
183
+ MaterialIconToggle.prototype['enable'] = MaterialIconToggle.prototype.enable;
177
184
 
178
185
  /**
179
186
  * Check icon toggle.
@@ -184,6 +191,7 @@
184
191
  this.inputElement_.checked = true;
185
192
  this.updateClasses_();
186
193
  };
194
+ MaterialIconToggle.prototype['check'] = MaterialIconToggle.prototype.check;
187
195
 
188
196
  /**
189
197
  * Uncheck icon toggle.
@@ -194,6 +202,8 @@
194
202
  this.inputElement_.checked = false;
195
203
  this.updateClasses_();
196
204
  };
205
+ MaterialIconToggle.prototype['uncheck'] =
206
+ MaterialIconToggle.prototype.uncheck;
197
207
 
198
208
  /**
199
209
  * Initialize element.
@@ -23,6 +23,7 @@
23
23
  * Implements MDL component design pattern defined at:
24
24
  * https://github.com/jasonmayes/mdl-component-design-pattern
25
25
  *
26
+ * @constructor
26
27
  * @param {HTMLElement} element The element that will be upgraded.
27
28
  */
28
29
  var MaterialLayout = function MaterialLayout(element) {
@@ -31,12 +32,12 @@
31
32
  // Initialize instance.
32
33
  this.init();
33
34
  };
34
- window.MaterialLayout = MaterialLayout;
35
+ window['MaterialLayout'] = MaterialLayout;
35
36
 
36
37
  /**
37
38
  * Store constants in one place so they can be updated easily.
38
39
  *
39
- * @enum {String | Number}
40
+ * @enum {string | number}
40
41
  * @private
41
42
  */
42
43
  MaterialLayout.prototype.Constant_ = {
@@ -51,7 +52,7 @@
51
52
  /**
52
53
  * Modes.
53
54
  *
54
- * @enum {Number}
55
+ * @enum {number}
55
56
  * @private
56
57
  */
57
58
  MaterialLayout.prototype.Mode_ = {
@@ -66,7 +67,7 @@
66
67
  * JavaScript. This allows us to simply change it in one place should we
67
68
  * decide to modify at a later date.
68
69
  *
69
- * @enum {String}
70
+ * @enum {string}
70
71
  * @private
71
72
  */
72
73
  MaterialLayout.prototype.CssClasses_ = {
@@ -244,7 +245,8 @@
244
245
 
245
246
  // Keep an eye on screen size, and add/remove auxiliary class for styling
246
247
  // of small screens.
247
- this.screenSizeMediaQuery_ = window.matchMedia(this.Constant_.MAX_WIDTH);
248
+ this.screenSizeMediaQuery_ = window.matchMedia(
249
+ /** @type {string} */ (this.Constant_.MAX_WIDTH));
248
250
  this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this));
249
251
  this.screenSizeHandler_();
250
252
 
@@ -284,14 +286,27 @@
284
286
  }
285
287
  }
286
288
 
289
+ /**
290
+ * Prevents an event from triggering the default behaviour.
291
+ * @param {Event} ev the event to eat.
292
+ */
287
293
  var eatEvent = function(ev) {
288
294
  ev.preventDefault();
289
295
  };
290
296
 
291
297
  // Add drawer toggling button to our layout, if we have an openable drawer.
292
298
  if (this.drawer_) {
293
- var drawerButton = document.createElement('div');
294
- drawerButton.classList.add(this.CssClasses_.DRAWER_BTN);
299
+ var drawerButton = this.element_.querySelector('.' +
300
+ this.CssClasses_.DRAWER_BTN);
301
+ if (typeof(drawerButton) === 'undefined' || drawerButton === null) {
302
+ drawerButton = document.createElement('div');
303
+ drawerButton.classList.add(this.CssClasses_.DRAWER_BTN);
304
+
305
+ var drawerButtonIcon = document.createElement('i');
306
+ drawerButtonIcon.classList.add(this.CssClasses_.ICON);
307
+ drawerButtonIcon.textContent = this.Constant_.MENU_ICON;
308
+ drawerButton.appendChild(drawerButtonIcon);
309
+ }
295
310
 
296
311
  if (this.drawer_.classList.contains(this.CssClasses_.ON_LARGE_SCREEN)) {
297
312
  //If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well.
@@ -300,10 +315,7 @@
300
315
  //If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well.
301
316
  drawerButton.classList.add(this.CssClasses_.ON_SMALL_SCREEN);
302
317
  }
303
- var drawerButtonIcon = document.createElement('i');
304
- drawerButtonIcon.classList.add(this.CssClasses_.ICON);
305
- drawerButtonIcon.textContent = this.Constant_.MENU_ICON;
306
- drawerButton.appendChild(drawerButtonIcon);
318
+
307
319
  drawerButton.addEventListener('click',
308
320
  this.drawerToggleHandler_.bind(this));
309
321
 
@@ -402,6 +414,15 @@
402
414
  }
403
415
  };
404
416
 
417
+ /**
418
+ * Constructor for an individual tab.
419
+ *
420
+ * @constructor
421
+ * @param {HTMLElement} tab The HTML element for the tab.
422
+ * @param {!Array<HTMLElement>} tabs Array with HTML elements for all tabs.
423
+ * @param {!Array<HTMLElement>} panels Array with HTML elements for all panels.
424
+ * @param {MaterialLayout} layout The MaterialLayout object that owns the tab.
425
+ */
405
426
  function MaterialLayoutTab(tab, tabs, panels, layout) {
406
427
  if (tab) {
407
428
  if (layout.tabBar_.classList.contains(
@@ -23,7 +23,66 @@
23
23
  * @author Jason Mayes.
24
24
  */
25
25
  /* exported componentHandler */
26
- window.componentHandler = (function() {
26
+
27
+ // Pre-defining the componentHandler interface, for closure documentation and
28
+ // static verification.
29
+ var componentHandler = {
30
+ /**
31
+ * Searches existing DOM for elements of our component type and upgrades them
32
+ * if they have not already been upgraded.
33
+ *
34
+ * @param {string=} optJsClass the programatic name of the element class we
35
+ * need to create a new instance of.
36
+ * @param {string=} optCssClass the name of the CSS class elements of this
37
+ * type will have.
38
+ */
39
+ upgradeDom: function(optJsClass, optCssClass) {},
40
+ /**
41
+ * Upgrades a specific element rather than all in the DOM.
42
+ *
43
+ * @param {!Element} element The element we wish to upgrade.
44
+ * @param {string=} optJsClass Optional name of the class we want to upgrade
45
+ * the element to.
46
+ */
47
+ upgradeElement: function(element, optJsClass) {},
48
+ /**
49
+ * Upgrades a specific list of elements rather than all in the DOM.
50
+ *
51
+ * @param {!Element|!Array<!Element>|!NodeList|!HTMLCollection} elements
52
+ * The elements we wish to upgrade.
53
+ */
54
+ upgradeElements: function(elements) {},
55
+ /**
56
+ * Upgrades all registered components found in the current DOM. This is
57
+ * automatically called on window load.
58
+ */
59
+ upgradeAllRegistered: function() {},
60
+ /**
61
+ * Allows user to be alerted to any upgrades that are performed for a given
62
+ * component type
63
+ *
64
+ * @param {string} jsClass The class name of the MDL component we wish
65
+ * to hook into for any upgrades performed.
66
+ * @param {function(!HTMLElement)} callback The function to call upon an
67
+ * upgrade. This function should expect 1 parameter - the HTMLElement which
68
+ * got upgraded.
69
+ */
70
+ registerUpgradedCallback: function(jsClass, callback) {},
71
+ /**
72
+ * Registers a class for future use and attempts to upgrade existing DOM.
73
+ *
74
+ * @param {componentHandler.ComponentConfigPublic} config the registration configuration
75
+ */
76
+ register: function(config) {},
77
+ /**
78
+ * Downgrade either a given node, an array of nodes, or a NodeList.
79
+ *
80
+ * @param {!Node|!Array<!Node>|!NodeList} nodes
81
+ */
82
+ downgradeElements: function(nodes) {}
83
+ };
84
+
85
+ componentHandler = (function() {
27
86
  'use strict';
28
87
 
29
88
  /** @type {!Array<componentHandler.ComponentConfig>} */
@@ -39,15 +98,15 @@ window.componentHandler = (function() {
39
98
  * Searches registered components for a class we are interested in using.
40
99
  * Optionally replaces a match with passed object if specified.
41
100
  *
42
- * @param {String} name The name of a class we want to use.
101
+ * @param {string} name The name of a class we want to use.
43
102
  * @param {componentHandler.ComponentConfig=} optReplace Optional object to replace match with.
44
- * @return {!Object|Boolean}
103
+ * @return {!Object|boolean}
45
104
  * @private
46
105
  */
47
106
  function findRegisteredClass_(name, optReplace) {
48
107
  for (var i = 0; i < registeredComponents_.length; i++) {
49
108
  if (registeredComponents_[i].className === name) {
50
- if (optReplace !== undefined) {
109
+ if (typeof optReplace !== 'undefined') {
51
110
  registeredComponents_[i] = optReplace;
52
111
  }
53
112
  return registeredComponents_[i];
@@ -59,8 +118,8 @@ window.componentHandler = (function() {
59
118
  /**
60
119
  * Returns an array of the classNames of the upgraded classes on the element.
61
120
  *
62
- * @param {!HTMLElement} element The element to fetch data from.
63
- * @return {!Array<String>}
121
+ * @param {!Element} element The element to fetch data from.
122
+ * @return {!Array<string>}
64
123
  * @private
65
124
  */
66
125
  function getUpgradedListOfElement_(element) {
@@ -73,9 +132,9 @@ window.componentHandler = (function() {
73
132
  * Returns true if the given element has already been upgraded for the given
74
133
  * class.
75
134
  *
76
- * @param {!HTMLElement} element The element we want to check.
77
- * @param {String} jsClass The class to check for.
78
- * @returns {Boolean}
135
+ * @param {!Element} element The element we want to check.
136
+ * @param {string} jsClass The class to check for.
137
+ * @returns {boolean}
79
138
  * @private
80
139
  */
81
140
  function isElementUpgraded_(element, jsClass) {
@@ -87,20 +146,21 @@ window.componentHandler = (function() {
87
146
  * Searches existing DOM for elements of our component type and upgrades them
88
147
  * if they have not already been upgraded.
89
148
  *
90
- * @param {String=} optJsClass the programatic name of the element class we
149
+ * @param {string=} optJsClass the programatic name of the element class we
91
150
  * need to create a new instance of.
92
- * @param {String=} optCssClass the name of the CSS class elements of this
151
+ * @param {string=} optCssClass the name of the CSS class elements of this
93
152
  * type will have.
94
153
  */
95
154
  function upgradeDomInternal(optJsClass, optCssClass) {
96
- if (optJsClass === undefined && optCssClass === undefined) {
155
+ if (typeof optJsClass === 'undefined' &&
156
+ typeof optCssClass === 'undefined') {
97
157
  for (var i = 0; i < registeredComponents_.length; i++) {
98
158
  upgradeDomInternal(registeredComponents_[i].className,
99
159
  registeredComponents_[i].cssClass);
100
160
  }
101
161
  } else {
102
- var jsClass = /** @type {String} */ (optJsClass);
103
- if (optCssClass === undefined) {
162
+ var jsClass = /** @type {string} */ (optJsClass);
163
+ if (typeof optCssClass === 'undefined') {
104
164
  var registeredClass = findRegisteredClass_(jsClass);
105
165
  if (registeredClass) {
106
166
  optCssClass = registeredClass.cssClass;
@@ -117,8 +177,8 @@ window.componentHandler = (function() {
117
177
  /**
118
178
  * Upgrades a specific element rather than all in the DOM.
119
179
  *
120
- * @param {!HTMLElement} element The element we wish to upgrade.
121
- * @param {String=} optJsClass Optional name of the class we want to upgrade
180
+ * @param {!Element} element The element we wish to upgrade.
181
+ * @param {string=} optJsClass Optional name of the class we want to upgrade
122
182
  * the element to.
123
183
  */
124
184
  function upgradeElementInternal(element, optJsClass) {
@@ -177,7 +237,7 @@ window.componentHandler = (function() {
177
237
  /**
178
238
  * Upgrades a specific list of elements rather than all in the DOM.
179
239
  *
180
- * @param {!HTMLElement|!Array<!HTMLElement>|!NodeList|!HTMLCollection} elements
240
+ * @param {!Element|!Array<!Element>|!NodeList|!HTMLCollection} elements
181
241
  * The elements we wish to upgrade.
182
242
  */
183
243
  function upgradeElementsInternal(elements) {
@@ -191,10 +251,10 @@ window.componentHandler = (function() {
191
251
  for (var i = 0, n = elements.length, element; i < n; i++) {
192
252
  element = elements[i];
193
253
  if (element instanceof HTMLElement) {
254
+ upgradeElementInternal(element);
194
255
  if (element.children.length > 0) {
195
256
  upgradeElementsInternal(element.children);
196
257
  }
197
- upgradeElementInternal(element);
198
258
  }
199
259
  }
200
260
  }
@@ -202,20 +262,32 @@ window.componentHandler = (function() {
202
262
  /**
203
263
  * Registers a class for future use and attempts to upgrade existing DOM.
204
264
  *
205
- * @param {{constructor: !Function, classAsString: String, cssClass: String, widget: String}} config
265
+ * @param {componentHandler.ComponentConfigPublic} config
206
266
  */
207
267
  function registerInternal(config) {
268
+ // In order to support both Closure-compiled and uncompiled code accessing
269
+ // this method, we need to allow for both the dot and array syntax for
270
+ // property access. You'll therefore see the `foo.bar || foo['bar']`
271
+ // pattern repeated across this method.
272
+ var widgetMissing = (typeof config.widget === 'undefined' &&
273
+ typeof config['widget'] === 'undefined');
274
+ var widget = true;
275
+
276
+ if (!widgetMissing) {
277
+ widget = config.widget || config['widget'];
278
+ }
279
+
208
280
  var newConfig = /** @type {componentHandler.ComponentConfig} */ ({
209
- 'classConstructor': config.constructor,
210
- 'className': config.classAsString,
211
- 'cssClass': config.cssClass,
212
- 'widget': config.widget === undefined ? true : config.widget,
213
- 'callbacks': []
281
+ classConstructor: config.constructor || config['constructor'],
282
+ className: config.classAsString || config['classAsString'],
283
+ cssClass: config.cssClass || config['cssClass'],
284
+ widget: widget,
285
+ callbacks: []
214
286
  });
215
287
 
216
288
  registeredComponents_.forEach(function(item) {
217
289
  if (item.cssClass === newConfig.cssClass) {
218
- throw new Error('The provided cssClass has already been registered.');
290
+ throw new Error('The provided cssClass has already been registered: ' + item.cssClass);
219
291
  }
220
292
  if (item.className === newConfig.className) {
221
293
  throw new Error('The provided className has already been registered');
@@ -240,7 +312,7 @@ window.componentHandler = (function() {
240
312
  * Allows user to be alerted to any upgrades that are performed for a given
241
313
  * component type
242
314
  *
243
- * @param {String} jsClass The class name of the MDL component we wish
315
+ * @param {string} jsClass The class name of the MDL component we wish
244
316
  * to hook into for any upgrades performed.
245
317
  * @param {function(!HTMLElement)} callback The function to call upon an
246
318
  * upgrade. This function should expect 1 parameter - the HTMLElement which
@@ -312,6 +384,10 @@ window.componentHandler = (function() {
312
384
  * @param {!Node|!Array<!Node>|!NodeList} nodes
313
385
  */
314
386
  function downgradeNodesInternal(nodes) {
387
+ /**
388
+ * Auxiliary function to downgrade a single node.
389
+ * @param {!Node} node the node to be downgraded
390
+ */
315
391
  var downgradeNode = function(node) {
316
392
  deconstructComponentInternal(findCreatedComponentByNodeInternal(node));
317
393
  };
@@ -339,24 +415,18 @@ window.componentHandler = (function() {
339
415
  };
340
416
  })();
341
417
 
342
- window.addEventListener('load', function() {
343
- 'use strict';
344
-
345
- /**
346
- * Performs a "Cutting the mustard" test. If the browser supports the features
347
- * tested, adds a mdl-js class to the <html> element. It then upgrades all MDL
348
- * components requiring JavaScript.
349
- */
350
- if ('classList' in document.createElement('div') &&
351
- 'querySelector' in document &&
352
- 'addEventListener' in window && Array.prototype.forEach) {
353
- document.documentElement.classList.add('mdl-js');
354
- componentHandler.upgradeAllRegistered();
355
- } else {
356
- componentHandler.upgradeElement =
357
- componentHandler.register = function() {};
358
- }
359
- });
418
+ /**
419
+ * Describes the type of a registered component type managed by
420
+ * componentHandler. Provided for benefit of the Closure compiler.
421
+ *
422
+ * @typedef {{
423
+ * constructor: Function,
424
+ * classAsString: string,
425
+ * cssClass: string,
426
+ * widget: (string|boolean|undefined)
427
+ * }}
428
+ */
429
+ componentHandler.ComponentConfigPublic; // jshint ignore:line
360
430
 
361
431
  /**
362
432
  * Describes the type of a registered component type managed by
@@ -364,9 +434,9 @@ window.addEventListener('load', function() {
364
434
  *
365
435
  * @typedef {{
366
436
  * constructor: !Function,
367
- * className: String,
368
- * cssClass: String,
369
- * widget: String,
437
+ * className: string,
438
+ * cssClass: string,
439
+ * widget: (string|boolean),
370
440
  * callbacks: !Array<function(!HTMLElement)>
371
441
  * }}
372
442
  */
@@ -378,10 +448,49 @@ componentHandler.ComponentConfig; // jshint ignore:line
378
448
  *
379
449
  * @typedef {{
380
450
  * element_: !HTMLElement,
381
- * className: String,
382
- * classAsString: String,
383
- * cssClass: String,
384
- * widget: String
451
+ * className: string,
452
+ * classAsString: string,
453
+ * cssClass: string,
454
+ * widget: string
385
455
  * }}
386
456
  */
387
457
  componentHandler.Component; // jshint ignore:line
458
+
459
+ // Export all symbols, for the benefit of Closure compiler.
460
+ // No effect on uncompiled code.
461
+ componentHandler['upgradeDom'] = componentHandler.upgradeDom;
462
+ componentHandler['upgradeElement'] = componentHandler.upgradeElement;
463
+ componentHandler['upgradeElements'] = componentHandler.upgradeElements;
464
+ componentHandler['upgradeAllRegistered'] =
465
+ componentHandler.upgradeAllRegistered;
466
+ componentHandler['registerUpgradedCallback'] =
467
+ componentHandler.registerUpgradedCallback;
468
+ componentHandler['register'] = componentHandler.register;
469
+ componentHandler['downgradeElements'] = componentHandler.downgradeElements;
470
+ window.componentHandler = componentHandler;
471
+ window['componentHandler'] = componentHandler;
472
+
473
+ window.addEventListener('load', function() {
474
+ 'use strict';
475
+
476
+ /**
477
+ * Performs a "Cutting the mustard" test. If the browser supports the features
478
+ * tested, adds a mdl-js class to the <html> element. It then upgrades all MDL
479
+ * components requiring JavaScript.
480
+ */
481
+ if ('classList' in document.createElement('div') &&
482
+ 'querySelector' in document &&
483
+ 'addEventListener' in window && Array.prototype.forEach) {
484
+ document.documentElement.classList.add('mdl-js');
485
+ componentHandler.upgradeAllRegistered();
486
+ } else {
487
+ /**
488
+ * Dummy function to avoid JS errors.
489
+ */
490
+ componentHandler.upgradeElement = function() {};
491
+ /**
492
+ * Dummy function to avoid JS errors.
493
+ */
494
+ componentHandler.register = function() {};
495
+ }
496
+ });