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 +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/mui/sass/version.rb +1 -1
- data/vendor/assets/javascripts/mui.js +1713 -0
- data/vendor/assets/stylesheets/mui/_helpers.scss +10 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4da054e1e1cfde1df9e4adf069da1eae58de688d
|
4
|
+
data.tar.gz: e8f64e6ed41407ad40c3941c3da3cb4d56baebe2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ea46ada2caadaef6bacfd946ff35894484e9b142ab51c92877cbe288a40747a6d601383480b6392cb7f00a492f3ec705f9a2d0b82943382ae491a1bf0f32633
|
7
|
+
data.tar.gz: 03c5eee3fb22b4959a9b9b872316b6fb924b414b6c8a6bda5853c9ce68836d87b0997b2a39b7191d76d16259f7c70dc994de22b8dfc09919da90333299261eb7
|
data/CHANGELOG.md
CHANGED
data/lib/mui/sass/version.rb
CHANGED
@@ -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]);
|