mui-sass 0.2.4 → 0.2.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.
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]);