material_design_lite-sass 1.0.4.2 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
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
+ });