mui-sass 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a6311fabf9aee6114416314af3d7f45f3f8db882
4
- data.tar.gz: f7f5355d6d58313702868d458da1d7ddd73489e1
3
+ metadata.gz: 4da054e1e1cfde1df9e4adf069da1eae58de688d
4
+ data.tar.gz: e8f64e6ed41407ad40c3941c3da3cb4d56baebe2
5
5
  SHA512:
6
- metadata.gz: c68dc366988dc88ddf02d3ca98fd5380e558e2f6239a1e77435d5c28a92200a79128de8d0358e80a9cc800d36b028005e2e84ac1405d1d5fadd64da602fd7d12
7
- data.tar.gz: c3a322b9e49368e34adc2b1e6e60850d06bfa73444bdd842d5d1bd801af38aabf180ba667d3df302c7bfaf734fab1a417f791906238e4cb38b6512cc27afb04b
6
+ metadata.gz: 4ea46ada2caadaef6bacfd946ff35894484e9b142ab51c92877cbe288a40747a6d601383480b6392cb7f00a492f3ec705f9a2d0b82943382ae491a1bf0f32633
7
+ data.tar.gz: 03c5eee3fb22b4959a9b9b872316b6fb924b414b6c8a6bda5853c9ce68836d87b0997b2a39b7191d76d16259f7c70dc994de22b8dfc09919da90333299261eb7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.2.5 (2015-11-28)
2
+
3
+ - Update assets to match upstream version
4
+
5
+ Framework version: MUI v0.2.5
6
+
1
7
  ## 0.2.4 (2015-11-27)
2
8
 
3
9
  - Update assets to match upstream version
@@ -1,5 +1,5 @@
1
1
  module Mui
2
2
  module Sass
3
- VERSION = '0.2.4'
3
+ VERSION = '0.2.5'
4
4
  end
5
5
  end
@@ -1,3 +1,1256 @@
1
+ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ /**
3
+ * MUI config module
4
+ * @module config
5
+ */
6
+
7
+ /** Define module API */
8
+ module.exports = {
9
+ /** Use debug mode */
10
+ debug: true
11
+ };
12
+
13
+ },{}],2:[function(require,module,exports){
14
+ /**
15
+ * MUI CSS/JS dropdown module
16
+ * @module dropdowns
17
+ */
18
+
19
+ 'use strict';
20
+
21
+
22
+ var jqLite = require('./lib/jqLite.js'),
23
+ util = require('./lib/util.js'),
24
+ attrKey = 'data-mui-toggle',
25
+ attrSelector = '[data-mui-toggle="dropdown"]',
26
+ openClass = 'mui--is-open',
27
+ menuClass = 'mui-dropdown__menu';
28
+
29
+
30
+ /**
31
+ * Initialize toggle element.
32
+ * @param {Element} toggleEl - The toggle element.
33
+ */
34
+ function initialize(toggleEl) {
35
+ // check flag
36
+ if (toggleEl._muiDropdown === true) return;
37
+ else toggleEl._muiDropdown = true;
38
+
39
+ // attach click handler
40
+ jqLite.on(toggleEl, 'click', clickHandler);
41
+ }
42
+
43
+
44
+ /**
45
+ * Handle click events on dropdown toggle element.
46
+ * @param {Event} ev - The DOM event
47
+ */
48
+ function clickHandler(ev) {
49
+ // only left clicks
50
+ if (ev.button !== 0) return;
51
+
52
+ var toggleEl = this;
53
+
54
+ // exit if toggle button is disabled
55
+ if (toggleEl.getAttribute('disabled') !== null) return;
56
+
57
+ // prevent form submission
58
+ ev.preventDefault();
59
+ ev.stopPropagation();
60
+
61
+ // toggle dropdown
62
+ toggleDropdown(toggleEl);
63
+ }
64
+
65
+
66
+ /**
67
+ * Toggle the dropdown.
68
+ * @param {Element} toggleEl - The dropdown toggle element.
69
+ */
70
+ function toggleDropdown(toggleEl) {
71
+ var wrapperEl = toggleEl.parentNode,
72
+ menuEl = toggleEl.nextElementSibling,
73
+ doc = wrapperEl.ownerDocument;
74
+
75
+ // exit if no menu element
76
+ if (!menuEl || !jqLite.hasClass(menuEl, menuClass)) {
77
+ return util.raiseError('Dropdown menu element not found');
78
+ }
79
+
80
+ // method to close dropdown
81
+ function closeDropdownFn() {
82
+ jqLite.removeClass(menuEl, openClass);
83
+
84
+ // remove event handlers
85
+ jqLite.off(doc, 'click', closeDropdownFn);
86
+ }
87
+
88
+ // method to open dropdown
89
+ function openDropdownFn() {
90
+ // position menu element below toggle button
91
+ var wrapperRect = wrapperEl.getBoundingClientRect(),
92
+ toggleRect = toggleEl.getBoundingClientRect();
93
+
94
+ var top = toggleRect.top - wrapperRect.top + toggleRect.height;
95
+ jqLite.css(menuEl, 'top', top + 'px');
96
+
97
+ // add open class to wrapper
98
+ jqLite.addClass(menuEl, openClass);
99
+
100
+ // close dropdown when user clicks outside of menu
101
+ jqLite.on(doc, 'click', closeDropdownFn);
102
+ }
103
+
104
+ // toggle dropdown
105
+ if (jqLite.hasClass(menuEl, openClass)) closeDropdownFn();
106
+ else openDropdownFn();
107
+ }
108
+
109
+
110
+ /** Define module API */
111
+ module.exports = {
112
+ /** Initialize module listeners */
113
+ initListeners: function() {
114
+ var doc = document;
115
+
116
+ // markup elements available when method is called
117
+ var elList = doc.querySelectorAll(attrSelector);
118
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
119
+
120
+ // listen for new elements
121
+ util.onNodeInserted(function(el) {
122
+ if (el.getAttribute(attrKey) === 'dropdown') initialize(el);
123
+ });
124
+ }
125
+ };
126
+
127
+ },{"./lib/jqLite.js":5,"./lib/util.js":6}],3:[function(require,module,exports){
128
+ /**
129
+ * MUI CSS/JS select module
130
+ * @module forms/select
131
+ */
132
+
133
+ 'use strict';
134
+
135
+
136
+ var jqLite = require('../lib/jqLite.js'),
137
+ util = require('../lib/util.js'),
138
+ wrapperClass = 'mui-select',
139
+ cssSelector = '.mui-select > select',
140
+ menuClass = 'mui-select__menu',
141
+ wrapperPadding = 15, // from CSS
142
+ inputHeight = 32, // from CSS
143
+ optionHeight = 42, // from CSS
144
+ menuPadding = 8, // from CSS
145
+ doc = document,
146
+ win = window;
147
+
148
+
149
+ /**
150
+ * Initialize select element.
151
+ * @param {Element} selectEl - The select element.
152
+ */
153
+ function initialize(selectEl) {
154
+ // check flag
155
+ if (selectEl._muiSelect === true) return;
156
+ else selectEl._muiSelect = true;
157
+
158
+ // use default behavior on touch devices
159
+ if ('ontouchstart' in doc.documentElement) return;
160
+
161
+ // initialize element
162
+ new Select(selectEl);
163
+ }
164
+
165
+
166
+ /**
167
+ * Creates a new Select object
168
+ * @class
169
+ */
170
+ function Select(selectEl) {
171
+ // instance variables
172
+ this.selectEl = selectEl;
173
+ this.wrapperEl = selectEl.parentNode;
174
+ this.useDefault = false; // currently unused but let's keep just in case
175
+
176
+ // attach event handlers
177
+ jqLite.on(selectEl, 'mousedown', util.callback(this, 'mousedownHandler'));
178
+ jqLite.on(selectEl, 'focus', util.callback(this, 'focusHandler'));
179
+ jqLite.on(selectEl, 'click', util.callback(this, 'clickHandler'));
180
+
181
+ // make wrapper focusable and fix firefox bug
182
+ this.wrapperEl.tabIndex = -1;
183
+ var callbackFn = util.callback(this, 'wrapperFocusHandler');
184
+ jqLite.on(this.wrapperEl, 'focus', callbackFn);
185
+ }
186
+
187
+
188
+ /**
189
+ * Disable default dropdown on mousedown.
190
+ * @param {Event} ev - The DOM event
191
+ */
192
+ Select.prototype.mousedownHandler = function(ev) {
193
+ if (ev.button !== 0 || this.useDefault === true) return;
194
+ ev.preventDefault();
195
+ }
196
+
197
+
198
+ /**
199
+ * Handle focus event on select element.
200
+ * @param {Event} ev - The DOM event
201
+ */
202
+ Select.prototype.focusHandler = function(ev) {
203
+ // check flag
204
+ if (this.useDefault === true) return;
205
+
206
+ var selectEl = this.selectEl,
207
+ wrapperEl = this.wrapperEl,
208
+ origIndex = selectEl.tabIndex,
209
+ keydownFn = util.callback(this, 'keydownHandler');
210
+
211
+ // attach keydown handler
212
+ jqLite.on(doc, 'keydown', keydownFn);
213
+
214
+ // disable tabfocus once
215
+ selectEl.tabIndex = -1;
216
+ jqLite.one(wrapperEl, 'blur', function() {
217
+ selectEl.tabIndex = origIndex;
218
+ jqLite.off(doc, 'keydown', keydownFn);
219
+ });
220
+
221
+ // defer focus to parent
222
+ wrapperEl.focus();
223
+ }
224
+
225
+
226
+ /**
227
+ * Handle keydown events on doc
228
+ **/
229
+ Select.prototype.keydownHandler = function(ev) {
230
+ // spacebar, down, up
231
+ if (ev.keyCode === 32 || ev.keyCode === 38 || ev.keyCode === 40) {
232
+ // prevent win scroll
233
+ ev.preventDefault();
234
+
235
+ if (this.selectEl.disabled !== true) this.renderMenu();
236
+ }
237
+ }
238
+
239
+
240
+ /**
241
+ * Handle focus event on wrapper element.
242
+ */
243
+ Select.prototype.wrapperFocusHandler = function() {
244
+ // firefox bugfix
245
+ if (this.selectEl.disabled) return this.wrapperEl.blur();
246
+ }
247
+
248
+
249
+ /**
250
+ * Handle click events on select element.
251
+ * @param {Event} ev - The DOM event
252
+ */
253
+ Select.prototype.clickHandler = function(ev) {
254
+ // only left clicks
255
+ if (ev.button !== 0) return;
256
+ this.renderMenu();
257
+ }
258
+
259
+
260
+ /**
261
+ * Render options dropdown.
262
+ */
263
+ Select.prototype.renderMenu = function() {
264
+ // check and reset flag
265
+ if (this.useDefault === true) return this.useDefault = false;
266
+
267
+ new Menu(this.wrapperEl, this.selectEl);
268
+ }
269
+
270
+
271
+ /**
272
+ * Creates a new Menu
273
+ * @class
274
+ */
275
+ function Menu(wrapperEl, selectEl) {
276
+ // add scroll lock
277
+ util.enableScrollLock();
278
+
279
+ // instance variables
280
+ this.origIndex = null;
281
+ this.currentIndex = null;
282
+ this.selectEl = selectEl;
283
+ this.menuEl = this._createMenuEl(wrapperEl, selectEl);
284
+ this.clickCallbackFn = util.callback(this, 'clickHandler');
285
+ this.keydownCallbackFn = util.callback(this, 'keydownHandler');
286
+ this.destroyCallbackFn = util.callback(this, 'destroy');
287
+
288
+ // add to DOM
289
+ wrapperEl.appendChild(this.menuEl);
290
+ jqLite.scrollTop(this.menuEl, this.menuEl._muiScrollTop);
291
+
292
+ // blur active element
293
+ setTimeout(function() {
294
+ // ie10 bugfix
295
+ if (doc.activeElement.nodeName.toLowerCase() !== "body") {
296
+ doc.activeElement.blur();
297
+ }
298
+ }, 0);
299
+
300
+ // attach event handlers
301
+ jqLite.on(this.menuEl, 'click', this.clickCallbackFn);
302
+ jqLite.on(doc, 'keydown', this.keydownCallbackFn);
303
+ jqLite.on(win, 'resize', this.destroyCallbackFn);
304
+
305
+ // attach event handler after current event loop exits
306
+ var fn = this.destroyCallbackFn;
307
+ setTimeout(function() {jqLite.on(doc, 'click', fn);}, 0);
308
+ }
309
+
310
+
311
+ /**
312
+ * Create menu element
313
+ * @param {Element} selectEl - The select element
314
+ */
315
+ Menu.prototype._createMenuEl = function(wrapperEl, selectEl) {
316
+ var optionEl, itemEl, i, minTop, maxTop, top;
317
+
318
+ var menuEl = doc.createElement('div'),
319
+ optionList = selectEl.children,
320
+ m = optionList.length,
321
+ selectedPos = 0,
322
+ initTop = (menuPadding + optionHeight) - (wrapperPadding + inputHeight);
323
+
324
+ // create element
325
+ menuEl.className = menuClass;
326
+
327
+ // add options
328
+ for (i=0; i < m; i++) {
329
+ optionEl = optionList[i];
330
+
331
+ itemEl = doc.createElement('div');
332
+ itemEl.textContent = optionEl.textContent;
333
+ itemEl._muiPos = i;
334
+
335
+ if (optionEl.selected) selectedPos = i;
336
+
337
+ menuEl.appendChild(itemEl);
338
+ }
339
+
340
+ // add selected attribute
341
+ menuEl.children[selectedPos].setAttribute('selected', true);
342
+
343
+ // save indices
344
+ this.origIndex = selectedPos;
345
+ this.currentIndex = selectedPos;
346
+
347
+ var viewHeight = doc.documentElement.clientHeight;
348
+
349
+ // set height (use viewport as maximum height)
350
+ var height = m * optionHeight + 2 * menuPadding,
351
+ isOverflow = height > viewHeight;
352
+
353
+ height = Math.min(height, viewHeight);
354
+ jqLite.css(menuEl, 'height', height + 'px');
355
+
356
+ // ideal position
357
+ initTop -= selectedPos * optionHeight;
358
+
359
+ // minimum position
360
+ minTop = -1 * wrapperEl.getBoundingClientRect().top;
361
+
362
+ // maximium position
363
+ maxTop = (viewHeight - height) + minTop;
364
+
365
+ // prevent overflow-y
366
+ top = Math.max(initTop, minTop);
367
+ top = Math.min(top, maxTop);
368
+
369
+ jqLite.css(menuEl, 'top', top + 'px');
370
+
371
+ // set menu scroll position
372
+ if (isOverflow) {
373
+ var scrollIdeal, scrollMax;
374
+
375
+ scrollIdeal = (menuPadding + (selectedPos + 1) * optionHeight) -
376
+ (-1 * top + wrapperPadding + inputHeight);
377
+
378
+ scrollMax = m * optionHeight + 2 * menuPadding - height;
379
+
380
+ menuEl._muiHasOverflow = true;
381
+ menuEl._muiScrollTop = Math.min(scrollIdeal, scrollMax);
382
+ } else {
383
+ menuEl._muiHasOverflow = false;
384
+ menuEl._muiScrollTop = 0;
385
+ }
386
+
387
+ return menuEl;
388
+ }
389
+
390
+
391
+ /**
392
+ * Handle keydown events on doc element.
393
+ * @param {Event} ev - The DOM event
394
+ */
395
+ Menu.prototype.keydownHandler = function(ev) {
396
+ var keyCode = ev.keyCode;
397
+
398
+ // tab
399
+ if (keyCode === 9) return this.destroy();
400
+
401
+ // escape | up | down | enter
402
+ if (keyCode === 27 || keyCode === 40 || keyCode === 38 || keyCode === 13) {
403
+ ev.preventDefault();
404
+ }
405
+
406
+ if (keyCode === 27) {
407
+ this.destroy();
408
+ } else if (keyCode === 40) {
409
+ this.increment();
410
+ } else if (keyCode === 38) {
411
+ this.decrement();
412
+ } else if (keyCode === 13) {
413
+ this.selectCurrent();
414
+ this.destroy();
415
+ }
416
+ }
417
+
418
+
419
+ /**
420
+ * Handle click events on menu element.
421
+ * @param {Event} ev - The DOM event
422
+ */
423
+ Menu.prototype.clickHandler = function(ev) {
424
+ // don't allow events to bubble
425
+ ev.stopPropagation();
426
+
427
+ var pos = ev.target._muiPos;
428
+
429
+ // ignore clicks on non-items
430
+ if (pos === undefined) return;
431
+
432
+ // select option
433
+ this.currentIndex = pos;
434
+ this.selectCurrent();
435
+
436
+ // destroy menu
437
+ this.destroy();
438
+ }
439
+
440
+
441
+ /**
442
+ * Increment selected item
443
+ */
444
+ Menu.prototype.increment = function() {
445
+ if (this.currentIndex === this.menuEl.children.length - 1) return;
446
+
447
+ this.menuEl.children[this.currentIndex].removeAttribute('selected');
448
+ this.currentIndex += 1;
449
+ this.menuEl.children[this.currentIndex].setAttribute('selected', true);
450
+ }
451
+
452
+
453
+ /**
454
+ * Decrement selected item
455
+ */
456
+ Menu.prototype.decrement = function() {
457
+ if (this.currentIndex === 0) return;
458
+
459
+ this.menuEl.children[this.currentIndex].removeAttribute('selected');
460
+ this.currentIndex -= 1;
461
+ this.menuEl.children[this.currentIndex].setAttribute('selected', true);
462
+ }
463
+
464
+
465
+ /**
466
+ * Select current item
467
+ */
468
+ Menu.prototype.selectCurrent = function() {
469
+ if (this.currentIndex !== this.origIndex) {
470
+ this.selectEl.children[this.origIndex].selected = false;
471
+ this.selectEl.children[this.currentIndex].selected = true;
472
+
473
+ // trigger change event
474
+ util.dispatchEvent(this.selectEl, 'change');
475
+ }
476
+ }
477
+
478
+
479
+ /**
480
+ * Destroy menu and detach event handlers
481
+ */
482
+ Menu.prototype.destroy = function() {
483
+ // remove element and focus element
484
+ this.menuEl.parentNode.removeChild(this.menuEl);
485
+ this.selectEl.focus();
486
+
487
+ // remove scroll lock
488
+ util.disableScrollLock();
489
+
490
+ // remove event handlers
491
+ jqLite.off(this.menuEl, 'click', this.clickCallbackFn);
492
+ jqLite.off(doc, 'keydown', this.keydownCallbackFn);
493
+ jqLite.off(doc, 'click', this.destroyCallbackFn);
494
+ jqLite.off(win, 'resize', this.destroyCallbackFn);
495
+ }
496
+
497
+
498
+ /** Define module API */
499
+ module.exports = {
500
+ /** Initialize module listeners */
501
+ initListeners: function() {
502
+ // markup elements available when method is called
503
+ var elList = doc.querySelectorAll(cssSelector);
504
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
505
+
506
+ // listen for new elements
507
+ util.onNodeInserted(function(el) {
508
+ if (el.tagName === 'SELECT' &&
509
+ jqLite.hasClass(el.parentNode, wrapperClass)) {
510
+ initialize(el);
511
+ }
512
+ });
513
+ }
514
+ };
515
+
516
+ },{"../lib/jqLite.js":5,"../lib/util.js":6}],4:[function(require,module,exports){
517
+ /**
518
+ * MUI CSS/JS form-control module
519
+ * @module forms/form-control
520
+ */
521
+
522
+ 'use strict';
523
+
524
+
525
+ var jqLite = require('../lib/jqLite.js'),
526
+ util = require('../lib/util.js'),
527
+ cssSelector = '.mui-textfield > input, .mui-textfield > textarea',
528
+ emptyClass = 'mui--is-empty',
529
+ notEmptyClass = 'mui--is-not-empty',
530
+ dirtyClass = 'mui--is-dirty',
531
+ floatingLabelClass = 'mui-textfield--float-label';
532
+
533
+
534
+ /**
535
+ * Initialize input element.
536
+ * @param {Element} inputEl - The input element.
537
+ */
538
+ function initialize(inputEl) {
539
+ // check flag
540
+ if (inputEl._muiTextfield === true) return;
541
+ else inputEl._muiTextfield = true;
542
+
543
+ if (inputEl.value.length) jqLite.addClass(inputEl, notEmptyClass);
544
+ else jqLite.addClass(inputEl, emptyClass);
545
+
546
+ jqLite.on(inputEl, 'input', inputHandler);
547
+
548
+ // add dirty class on focus
549
+ jqLite.on(inputEl, 'focus', function(){jqLite.addClass(this, dirtyClass);});
550
+ }
551
+
552
+
553
+ /**
554
+ * Handle input events.
555
+ */
556
+ function inputHandler() {
557
+ var inputEl = this;
558
+
559
+ if (inputEl.value.length) {
560
+ jqLite.removeClass(inputEl, emptyClass);
561
+ jqLite.addClass(inputEl, notEmptyClass);
562
+ } else {
563
+ jqLite.removeClass(inputEl, notEmptyClass);
564
+ jqLite.addClass(inputEl, emptyClass)
565
+ }
566
+
567
+ jqLite.addClass(inputEl, dirtyClass);
568
+ }
569
+
570
+
571
+ /** Define module API */
572
+ module.exports = {
573
+ /** Initialize input elements */
574
+ initialize: initialize,
575
+
576
+ /** Initialize module listeners */
577
+ initListeners: function() {
578
+ var doc = document;
579
+
580
+ // markup elements available when method is called
581
+ var elList = doc.querySelectorAll(cssSelector);
582
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
583
+
584
+ // listen for new elements
585
+ util.onNodeInserted(function(el) {
586
+ if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') initialize(el);
587
+ });
588
+
589
+ // add transition css for floating labels
590
+ setTimeout(function() {
591
+ var css = '.mui-textfield.mui-textfield--float-label > label {' + [
592
+ '-webkit-transition',
593
+ '-moz-transition',
594
+ '-o-transition',
595
+ 'transition',
596
+ ''
597
+ ].join(':all .15s ease-out;') + '}';
598
+
599
+ util.loadStyle(css);
600
+ }, 150);
601
+
602
+ // pointer-events shim for floating labels
603
+ if (util.supportsPointerEvents() === false) {
604
+ jqLite.on(document, 'click', function(ev) {
605
+ var targetEl = ev.target;
606
+
607
+ if (targetEl.tagName === 'LABEL' &&
608
+ jqLite.hasClass(targetEl.parentNode, floatingLabelClass)) {
609
+ var inputEl = targetEl.previousElementSibling;
610
+ if (inputEl) inputEl.focus();
611
+ }
612
+ });
613
+ }
614
+ }
615
+ };
616
+
617
+ },{"../lib/jqLite.js":5,"../lib/util.js":6}],5:[function(require,module,exports){
618
+ /**
619
+ * MUI CSS/JS jqLite module
620
+ * @module lib/jqLite
621
+ */
622
+
623
+ 'use strict';
624
+
625
+ // Global vars
626
+ var gDoc = document,
627
+ gDocEl = gDoc.documentElement,
628
+ gWin = window;
629
+
630
+
631
+ /**
632
+ * Add a class to an element.
633
+ * @param {Element} element - The DOM element.
634
+ * @param {string} cssClasses - Space separated list of class names.
635
+ */
636
+ function jqLiteAddClass(element, cssClasses) {
637
+ if (!cssClasses || !element.setAttribute) return;
638
+
639
+ var existingClasses = _getExistingClasses(element),
640
+ splitClasses = cssClasses.split(' '),
641
+ cssClass;
642
+
643
+ for (var i=0; i < splitClasses.length; i++) {
644
+ cssClass = splitClasses[i].trim();
645
+ if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
646
+ existingClasses += cssClass + ' ';
647
+ }
648
+ }
649
+
650
+ element.setAttribute('class', existingClasses.trim());
651
+ }
652
+
653
+
654
+ /**
655
+ * Get or set CSS properties.
656
+ * @param {Element} element - The DOM element.
657
+ * @param {string} [name] - The property name.
658
+ * @param {string} [value] - The property value.
659
+ */
660
+ function jqLiteCss(element, name, value) {
661
+ // Return full style object
662
+ if (name === undefined) {
663
+ return getComputedStyle(element);
664
+ }
665
+
666
+ var nameType = jqLiteType(name);
667
+
668
+ // Set multiple values
669
+ if (nameType === 'object') {
670
+ for (var key in name) element.style[_camelCase(key)] = name[key];
671
+ return;
672
+ }
673
+
674
+ // Set a single value
675
+ if (nameType === 'string' && value !== undefined) {
676
+ element.style[_camelCase(name)] = value;
677
+ }
678
+
679
+ var styleObj = getComputedStyle(element),
680
+ isArray = (jqLiteType(name) === 'array');
681
+
682
+ // Read single value
683
+ if (!isArray) return _getCurrCssProp(element, name, styleObj);
684
+
685
+ // Read multiple values
686
+ var outObj = {},
687
+ key;
688
+
689
+ for (var i=0; i < name.length; i++) {
690
+ key = name[i];
691
+ outObj[key] = _getCurrCssProp(element, key, styleObj);
692
+ }
693
+
694
+ return outObj;
695
+ }
696
+
697
+
698
+ /**
699
+ * Check if element has class.
700
+ * @param {Element} element - The DOM element.
701
+ * @param {string} cls - The class name string.
702
+ */
703
+ function jqLiteHasClass(element, cls) {
704
+ if (!cls || !element.getAttribute) return false;
705
+ return (_getExistingClasses(element).indexOf(' ' + cls + ' ') > -1);
706
+ }
707
+
708
+
709
+ /**
710
+ * Return the type of a variable.
711
+ * @param {} somevar - The JavaScript variable.
712
+ */
713
+ function jqLiteType(somevar) {
714
+ // handle undefined
715
+ if (somevar === undefined) return 'undefined';
716
+
717
+ // handle others (of type [object <Type>])
718
+ var typeStr = Object.prototype.toString.call(somevar);
719
+ if (typeStr.indexOf('[object ') === 0) {
720
+ return typeStr.slice(8, -1).toLowerCase();
721
+ } else {
722
+ throw new Error("MUI: Could not understand type: " + typeStr);
723
+ }
724
+ }
725
+
726
+
727
+ /**
728
+ * Attach an event handler to a DOM element
729
+ * @param {Element} element - The DOM element.
730
+ * @param {string} type - The event type name.
731
+ * @param {Function} callback - The callback function.
732
+ * @param {Boolean} useCapture - Use capture flag.
733
+ */
734
+ function jqLiteOn(element, type, callback, useCapture) {
735
+ useCapture = (useCapture === undefined) ? false : useCapture;
736
+
737
+ // add to DOM
738
+ element.addEventListener(type, callback, useCapture);
739
+
740
+ // add to cache
741
+ var cache = element._muiEventCache = element._muiEventCache || {};
742
+ cache[type] = cache[type] || [];
743
+ cache[type].push([callback, useCapture]);
744
+ }
745
+
746
+
747
+ /**
748
+ * Remove an event handler from a DOM element
749
+ * @param {Element} element - The DOM element.
750
+ * @param {string} type - The event type name.
751
+ * @param {Function} callback - The callback function.
752
+ * @param {Boolean} useCapture - Use capture flag.
753
+ */
754
+ function jqLiteOff(element, type, callback, useCapture) {
755
+ useCapture = (useCapture === undefined) ? false : useCapture;
756
+
757
+ // remove from cache
758
+ var cache = element._muiEventCache = element._muiEventCache || {},
759
+ argsList = cache[type] || [],
760
+ args,
761
+ i;
762
+
763
+ i = argsList.length;
764
+ while (i--) {
765
+ args = argsList[i];
766
+
767
+ // remove all events if callback is undefined
768
+ if (callback === undefined ||
769
+ (args[0] === callback && args[1] === useCapture)) {
770
+
771
+ // remove from cache
772
+ argsList.splice(i, 1);
773
+
774
+ // remove from DOM
775
+ element.removeEventListener(type, args[0], args[1]);
776
+ }
777
+ }
778
+ }
779
+
780
+
781
+ /**
782
+ * Attach an event hander which will only execute once
783
+ * @param {Element} element - The DOM element.
784
+ * @param {string} type - The event type name.
785
+ * @param {Function} callback - The callback function.
786
+ * @param {Boolean} useCapture - Use capture flag.
787
+ */
788
+ function jqLiteOne(element, type, callback, useCapture) {
789
+ jqLiteOn(element, type, function onFn(ev) {
790
+ // execute callback
791
+ if (callback) callback.apply(this, arguments);
792
+
793
+ // remove wrapper
794
+ jqLiteOff(element, type, onFn);
795
+ }, useCapture);
796
+ }
797
+
798
+
799
+ /**
800
+ * Get or set horizontal scroll position
801
+ * @param {Element} element - The DOM element
802
+ * @param {number} [value] - The scroll position
803
+ */
804
+ function jqLiteScrollLeft(element, value) {
805
+ // get
806
+ if (value === undefined) {
807
+ if (element === gWin) {
808
+ var t = (gWin.pageXOffset || gDocEl.scrollLeft)
809
+ return t - (gDocEl.clientLeft || 0);
810
+ } else {
811
+ return element.scrollLeft;
812
+ }
813
+ }
814
+
815
+ // set
816
+ if (element === gWin) gWin.scrollTo(value, jqLiteScrollTop(gWin));
817
+ else element.scrollLeft = value;
818
+ }
819
+
820
+
821
+ /**
822
+ * Get or set vertical scroll position
823
+ * @param {Element} element - The DOM element
824
+ * @param {number} value - The scroll position
825
+ */
826
+ function jqLiteScrollTop(element, value) {
827
+ // get
828
+ if (value === undefined) {
829
+ if (element === gWin) {
830
+ return (gWin.pageYOffset || gDocEl.scrollTop) - (gDocEl.clientTop || 0);
831
+ } else {
832
+ return element.scrollTop;
833
+ }
834
+ }
835
+
836
+ // set
837
+ if (element === gWin) gWin.scrollTo(jqLiteScrollLeft(gWin), value);
838
+ else element.scrollTop = value;
839
+ }
840
+
841
+
842
+ /**
843
+ * Return object representing top/left offset and element height/width.
844
+ * @param {Element} element - The DOM element.
845
+ */
846
+ function jqLiteOffset(element) {
847
+ var rect = element.getBoundingClientRect(),
848
+ scrollTop = jqLiteScrollTop(gWin),
849
+ scrollLeft = jqLiteScrollLeft(gWin);
850
+
851
+ return {
852
+ top: rect.top + scrollTop,
853
+ left: rect.left + scrollLeft,
854
+ height: rect.height,
855
+ width: rect.width
856
+ };
857
+ }
858
+
859
+
860
+ /**
861
+ * Attach a callback to the DOM ready event listener
862
+ * @param {Function} fn - The callback function.
863
+ */
864
+ function jqLiteReady(fn) {
865
+ var done = false,
866
+ top = true,
867
+ doc = document,
868
+ win = doc.defaultView,
869
+ root = doc.documentElement,
870
+ add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
871
+ rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
872
+ pre = doc.addEventListener ? '' : 'on';
873
+
874
+ var init = function(e) {
875
+ if (e.type == 'readystatechange' && doc.readyState != 'complete') {
876
+ return;
877
+ }
878
+
879
+ (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
880
+ if (!done && (done = true)) fn.call(win, e.type || e);
881
+ };
882
+
883
+ var poll = function() {
884
+ try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
885
+ init('poll');
886
+ };
887
+
888
+ if (doc.readyState == 'complete') {
889
+ fn.call(win, 'lazy');
890
+ } else {
891
+ if (doc.createEventObject && root.doScroll) {
892
+ try { top = !win.frameElement; } catch(e) { }
893
+ if (top) poll();
894
+ }
895
+ doc[add](pre + 'DOMContentLoaded', init, false);
896
+ doc[add](pre + 'readystatechange', init, false);
897
+ win[add](pre + 'load', init, false);
898
+ }
899
+ }
900
+
901
+
902
+ /**
903
+ * Remove classes from a DOM element
904
+ * @param {Element} element - The DOM element.
905
+ * @param {string} cssClasses - Space separated list of class names.
906
+ */
907
+ function jqLiteRemoveClass(element, cssClasses) {
908
+ if (!cssClasses || !element.setAttribute) return;
909
+
910
+ var existingClasses = _getExistingClasses(element),
911
+ splitClasses = cssClasses.split(' '),
912
+ cssClass;
913
+
914
+ for (var i=0; i < splitClasses.length; i++) {
915
+ cssClass = splitClasses[i].trim();
916
+ while (existingClasses.indexOf(' ' + cssClass + ' ') >= 0) {
917
+ existingClasses = existingClasses.replace(' ' + cssClass + ' ', ' ');
918
+ }
919
+ }
920
+
921
+ element.setAttribute('class', existingClasses.trim());
922
+ }
923
+
924
+
925
+ // ------------------------------
926
+ // Utilities
927
+ // ------------------------------
928
+ var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g,
929
+ MOZ_HACK_REGEXP = /^moz([A-Z])/,
930
+ ESCAPE_REGEXP = /([.*+?^=!:${}()|\[\]\/\\])/g,
931
+ BOOLEAN_ATTRS;
932
+
933
+
934
+ BOOLEAN_ATTRS = {
935
+ multiple: true,
936
+ selected: true,
937
+ checked: true,
938
+ disabled: true,
939
+ readonly: true,
940
+ required: true,
941
+ open: true
942
+ }
943
+
944
+
945
+ function _getExistingClasses(element) {
946
+ var classes = (element.getAttribute('class') || '').replace(/[\n\t]/g, '');
947
+ return ' ' + classes + ' ';
948
+ }
949
+
950
+
951
+ function _camelCase(name) {
952
+ return name.
953
+ replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
954
+ return offset ? letter.toUpperCase() : letter;
955
+ }).
956
+ replace(MOZ_HACK_REGEXP, 'Moz$1');
957
+ }
958
+
959
+
960
+ function _escapeRegExp(string) {
961
+ return string.replace(ESCAPE_REGEXP, "\\$1");
962
+ }
963
+
964
+
965
+ function _getCurrCssProp(elem, name, computed) {
966
+ var ret;
967
+
968
+ // try computed style
969
+ ret = computed.getPropertyValue(name);
970
+
971
+ // try style attribute (if element is not attached to document)
972
+ if (ret === '' && !elem.ownerDocument) ret = elem.style[_camelCase(name)];
973
+
974
+ return ret;
975
+ }
976
+
977
+
978
+ /**
979
+ * Module API
980
+ */
981
+ module.exports = {
982
+ /** Add classes */
983
+ addClass: jqLiteAddClass,
984
+
985
+ /** Get or set CSS properties */
986
+ css: jqLiteCss,
987
+
988
+ /** Check for class */
989
+ hasClass: jqLiteHasClass,
990
+
991
+ /** Remove event handlers */
992
+ off: jqLiteOff,
993
+
994
+ /** Return offset values */
995
+ offset: jqLiteOffset,
996
+
997
+ /** Add event handlers */
998
+ on: jqLiteOn,
999
+
1000
+ /** Add an execute-once event handler */
1001
+ one: jqLiteOne,
1002
+
1003
+ /** DOM ready event handler */
1004
+ ready: jqLiteReady,
1005
+
1006
+ /** Remove classes */
1007
+ removeClass: jqLiteRemoveClass,
1008
+
1009
+ /** Check JavaScript variable instance type */
1010
+ type: jqLiteType,
1011
+
1012
+ /** Get or set horizontal scroll position */
1013
+ scrollLeft: jqLiteScrollLeft,
1014
+
1015
+ /** Get or set vertical scroll position */
1016
+ scrollTop: jqLiteScrollTop
1017
+ };
1018
+
1019
+ },{}],6:[function(require,module,exports){
1020
+ /**
1021
+ * MUI CSS/JS utilities module
1022
+ * @module lib/util
1023
+ */
1024
+
1025
+ 'use strict';
1026
+
1027
+
1028
+ var config = require('../config.js'),
1029
+ jqLite = require('./jqLite.js'),
1030
+ win = window,
1031
+ doc = document,
1032
+ nodeInsertedCallbacks = [],
1033
+ scrollLock = 0,
1034
+ scrollLockCls = 'mui-body--scroll-lock',
1035
+ scrollLockPos,
1036
+ head,
1037
+ _supportsPointerEvents;
1038
+
1039
+ head = doc.head || doc.getElementsByTagName('head')[0] || doc.documentElement;
1040
+
1041
+
1042
+ /**
1043
+ * Logging function
1044
+ */
1045
+ function logFn() {
1046
+ if (config.debug && typeof win.console !== "undefined") {
1047
+ try {
1048
+ win.console.log.apply(win.console, arguments);
1049
+ } catch (a) {
1050
+ var e = Array.prototype.slice.call(arguments);
1051
+ win.console.log(e.join("\n"));
1052
+ }
1053
+ }
1054
+ }
1055
+
1056
+
1057
+ /**
1058
+ * Load CSS text in new stylesheet
1059
+ * @param {string} cssText - The css text.
1060
+ */
1061
+ function loadStyleFn(cssText) {
1062
+ var e = doc.createElement('style');
1063
+ e.type = 'text/css';
1064
+
1065
+ if (e.styleSheet) e.styleSheet.cssText = cssText;
1066
+ else e.appendChild(doc.createTextNode(cssText));
1067
+
1068
+ // add to document
1069
+ head.insertBefore(e, head.firstChild);
1070
+
1071
+ return e;
1072
+ }
1073
+
1074
+
1075
+ /**
1076
+ * Raise an error
1077
+ * @param {string} msg - The error message.
1078
+ */
1079
+ function raiseErrorFn(msg) {
1080
+ throw new Error("MUI: " + msg);
1081
+ }
1082
+
1083
+
1084
+ /**
1085
+ * Register callbacks on muiNodeInserted event
1086
+ * @param {function} callbackFn - The callback function.
1087
+ */
1088
+ function onNodeInsertedFn(callbackFn) {
1089
+ nodeInsertedCallbacks.push(callbackFn);
1090
+
1091
+ // initalize listeners
1092
+ if (nodeInsertedCallbacks._initialized === undefined) {
1093
+ jqLite.on(doc, 'animationstart', animationHandlerFn);
1094
+ jqLite.on(doc, 'mozAnimationStart', animationHandlerFn);
1095
+ jqLite.on(doc, 'webkitAnimationStart', animationHandlerFn);
1096
+
1097
+ nodeInsertedCallbacks._initialized = true;
1098
+ }
1099
+ }
1100
+
1101
+
1102
+ /**
1103
+ * Execute muiNodeInserted callbacks
1104
+ * @param {Event} ev - The DOM event.
1105
+ */
1106
+ function animationHandlerFn(ev) {
1107
+ // check animation name
1108
+ if (ev.animationName !== 'mui-node-inserted') return;
1109
+
1110
+ var el = ev.target;
1111
+
1112
+ // iterate through callbacks
1113
+ for (var i=nodeInsertedCallbacks.length - 1; i >= 0; i--) {
1114
+ nodeInsertedCallbacks[i](el);
1115
+ }
1116
+ }
1117
+
1118
+
1119
+ /**
1120
+ * Convert Classname object, with class as key and true/false as value, to an
1121
+ * class string.
1122
+ * @param {Object} classes The classes
1123
+ * @return {String} class string
1124
+ */
1125
+ function classNamesFn(classes) {
1126
+ var cs = '';
1127
+ for (var i in classes) {
1128
+ cs += (classes[i]) ? i + ' ' : '';
1129
+ }
1130
+ return cs.trim();
1131
+ }
1132
+
1133
+
1134
+ /**
1135
+ * Check if client supports pointer events.
1136
+ */
1137
+ function supportsPointerEventsFn() {
1138
+ // check cache
1139
+ if (_supportsPointerEvents !== undefined) return _supportsPointerEvents;
1140
+
1141
+ var element = document.createElement('x');
1142
+ element.style.cssText = 'pointer-events:auto';
1143
+ _supportsPointerEvents = (element.style.pointerEvents === 'auto');
1144
+ return _supportsPointerEvents;
1145
+ }
1146
+
1147
+
1148
+ /**
1149
+ * Create callback closure.
1150
+ * @param {Object} instance - The object instance.
1151
+ * @param {String} funcName - The name of the callback function.
1152
+ */
1153
+ function callbackFn(instance, funcName) {
1154
+ return function() {instance[funcName].apply(instance, arguments);};
1155
+ }
1156
+
1157
+
1158
+ /**
1159
+ * Dispatch event.
1160
+ * @param {Element} element - The DOM element.
1161
+ * @param {String} eventType - The event type.
1162
+ * @param {Boolean} bubbles=true - If true, event bubbles.
1163
+ * @param {Boolean} cancelable=true = If true, event is cancelable
1164
+ * @param {Object} [data] - Data to add to event object
1165
+ */
1166
+ function dispatchEventFn(element, eventType, bubbles, cancelable, data) {
1167
+ var ev = document.createEvent('HTMLEvents'),
1168
+ bubbles = (bubbles !== undefined) ? bubbles : true,
1169
+ cancelable = (cancelable !== undefined) ? cancelable : true,
1170
+ k;
1171
+
1172
+ ev.initEvent(eventType, bubbles, cancelable);
1173
+
1174
+ // add data to event object
1175
+ if (data) for (k in data) ev[k] = data[k];
1176
+
1177
+ // dispatch
1178
+ if (element) element.dispatchEvent(ev);
1179
+
1180
+ return ev;
1181
+ }
1182
+
1183
+
1184
+ /**
1185
+ * Turn on window scroll lock.
1186
+ */
1187
+ function enableScrollLockFn() {
1188
+ // increment counter
1189
+ scrollLock += 1
1190
+
1191
+ // add lock
1192
+ if (scrollLock === 1) {
1193
+ scrollLockPos = {left: jqLite.scrollLeft(win), top: jqLite.scrollTop(win)};
1194
+ jqLite.addClass(doc.body, scrollLockCls);
1195
+ win.scrollTo(scrollLockPos.left, scrollLockPos.top);
1196
+ }
1197
+ }
1198
+
1199
+
1200
+ /**
1201
+ * Turn off window scroll lock.
1202
+ */
1203
+ function disableScrollLockFn() {
1204
+ // ignore
1205
+ if (scrollLock === 0) return;
1206
+
1207
+ // decrement counter
1208
+ scrollLock -= 1
1209
+
1210
+ // remove lock
1211
+ if (scrollLock === 0) {
1212
+ jqLite.removeClass(doc.body, scrollLockCls);
1213
+ win.scrollTo(scrollLockPos.left, scrollLockPos.top);
1214
+ }
1215
+ }
1216
+
1217
+
1218
+ /**
1219
+ * Define the module API
1220
+ */
1221
+ module.exports = {
1222
+ /** Create callback closures */
1223
+ callback: callbackFn,
1224
+
1225
+ /** Classnames object to string */
1226
+ classNames: classNamesFn,
1227
+
1228
+ /** Disable scroll lock */
1229
+ disableScrollLock: disableScrollLockFn,
1230
+
1231
+ /** Dispatch event */
1232
+ dispatchEvent: dispatchEventFn,
1233
+
1234
+ /** Enable scroll lock */
1235
+ enableScrollLock: enableScrollLockFn,
1236
+
1237
+ /** Log messages to the console when debug is turned on */
1238
+ log: logFn,
1239
+
1240
+ /** Load CSS text as new stylesheet */
1241
+ loadStyle: loadStyleFn,
1242
+
1243
+ /** Register muiNodeInserted handler */
1244
+ onNodeInserted: onNodeInsertedFn,
1245
+
1246
+ /** Raise MUI error */
1247
+ raiseError: raiseErrorFn,
1248
+
1249
+ /** Support Pointer Events check */
1250
+ supportsPointerEvents: supportsPointerEventsFn
1251
+ };
1252
+
1253
+ },{"../config.js":1,"./jqLite.js":5}],7:[function(require,module,exports){
1
1254
  /**
2
1255
  * MUI CSS/JS main module
3
1256
  * @module main
@@ -35,3 +1288,463 @@
35
1288
  tabs.initListeners();
36
1289
  });
37
1290
  })(window);
1291
+
1292
+ },{"./dropdowns.js":2,"./forms/select.js":3,"./forms/textfield.js":4,"./lib/jqLite.js":5,"./lib/util.js":6,"./overlay.js":8,"./ripple.js":9,"./tabs.js":10}],8:[function(require,module,exports){
1293
+ /**
1294
+ * MUI CSS/JS overlay module
1295
+ * @module overlay
1296
+ */
1297
+
1298
+ 'use strict';
1299
+
1300
+
1301
+ var util = require('./lib/util.js'),
1302
+ jqLite = require('./lib/jqLite.js'),
1303
+ overlayId = 'mui-overlay',
1304
+ bodyClass = 'mui--overflow-hidden',
1305
+ iosRegex = /(iPad|iPhone|iPod)/g;
1306
+
1307
+
1308
+ /**
1309
+ * Turn overlay on/off.
1310
+ * @param {string} action - Turn overlay "on"/"off".
1311
+ * @param {object} [options]
1312
+ * @config {boolean} [keyboard] - If true, close when escape key is pressed.
1313
+ * @config {boolean} [static] - If false, close when backdrop is clicked.
1314
+ * @config {Function} [onclose] - Callback function to execute on close
1315
+ * @param {Element} [childElement] - Child element to add to overlay.
1316
+ */
1317
+ function overlayFn(action) {
1318
+ var overlayEl;
1319
+
1320
+ if (action === 'on') {
1321
+ // extract arguments
1322
+ var arg, options, childElement;
1323
+
1324
+ // pull options and childElement from arguments
1325
+ for (var i=arguments.length - 1; i > 0; i--) {
1326
+ arg = arguments[i];
1327
+
1328
+ if (jqLite.type(arg) === 'object') options = arg;
1329
+ if (arg instanceof Element && arg.nodeType === 1) childElement = arg;
1330
+ }
1331
+
1332
+ // option defaults
1333
+ options = options || {};
1334
+ if (options.keyboard === undefined) options.keyboard = true;
1335
+ if (options.static === undefined) options.static = false;
1336
+
1337
+ // execute method
1338
+ overlayEl = overlayOn(options, childElement);
1339
+
1340
+ } else if (action === 'off') {
1341
+ overlayEl = overlayOff();
1342
+
1343
+ } else {
1344
+ // raise error
1345
+ util.raiseError("Expecting 'on' or 'off'");
1346
+ }
1347
+
1348
+ return overlayEl;
1349
+ }
1350
+
1351
+
1352
+ /**
1353
+ * Turn on overlay.
1354
+ * @param {object} options - Overlay options.
1355
+ * @param {Element} childElement - The child element.
1356
+ */
1357
+ function overlayOn(options, childElement) {
1358
+ var bodyEl = document.body,
1359
+ overlayEl = document.getElementById(overlayId);
1360
+
1361
+ // add overlay
1362
+ util.enableScrollLock();
1363
+ //jqLite.addClass(bodyEl, bodyClass);
1364
+
1365
+ if (!overlayEl) {
1366
+ // create overlayEl
1367
+ overlayEl = document.createElement('div');
1368
+ overlayEl.setAttribute('id', overlayId);
1369
+
1370
+ // add child element
1371
+ if (childElement) overlayEl.appendChild(childElement);
1372
+
1373
+ bodyEl.appendChild(overlayEl);
1374
+
1375
+ } else {
1376
+ // remove existing children
1377
+ while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild);
1378
+
1379
+ // add child element
1380
+ if (childElement) overlayEl.appendChild(childElement);
1381
+ }
1382
+
1383
+ // iOS bugfix
1384
+ if (iosRegex.test(navigator.userAgent)) {
1385
+ jqLite.css(overlayEl, 'cursor', 'pointer');
1386
+ }
1387
+
1388
+ // handle options
1389
+ if (options.keyboard) addKeyupHandler();
1390
+ else removeKeyupHandler();
1391
+
1392
+ if (options.static) removeClickHandler(overlayEl);
1393
+ else addClickHandler(overlayEl);
1394
+
1395
+ // attach options
1396
+ overlayEl.muiOptions = options;
1397
+
1398
+ return overlayEl;
1399
+ }
1400
+
1401
+
1402
+ /**
1403
+ * Turn off overlay.
1404
+ */
1405
+ function overlayOff() {
1406
+ var overlayEl = document.getElementById(overlayId),
1407
+ callbackFn;
1408
+
1409
+ if (overlayEl) {
1410
+ // remove children
1411
+ while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild);
1412
+
1413
+ // remove overlay element
1414
+ overlayEl.parentNode.removeChild(overlayEl);
1415
+
1416
+ // callback reference
1417
+ callbackFn = overlayEl.muiOptions.onclose;
1418
+ }
1419
+
1420
+ util.disableScrollLock();
1421
+
1422
+ // remove option handlers
1423
+ removeKeyupHandler();
1424
+ removeClickHandler(overlayEl);
1425
+
1426
+ // execute callback
1427
+ if (callbackFn) callbackFn();
1428
+
1429
+ return overlayEl;
1430
+ }
1431
+
1432
+
1433
+ /**
1434
+ * Add keyup handler.
1435
+ */
1436
+ function addKeyupHandler() {
1437
+ jqLite.on(document, 'keyup', onKeyup);
1438
+ }
1439
+
1440
+
1441
+ /**
1442
+ * Remove keyup handler.
1443
+ */
1444
+ function removeKeyupHandler() {
1445
+ jqLite.off(document, 'keyup', onKeyup);
1446
+ }
1447
+
1448
+
1449
+ /**
1450
+ * Teardown overlay when escape key is pressed.
1451
+ */
1452
+ function onKeyup(ev) {
1453
+ if (ev.keyCode === 27) overlayOff();
1454
+ }
1455
+
1456
+
1457
+ /**
1458
+ * Add click handler.
1459
+ */
1460
+ function addClickHandler(overlayEl) {
1461
+ jqLite.on(overlayEl, 'click', onClick);
1462
+ }
1463
+
1464
+
1465
+ /**
1466
+ * Remove click handler.
1467
+ */
1468
+ function removeClickHandler(overlayEl) {
1469
+ jqLite.off(overlayEl, 'click', onClick);
1470
+ }
1471
+
1472
+
1473
+ /**
1474
+ * Teardown overlay when backdrop is clicked.
1475
+ */
1476
+ function onClick(ev) {
1477
+ if (ev.target.id === overlayId) overlayOff();
1478
+ }
1479
+
1480
+
1481
+ /** Define module API */
1482
+ module.exports = overlayFn;
1483
+
1484
+ },{"./lib/jqLite.js":5,"./lib/util.js":6}],9:[function(require,module,exports){
1485
+ /**
1486
+ * MUI CSS/JS ripple module
1487
+ * @module ripple
1488
+ */
1489
+
1490
+ 'use strict';
1491
+
1492
+
1493
+ var jqLite = require('./lib/jqLite.js'),
1494
+ util = require('./lib/util.js'),
1495
+ btnClass = 'mui-btn',
1496
+ btnFABClass = 'mui-btn--fab',
1497
+ rippleClass = 'mui-ripple-effect',
1498
+ animationName = 'mui-btn-inserted';
1499
+
1500
+
1501
+ /**
1502
+ * Add ripple effects to button element.
1503
+ * @param {Element} buttonEl - The button element.
1504
+ */
1505
+ function initialize(buttonEl) {
1506
+ // check flag
1507
+ if (buttonEl._muiRipple === true) return;
1508
+ else buttonEl._muiRipple = true;
1509
+
1510
+ // exit if element is INPUT (doesn't support absolute positioned children)
1511
+ if (buttonEl.tagName === 'INPUT') return;
1512
+
1513
+ // attach event handler
1514
+ jqLite.on(buttonEl, 'touchstart', eventHandler);
1515
+ jqLite.on(buttonEl, 'mousedown', eventHandler);
1516
+ }
1517
+
1518
+
1519
+ /**
1520
+ * Event handler
1521
+ * @param {Event} ev - The DOM event
1522
+ */
1523
+ function eventHandler(ev) {
1524
+ // only left clicks
1525
+ if (ev.button !== 0) return;
1526
+
1527
+ var buttonEl = this;
1528
+
1529
+ // exit if button is disabled
1530
+ if (buttonEl.disabled === true) return;
1531
+
1532
+ // de-dupe touchstart and mousedown with 100msec flag
1533
+ if (buttonEl.touchFlag === true) {
1534
+ return;
1535
+ } else {
1536
+ buttonEl.touchFlag = true;
1537
+ setTimeout(function() {
1538
+ buttonEl.touchFlag = false;
1539
+ }, 100);
1540
+ }
1541
+
1542
+ var rippleEl = document.createElement('div');
1543
+ rippleEl.className = rippleClass;
1544
+
1545
+ var offset = jqLite.offset(buttonEl),
1546
+ xPos = ev.pageX - offset.left,
1547
+ yPos = ev.pageY - offset.top,
1548
+ diameter,
1549
+ radius;
1550
+
1551
+ // get height
1552
+ if (jqLite.hasClass(buttonEl, btnFABClass)) diameter = offset.height / 2;
1553
+ else diameter = offset.height;
1554
+
1555
+ radius = diameter / 2;
1556
+
1557
+ jqLite.css(rippleEl, {
1558
+ height: diameter + 'px',
1559
+ width: diameter + 'px',
1560
+ top: yPos - radius + 'px',
1561
+ left: xPos - radius + 'px'
1562
+ });
1563
+
1564
+ buttonEl.appendChild(rippleEl);
1565
+
1566
+ window.setTimeout(function() {
1567
+ buttonEl.removeChild(rippleEl);
1568
+ }, 2000);
1569
+ }
1570
+
1571
+
1572
+ /** Define module API */
1573
+ module.exports = {
1574
+ /** Initialize module listeners */
1575
+ initListeners: function() {
1576
+ var doc = document;
1577
+
1578
+ // markup elements available when method is called
1579
+ var elList = doc.getElementsByClassName(btnClass);
1580
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
1581
+
1582
+ // listen for new elements
1583
+ util.onNodeInserted(function(el) {
1584
+ if (jqLite.hasClass(el, btnClass)) initialize(el);
1585
+ });
1586
+ }
1587
+ };
1588
+
1589
+ },{"./lib/jqLite.js":5,"./lib/util.js":6}],10:[function(require,module,exports){
1590
+ /**
1591
+ * MUI CSS/JS tabs module
1592
+ * @module tabs
1593
+ */
1594
+
1595
+ 'use strict';
1596
+
1597
+
1598
+ var jqLite = require('./lib/jqLite.js'),
1599
+ util = require('./lib/util.js'),
1600
+ attrKey = 'data-mui-toggle',
1601
+ attrSelector = '[' + attrKey + '="tab"]',
1602
+ controlsAttrKey = 'data-mui-controls',
1603
+ activeClass = 'mui--is-active',
1604
+ showstartKey = 'mui.tabs.showstart',
1605
+ showendKey = 'mui.tabs.showend',
1606
+ hidestartKey = 'mui.tabs.hidestart',
1607
+ hideendKey = 'mui.tabs.hideend';
1608
+
1609
+
1610
+ /**
1611
+ * Initialize the toggle element
1612
+ * @param {Element} toggleEl - The toggle element.
1613
+ */
1614
+ function initialize(toggleEl) {
1615
+ // check flag
1616
+ if (toggleEl._muiTabs === true) return;
1617
+ else toggleEl._muiTabs = true;
1618
+
1619
+ // attach click handler
1620
+ jqLite.on(toggleEl, 'click', clickHandler);
1621
+ }
1622
+
1623
+
1624
+ /**
1625
+ * Handle clicks on the toggle element.
1626
+ * @param {Event} ev - The DOM event.
1627
+ */
1628
+ function clickHandler(ev) {
1629
+ // only left clicks
1630
+ if (ev.button !== 0) return;
1631
+
1632
+ var toggleEl = this;
1633
+
1634
+ // exit if toggle element is disabled
1635
+ if (toggleEl.getAttribute('disabled') !== null) return;
1636
+
1637
+ activateTab(toggleEl);
1638
+ }
1639
+
1640
+
1641
+ /**
1642
+ * Activate the tab controlled by the toggle element.
1643
+ * @param {Element} toggleEl - The toggle element.
1644
+ */
1645
+ function activateTab(currToggleEl) {
1646
+ var currTabEl = currToggleEl.parentNode,
1647
+ currPaneId = currToggleEl.getAttribute(controlsAttrKey),
1648
+ currPaneEl = document.getElementById(currPaneId),
1649
+ prevTabEl,
1650
+ prevPaneEl,
1651
+ prevPaneId,
1652
+ prevToggleEl,
1653
+ currData,
1654
+ prevData,
1655
+ ev1,
1656
+ ev2,
1657
+ cssSelector;
1658
+
1659
+ // exit if already active
1660
+ if (jqLite.hasClass(currTabEl, activeClass)) return;
1661
+
1662
+ // raise error if pane doesn't exist
1663
+ if (!currPaneEl) util.raiseError('Tab pane "' + currPaneId + '" not found');
1664
+
1665
+ // get previous pane
1666
+ prevPaneEl = getActiveSibling(currPaneEl);
1667
+ prevPaneId = prevPaneEl.id;
1668
+
1669
+ // get previous toggle and tab elements
1670
+ cssSelector = '[' + controlsAttrKey + '="' + prevPaneId + '"]';
1671
+ prevToggleEl = document.querySelectorAll(cssSelector)[0];
1672
+ prevTabEl = prevToggleEl.parentNode;
1673
+
1674
+ // define event data
1675
+ currData = {paneId: currPaneId, relatedPaneId: prevPaneId};
1676
+ prevData = {paneId: prevPaneId, relatedPaneId: currPaneId};
1677
+
1678
+ // dispatch 'hidestart', 'showstart' events
1679
+ ev1 = util.dispatchEvent(prevToggleEl, hidestartKey, true, true, prevData);
1680
+ ev2 = util.dispatchEvent(currToggleEl, showstartKey, true, true, currData);
1681
+
1682
+ // let events bubble
1683
+ setTimeout(function() {
1684
+ // exit if either event was canceled
1685
+ if (ev1.defaultPrevented || ev2.defaultPrevented) return;
1686
+
1687
+ // de-activate previous
1688
+ if (prevTabEl) jqLite.removeClass(prevTabEl, activeClass);
1689
+ if (prevPaneEl) jqLite.removeClass(prevPaneEl, activeClass);
1690
+
1691
+ // activate current
1692
+ jqLite.addClass(currTabEl, activeClass);
1693
+ jqLite.addClass(currPaneEl, activeClass);
1694
+
1695
+ // dispatch 'hideend', 'showend' events
1696
+ util.dispatchEvent(prevToggleEl, hideendKey, true, false, prevData);
1697
+ util.dispatchEvent(currToggleEl, showendKey, true, false, currData);
1698
+ }, 0);
1699
+ }
1700
+
1701
+
1702
+ /**
1703
+ * Get previous active sibling.
1704
+ * @param {Element} el - The anchor element.
1705
+ */
1706
+ function getActiveSibling(el) {
1707
+ var elList = el.parentNode.children,
1708
+ q = elList.length,
1709
+ activeEl = null,
1710
+ tmpEl;
1711
+
1712
+ while (q-- && !activeEl) {
1713
+ tmpEl = elList[q];
1714
+ if (tmpEl !== el && jqLite.hasClass(tmpEl, activeClass)) activeEl = tmpEl
1715
+ }
1716
+
1717
+ return activeEl;
1718
+ }
1719
+
1720
+
1721
+ /** Define module API */
1722
+ module.exports = {
1723
+ /** Initialize module listeners */
1724
+ initListeners: function() {
1725
+ // markup elements available when method is called
1726
+ var elList = document.querySelectorAll(attrSelector);
1727
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
1728
+
1729
+ // TODO: listen for new elements
1730
+ util.onNodeInserted(function(el) {
1731
+ if (el.getAttribute(attrKey) === 'tab') initialize(el);
1732
+ });
1733
+ },
1734
+
1735
+ /** External API */
1736
+ api: {
1737
+ activate: function(paneId) {
1738
+ var cssSelector = '[' + controlsAttrKey + '=' + paneId + ']',
1739
+ toggleEl = document.querySelectorAll(cssSelector);
1740
+
1741
+ if (!toggleEl.length) {
1742
+ util.raiseError('Tab control for pane "' + paneId + '" not found');
1743
+ }
1744
+
1745
+ activateTab(toggleEl[0]);
1746
+ }
1747
+ }
1748
+ };
1749
+
1750
+ },{"./lib/jqLite.js":5,"./lib/util.js":6}]},{},[7]);