(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o input', 'mui-textfield-inserted'], ['.mui-textfield > textarea', 'mui-textfield-inserted'], ['.mui-textfield > input:-webkit-autofill', 'mui-textfield-autofill'], ['.mui-textfield > textarea:-webkit-autofill', 'mui-textfield-autofill'], ['.mui-select > select', 'mui-select-inserted'], ['.mui-select > select ~ .mui-event-trigger', 'mui-node-inserted'], ['.mui-select > select:disabled ~ .mui-event-trigger', 'mui-node-disabled'] ]; // build css var css = '', rule; for (var i=0, m=rules.length; i < m; i++) { rule = rules[i]; css += '@keyframes ' + rule[1]; css += '{from{transform:none;}to{transform:none;}}'; css += rule[0]; css += '{animation-duration:0.0001s;animation-name:' + rule[1] + ';}'; } // add CSS to DOM util.loadStyle(css); } /** * Define module API */ module.exports = { animationEvents: animationEvents, onAnimationStart: onAnimationStartFn } },{"./jqLite":5,"./util":6}],4:[function(require,module,exports){ /** * MUI CSS/JS form helpers module * @module lib/forms.py */ 'use strict'; var wrapperPadding = 15, // from CSS inputHeight = 32, // from CSS rowHeight = 42, // from CSS menuPadding = 8; // from CSS /** * Menu position/size/scroll helper * @returns {Object} Object with keys 'height', 'top', 'scrollTop' */ function getMenuPositionalCSSFn(wrapperEl, numRows, selectedRow) { var viewHeight = document.documentElement.clientHeight; // determine 'height' var h = numRows * rowHeight + 2 * menuPadding, height = Math.min(h, viewHeight); // determine 'top' var top, initTop, minTop, maxTop; initTop = (menuPadding + rowHeight) - (wrapperPadding + inputHeight); initTop -= selectedRow * rowHeight; minTop = -1 * wrapperEl.getBoundingClientRect().top; maxTop = (viewHeight - height) + minTop; top = Math.min(Math.max(initTop, minTop), maxTop); // determine 'scrollTop' var scrollTop = 0, scrollIdeal, scrollMax; if (h > viewHeight) { scrollIdeal = (menuPadding + (selectedRow + 1) * rowHeight) - (-1 * top + wrapperPadding + inputHeight); scrollMax = numRows * rowHeight + 2 * menuPadding - height; scrollTop = Math.min(scrollIdeal, scrollMax); } return { 'height': height + 'px', 'top': top + 'px', 'scrollTop': scrollTop }; } /** Define module API */ module.exports = { getMenuPositionalCSS: getMenuPositionalCSSFn }; },{}],5:[function(require,module,exports){ /** * MUI CSS/JS jqLite module * @module lib/jqLite */ 'use strict'; /** * Add a class to an element. * @param {Element} element - The DOM element. * @param {string} cssClasses - Space separated list of class names. */ function jqLiteAddClass(element, cssClasses) { if (!cssClasses || !element.setAttribute) return; var existingClasses = _getExistingClasses(element), splitClasses = cssClasses.split(' '), cssClass; for (var i=0; i < splitClasses.length; i++) { cssClass = splitClasses[i].trim(); if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) { existingClasses += cssClass + ' '; } } element.setAttribute('class', existingClasses.trim()); } /** * Get or set CSS properties. * @param {Element} element - The DOM element. * @param {string} [name] - The property name. * @param {string} [value] - The property value. */ function jqLiteCss(element, name, value) { // Return full style object if (name === undefined) { return getComputedStyle(element); } var nameType = jqLiteType(name); // Set multiple values if (nameType === 'object') { for (var key in name) element.style[_camelCase(key)] = name[key]; return; } // Set a single value if (nameType === 'string' && value !== undefined) { element.style[_camelCase(name)] = value; } var styleObj = getComputedStyle(element), isArray = (jqLiteType(name) === 'array'); // Read single value if (!isArray) return _getCurrCssProp(element, name, styleObj); // Read multiple values var outObj = {}, key; for (var i=0; i < name.length; i++) { key = name[i]; outObj[key] = _getCurrCssProp(element, key, styleObj); } return outObj; } /** * Check if element has class. * @param {Element} element - The DOM element. * @param {string} cls - The class name string. */ function jqLiteHasClass(element, cls) { if (!cls || !element.getAttribute) return false; return (_getExistingClasses(element).indexOf(' ' + cls + ' ') > -1); } /** * Return the type of a variable. * @param {} somevar - The JavaScript variable. */ function jqLiteType(somevar) { // handle undefined if (somevar === undefined) return 'undefined'; // handle others (of type [object ]) var typeStr = Object.prototype.toString.call(somevar); if (typeStr.indexOf('[object ') === 0) { return typeStr.slice(8, -1).toLowerCase(); } else { throw new Error("MUI: Could not understand type: " + typeStr); } } /** * Attach an event handler to a DOM element * @param {Element} element - The DOM element. * @param {string} events - Space separated event names. * @param {Function} callback - The callback function. * @param {Boolean} useCapture - Use capture flag. */ function jqLiteOn(element, events, callback, useCapture) { useCapture = (useCapture === undefined) ? false : useCapture; var cache = element._muiEventCache = element._muiEventCache || {}; events.split(' ').map(function(event) { // add to DOM element.addEventListener(event, callback, useCapture); // add to cache cache[event] = cache[event] || []; cache[event].push([callback, useCapture]); }); } /** * Remove an event handler from a DOM element * @param {Element} element - The DOM element. * @param {string} events - Space separated event names. * @param {Function} callback - The callback function. * @param {Boolean} useCapture - Use capture flag. */ function jqLiteOff(element, events, callback, useCapture) { useCapture = (useCapture === undefined) ? false : useCapture; // remove from cache var cache = element._muiEventCache = element._muiEventCache || {}, argsList, args, i; events.split(' ').map(function(event) { argsList = cache[event] || []; i = argsList.length; while (i--) { args = argsList[i]; // remove all events if callback is undefined if (callback === undefined || (args[0] === callback && args[1] === useCapture)) { // remove from cache argsList.splice(i, 1); // remove from DOM element.removeEventListener(event, args[0], args[1]); } } }); } /** * Attach an event hander which will only execute once per element per event * @param {Element} element - The DOM element. * @param {string} events - Space separated event names. * @param {Function} callback - The callback function. * @param {Boolean} useCapture - Use capture flag. */ function jqLiteOne(element, events, callback, useCapture) { events.split(' ').map(function(event) { jqLiteOn(element, event, function onFn(ev) { // execute callback if (callback) callback.apply(this, arguments); // remove wrapper jqLiteOff(element, event, onFn, useCapture); }, useCapture); }); } /** * Get or set horizontal scroll position * @param {Element} element - The DOM element * @param {number} [value] - The scroll position */ function jqLiteScrollLeft(element, value) { var win = window; // get if (value === undefined) { if (element === win) { var docEl = document.documentElement; return (win.pageXOffset || docEl.scrollLeft) - (docEl.clientLeft || 0); } else { return element.scrollLeft; } } // set if (element === win) win.scrollTo(value, jqLiteScrollTop(win)); else element.scrollLeft = value; } /** * Get or set vertical scroll position * @param {Element} element - The DOM element * @param {number} value - The scroll position */ function jqLiteScrollTop(element, value) { var win = window; // get if (value === undefined) { if (element === win) { var docEl = document.documentElement; return (win.pageYOffset || docEl.scrollTop) - (docEl.clientTop || 0); } else { return element.scrollTop; } } // set if (element === win) win.scrollTo(jqLiteScrollLeft(win), value); else element.scrollTop = value; } /** * Return object representing top/left offset and element height/width. * @param {Element} element - The DOM element. */ function jqLiteOffset(element) { var win = window, rect = element.getBoundingClientRect(), scrollTop = jqLiteScrollTop(win), scrollLeft = jqLiteScrollLeft(win); return { top: rect.top + scrollTop, left: rect.left + scrollLeft, height: rect.height, width: rect.width }; } /** * Attach a callback to the DOM ready event listener * @param {Function} fn - The callback function. */ function jqLiteReady(fn) { var done = false, top = true, doc = document, win = doc.defaultView, root = doc.documentElement, add = doc.addEventListener ? 'addEventListener' : 'attachEvent', rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent', pre = doc.addEventListener ? '' : 'on'; var init = function(e) { if (e.type == 'readystatechange' && doc.readyState != 'complete') { return; } (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false); if (!done && (done = true)) fn.call(win, e.type || e); }; var poll = function() { try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; } init('poll'); }; if (doc.readyState == 'complete') { fn.call(win, 'lazy'); } else { if (doc.createEventObject && root.doScroll) { try { top = !win.frameElement; } catch(e) { } if (top) poll(); } doc[add](pre + 'DOMContentLoaded', init, false); doc[add](pre + 'readystatechange', init, false); win[add](pre + 'load', init, false); } } /** * Remove classes from a DOM element * @param {Element} element - The DOM element. * @param {string} cssClasses - Space separated list of class names. */ function jqLiteRemoveClass(element, cssClasses) { if (!cssClasses || !element.setAttribute) return; var existingClasses = _getExistingClasses(element), splitClasses = cssClasses.split(' '), cssClass; for (var i=0; i < splitClasses.length; i++) { cssClass = splitClasses[i].trim(); while (existingClasses.indexOf(' ' + cssClass + ' ') >= 0) { existingClasses = existingClasses.replace(' ' + cssClass + ' ', ' '); } } element.setAttribute('class', existingClasses.trim()); } // ------------------------------ // Utilities // ------------------------------ var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g, MOZ_HACK_REGEXP = /^moz([A-Z])/, ESCAPE_REGEXP = /([.*+?^=!:${}()|\[\]\/\\])/g; function _getExistingClasses(element) { var classes = (element.getAttribute('class') || '').replace(/[\n\t]/g, ''); return ' ' + classes + ' '; } function _camelCase(name) { return name. replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { return offset ? letter.toUpperCase() : letter; }). replace(MOZ_HACK_REGEXP, 'Moz$1'); } function _escapeRegExp(string) { return string.replace(ESCAPE_REGEXP, "\\$1"); } function _getCurrCssProp(elem, name, computed) { var ret; // try computed style ret = computed.getPropertyValue(name); // try style attribute (if element is not attached to document) if (ret === '' && !elem.ownerDocument) ret = elem.style[_camelCase(name)]; return ret; } /** * Module API */ module.exports = { /** Add classes */ addClass: jqLiteAddClass, /** Get or set CSS properties */ css: jqLiteCss, /** Check for class */ hasClass: jqLiteHasClass, /** Remove event handlers */ off: jqLiteOff, /** Return offset values */ offset: jqLiteOffset, /** Add event handlers */ on: jqLiteOn, /** Add an execute-once event handler */ one: jqLiteOne, /** DOM ready event handler */ ready: jqLiteReady, /** Remove classes */ removeClass: jqLiteRemoveClass, /** Check JavaScript variable instance type */ type: jqLiteType, /** Get or set horizontal scroll position */ scrollLeft: jqLiteScrollLeft, /** Get or set vertical scroll position */ scrollTop: jqLiteScrollTop }; },{}],6:[function(require,module,exports){ /** * MUI CSS/JS utilities module * @module lib/util */ 'use strict'; var config = require('../config'), jqLite = require('./jqLite'), scrollLock = 0, scrollLockCls = 'mui-scroll-lock', scrollLockPos, scrollStyleEl, scrollEventHandler, _scrollBarWidth, _supportsPointerEvents; scrollEventHandler = function(ev) { // stop propagation on window scroll events if (!ev.target.tagName) ev.stopImmediatePropagation(); } /** * Logging function */ function logFn() { var win = window; if (config.debug && typeof win.console !== "undefined") { try { win.console.log.apply(win.console, arguments); } catch (a) { var e = Array.prototype.slice.call(arguments); win.console.log(e.join("\n")); } } } /** * Load CSS text in new stylesheet * @param {string} cssText - The css text. */ function loadStyleFn(cssText) { var doc = document, head; // copied from jQuery head = doc.head || doc.getElementsByTagName('head')[0] || doc.documentElement; var e = doc.createElement('style'); e.type = 'text/css'; if (e.styleSheet) e.styleSheet.cssText = cssText; else e.appendChild(doc.createTextNode(cssText)); // add to document head.insertBefore(e, head.firstChild); return e; } /** * Raise an error * @param {string} msg - The error message. */ function raiseErrorFn(msg, useConsole) { if (useConsole) { if (typeof console !== 'undefined') console.error('MUI Warning: ' + msg); } else { throw new Error('MUI: ' + msg); } } /** * Convert Classname object, with class as key and true/false as value, to an * class string. * @param {Object} classes The classes * @return {String} class string */ function classNamesFn(classes) { var cs = ''; for (var i in classes) { cs += (classes[i]) ? i + ' ' : ''; } return cs.trim(); } /** * Check if client supports pointer events. */ function supportsPointerEventsFn() { // check cache if (_supportsPointerEvents !== undefined) return _supportsPointerEvents; var element = document.createElement('x'); element.style.cssText = 'pointer-events:auto'; _supportsPointerEvents = (element.style.pointerEvents === 'auto'); return _supportsPointerEvents; } /** * Create callback closure. * @param {Object} instance - The object instance. * @param {String} funcName - The name of the callback function. */ function callbackFn(instance, funcName) { return function() {instance[funcName].apply(instance, arguments);}; } /** * Dispatch event. * @param {Element} element - The DOM element. * @param {String} eventType - The event type. * @param {Boolean} bubbles=true - If true, event bubbles. * @param {Boolean} cancelable=true = If true, event is cancelable * @param {Object} [data] - Data to add to event object */ function dispatchEventFn(element, eventType, bubbles, cancelable, data) { var ev = document.createEvent('HTMLEvents'), bubbles = (bubbles !== undefined) ? bubbles : true, cancelable = (cancelable !== undefined) ? cancelable : true, k; ev.initEvent(eventType, bubbles, cancelable); // add data to event object if (data) for (k in data) ev[k] = data[k]; // dispatch if (element) element.dispatchEvent(ev); return ev; } /** * Turn on window scroll lock. */ function enableScrollLockFn() { // increment counter scrollLock += 1; // add lock if (scrollLock === 1) { var doc = document, win = window, htmlEl = doc.documentElement, bodyEl = doc.body, scrollBarWidth = getScrollBarWidth(), cssProps, cssStr, x; // define scroll lock class dynamically cssProps = ['overflow:hidden']; if (scrollBarWidth) { // scrollbar-y if (htmlEl.scrollHeight > htmlEl.clientHeight) { x = parseInt(jqLite.css(bodyEl, 'padding-right')) + scrollBarWidth; cssProps.push('padding-right:' + x + 'px'); } // scrollbar-x if (htmlEl.scrollWidth > htmlEl.clientWidth) { x = parseInt(jqLite.css(bodyEl, 'padding-bottom')) + scrollBarWidth; cssProps.push('padding-bottom:' + x + 'px'); } } // define css class dynamically cssStr = '.' + scrollLockCls + '{'; cssStr += cssProps.join(' !important;') + ' !important;}'; scrollStyleEl = loadStyleFn(cssStr); // cancel 'scroll' event listener callbacks jqLite.on(win, 'scroll', scrollEventHandler, true); // add scroll lock scrollLockPos = {left: jqLite.scrollLeft(win), top: jqLite.scrollTop(win)}; jqLite.addClass(bodyEl, scrollLockCls); } } /** * Turn off window scroll lock. * @param {Boolean} resetPos - Reset scroll position to original value. */ function disableScrollLockFn(resetPos) { // ignore if (scrollLock === 0) return; // decrement counter scrollLock -= 1; // remove lock if (scrollLock === 0) { // remove scroll lock and delete style element jqLite.removeClass(document.body, scrollLockCls); scrollStyleEl.parentNode.removeChild(scrollStyleEl); // restore scroll position if (resetPos) window.scrollTo(scrollLockPos.left, scrollLockPos.top); // restore scroll event listeners jqLite.off(window, 'scroll', scrollEventHandler, true); } } /** * Return scroll bar width. */ var getScrollBarWidth = function() { // check cache if (_scrollBarWidth !== undefined) return _scrollBarWidth; // calculate scroll bar width var doc = document, bodyEl = doc.body, el = doc.createElement('div'); el.innerHTML = '
'; el = el.firstChild; bodyEl.appendChild(el); _scrollBarWidth = el.offsetWidth - el.clientWidth; bodyEl.removeChild(el); return _scrollBarWidth; } /** * requestAnimationFrame polyfilled * @param {Function} callback - The callback function */ function requestAnimationFrameFn(callback) { var fn = window.requestAnimationFrame; if (fn) fn(callback); else setTimeout(callback, 0); } /** * Define the module API */ module.exports = { /** Create callback closures */ callback: callbackFn, /** Classnames object to string */ classNames: classNamesFn, /** Disable scroll lock */ disableScrollLock: disableScrollLockFn, /** Dispatch event */ dispatchEvent: dispatchEventFn, /** Enable scroll lock */ enableScrollLock: enableScrollLockFn, /** Log messages to the console when debug is turned on */ log: logFn, /** Load CSS text as new stylesheet */ loadStyle: loadStyleFn, /** Raise MUI error */ raiseError: raiseErrorFn, /** Request animation frame */ requestAnimationFrame: requestAnimationFrameFn, /** Support Pointer Events check */ supportsPointerEvents: supportsPointerEventsFn }; },{"../config":2,"./jqLite":5}],7:[function(require,module,exports){ /** * MUI CSS/JS dropdown module * @module dropdowns */ 'use strict'; var jqLite = require('./lib/jqLite'), util = require('./lib/util'), animationHelpers = require('./lib/animationHelpers'), attrKey = 'data-mui-toggle', attrSelector = '[data-mui-toggle="dropdown"]', openClass = 'mui--is-open', menuClass = 'mui-dropdown__menu'; /** * Initialize toggle element. * @param {Element} toggleEl - The toggle element. */ function initialize(toggleEl) { // check flag if (toggleEl._muiDropdown === true) return; else toggleEl._muiDropdown = true; // use type "button" to prevent form submission by default var tagName = toggleEl.tagName; if ((tagName === 'INPUT' || tagName === 'BUTTON') && !toggleEl.hasAttribute('type')) { toggleEl.type = 'button'; } // attach click handler jqLite.on(toggleEl, 'click', clickHandler); } /** * Handle click events on dropdown toggle element. * @param {Event} ev - The DOM event */ function clickHandler(ev) { // only left clicks if (ev.button !== 0) return; var toggleEl = this; // exit if toggle button is disabled if (toggleEl.getAttribute('disabled') !== null) return; // toggle dropdown toggleDropdown(toggleEl); } /** * Toggle the dropdown. * @param {Element} toggleEl - The dropdown toggle element. */ function toggleDropdown(toggleEl) { var wrapperEl = toggleEl.parentNode, menuEl = toggleEl.nextElementSibling, doc = wrapperEl.ownerDocument; // exit if no menu element if (!menuEl || !jqLite.hasClass(menuEl, menuClass)) { return util.raiseError('Dropdown menu element not found'); } // method to close dropdown function closeDropdownFn() { jqLite.removeClass(menuEl, openClass); // remove event handlers jqLite.off(doc, 'click', closeDropdownFn); } // method to open dropdown function openDropdownFn() { // position menu element below toggle button var wrapperRect = wrapperEl.getBoundingClientRect(), toggleRect = toggleEl.getBoundingClientRect(); var top = toggleRect.top - wrapperRect.top + toggleRect.height; jqLite.css(menuEl, 'top', top + 'px'); // add open class to wrapper jqLite.addClass(menuEl, openClass); // close dropdown when user clicks outside of menu setTimeout(function() {jqLite.on(doc, 'click', closeDropdownFn);}, 0); } // toggle dropdown if (jqLite.hasClass(menuEl, openClass)) closeDropdownFn(); else openDropdownFn(); } /** Define module API */ module.exports = { /** Initialize module listeners */ initListeners: function() { // markup elements available when method is called var elList = document.querySelectorAll(attrSelector), i = elList.length; while (i--) {initialize(elList[i]);} // listen for new elements animationHelpers.onAnimationStart('mui-dropdown-inserted', function(ev) { initialize(ev.target); }); } }; },{"./lib/animationHelpers":3,"./lib/jqLite":5,"./lib/util":6}],8:[function(require,module,exports){ module.exports=require(5) },{}],9:[function(require,module,exports){ /** * MUI CSS/JS overlay module * @module overlay */ 'use strict'; var util = require('./lib/util'), jqLite = require('./lib/jqLite'), overlayId = 'mui-overlay', bodyClass = 'mui--overflow-hidden', iosRegex = /(iPad|iPhone|iPod)/g, activeElement; /** * Turn overlay on/off. * @param {string} action - Turn overlay "on"/"off". * @param {object} [options] * @config {boolean} [keyboard] - If true, close when escape key is pressed. * @config {boolean} [static] - If false, close when backdrop is clicked. * @config {Function} [onclose] - Callback function to execute on close * @param {Element} [childElement] - Child element to add to overlay. */ function overlayFn(action) { var overlayEl; if (action === 'on') { // extract arguments var arg, options, childElement; // pull options and childElement from arguments for (var i=arguments.length - 1; i > 0; i--) { arg = arguments[i]; if (jqLite.type(arg) === 'object') options = arg; if (arg instanceof Element && arg.nodeType === 1) childElement = arg; } // option defaults options = options || {}; if (options.keyboard === undefined) options.keyboard = true; if (options.static === undefined) options.static = false; // execute method overlayEl = overlayOn(options, childElement); } else if (action === 'off') { overlayEl = overlayOff(); } else { // raise error util.raiseError("Expecting 'on' or 'off'"); } return overlayEl; } /** * Turn on overlay. * @param {object} options - Overlay options. * @param {Element} childElement - The child element. */ function overlayOn(options, childElement) { var doc = document, bodyEl = doc.body, overlayEl = doc.getElementById(overlayId); // cache activeElement if (doc.activeElement) activeElement = doc.activeElement; // add overlay util.enableScrollLock(); if (!overlayEl) { // create overlayEl overlayEl = doc.createElement('div'); overlayEl.setAttribute('id', overlayId); overlayEl.setAttribute('tabindex', '-1'); // add child element if (childElement) overlayEl.appendChild(childElement); bodyEl.appendChild(overlayEl); } else { // remove existing children while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild); // add child element if (childElement) overlayEl.appendChild(childElement); } // iOS bugfix if (iosRegex.test(navigator.userAgent)) { jqLite.css(overlayEl, 'cursor', 'pointer'); } // handle options if (options.keyboard) addKeyupHandler(); else removeKeyupHandler(); if (options.static) removeClickHandler(overlayEl); else addClickHandler(overlayEl); // attach options overlayEl.muiOptions = options; // focus overlay element overlayEl.focus(); return overlayEl; } /** * Turn off overlay. */ function overlayOff() { var overlayEl = document.getElementById(overlayId), callbackFn; if (overlayEl) { // remove children while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild); // remove overlay element overlayEl.parentNode.removeChild(overlayEl); // callback reference callbackFn = overlayEl.muiOptions.onclose; // remove click handler removeClickHandler(overlayEl); } util.disableScrollLock(); // remove keyup handler removeKeyupHandler(); // return focus to activeElement if (activeElement) activeElement.focus(); // execute callback if (callbackFn) callbackFn(); return overlayEl; } /** * Add keyup handler. */ function addKeyupHandler() { jqLite.on(document, 'keyup', onKeyup); } /** * Remove keyup handler. */ function removeKeyupHandler() { jqLite.off(document, 'keyup', onKeyup); } /** * Teardown overlay when escape key is pressed. */ function onKeyup(ev) { if (ev.keyCode === 27) overlayOff(); } /** * Add click handler. */ function addClickHandler(overlayEl) { jqLite.on(overlayEl, 'click', onClick); } /** * Remove click handler. */ function removeClickHandler(overlayEl) { jqLite.off(overlayEl, 'click', onClick); } /** * Teardown overlay when backdrop is clicked. */ function onClick(ev) { if (ev.target.id === overlayId) overlayOff(); } /** Define module API */ module.exports = overlayFn; },{"./lib/jqLite":5,"./lib/util":6}],10:[function(require,module,exports){ /** * MUI CSS/JS ripple module * @module ripple */ 'use strict'; var jqLite = require('./lib/jqLite'), util = require('./lib/util'), animationHelpers = require('./lib/animationHelpers'), supportsTouch = 'ontouchstart' in document.documentElement, mouseDownEvents = (supportsTouch) ? 'touchstart' : 'mousedown', mouseUpEvents = (supportsTouch) ? 'touchend' : 'mouseup mouseleave'; /** * Add ripple effects to button element. * @param {Element} buttonEl - The button element. */ function initialize(buttonEl) { // check flag if (buttonEl._muiRipple === true) return; else buttonEl._muiRipple = true; // exit if element is INPUT (doesn't support absolute positioned children) if (buttonEl.tagName === 'INPUT') return; // attach event handler jqLite.on(buttonEl, mouseDownEvents, mouseDownHandler); } /** * MouseDown Event handler. * @param {Event} ev - The DOM event */ function mouseDownHandler(ev) { // only left clicks if (ev.type === 'mousedown' && ev.button !== 0) return; var buttonEl = this, rippleEl = buttonEl._rippleEl; // exit if button is disabled if (buttonEl.disabled) return; if (!rippleEl) { // add ripple container (to avoid https://github.com/muicss/mui/issues/169) var el = document.createElement('span'); el.className = 'mui-btn__ripple-container'; el.innerHTML = ''; buttonEl.appendChild(el); // cache reference to ripple element rippleEl = buttonEl._rippleEl = el.children[0]; // add mouseup handler on first-click jqLite.on(buttonEl, mouseUpEvents, mouseUpHandler); } // get ripple element offset values and (x, y) position of click var offset = jqLite.offset(buttonEl), clickEv = (ev.type === 'touchstart') ? ev.touches[0] : ev, radius, diameter; // calculate radius radius = Math.sqrt(offset.height * offset.height + offset.width * offset.width); diameter = radius * 2 + 'px'; // set position and dimensions jqLite.css(rippleEl, { width: diameter, height: diameter, top: Math.round(clickEv.pageY - offset.top - radius) + 'px', left: Math.round(clickEv.pageX - offset.left - radius) + 'px' }); jqLite.removeClass(rippleEl, 'mui--is-animating'); jqLite.addClass(rippleEl, 'mui--is-visible'); // start animation util.requestAnimationFrame(function() { jqLite.addClass(rippleEl, 'mui--is-animating'); }); } /** * MouseUp event handler. * @param {Event} ev - The DOM event */ function mouseUpHandler(ev) { // get ripple element var rippleEl = this._rippleEl; // allow a repaint to occur before removing class so animation shows for // tap events util.requestAnimationFrame(function() { jqLite.removeClass(rippleEl, 'mui--is-visible'); }); } /** Define module API */ module.exports = { /** Initialize module listeners */ initListeners: function() { // markup elements available when method is called var elList = document.getElementsByClassName('mui-btn'), i = elList.length; while (i--) initialize(elList[i]); // listen for new elements animationHelpers.onAnimationStart('mui-btn-inserted', function(ev) { initialize(ev.target); }); } }; },{"./lib/animationHelpers":3,"./lib/jqLite":5,"./lib/util":6}],11:[function(require,module,exports){ /** * MUI CSS/JS select module * @module forms/select */ 'use strict'; var jqLite = require('./lib/jqLite'), util = require('./lib/util'), animationHelpers = require('./lib/animationHelpers'), formlib = require('./lib/forms'), wrapperClass = 'mui-select', cssSelector = '.mui-select > select', menuClass = 'mui-select__menu', selectedClass = 'mui--is-selected', disabledClass = 'mui--is-disabled', doc = document, win = window; /** * Initialize select element. * @param {Element} selectEl - The select element. */ function initialize(selectEl) { // check flag if (selectEl._muiSelect === true) return; else selectEl._muiSelect = true; // use default behavior on touch devices if ('ontouchstart' in doc.documentElement) return; // NOTE: To get around cross-browser issues with if (!selectEl.disabled) wrapperEl.tabIndex = 0; selectEl.tabIndex = -1; // prevent built-in menu from opening on element. * @param {Event} ev - The DOM event */ function onWrapperBlurOrFocus(ev) { util.dispatchEvent(this._selectEl, ev.type, false, false); } /** * Handle keydown events when wrapper is focused **/ function onWrapperKeyDown(ev) { if (ev.defaultPrevented) return; var keyCode = ev.keyCode, menu = this._menu; if (!menu) { // spacebar, down, up if (keyCode === 32 || keyCode === 38 || keyCode === 40) { ev.preventDefault(); // open custom menu renderMenu(this); } } else { // tab if (keyCode === 9) return menu.destroy(); // escape | up | down | enter if (keyCode === 27 || keyCode === 40 || keyCode === 38 || keyCode === 13) { ev.preventDefault(); } if (keyCode === 27) { // escape menu.destroy(); } else if (keyCode === 40) { // up menu.increment(); } else if (keyCode === 38) { // down menu.decrement(); } else if (keyCode === 13) { // enter menu.selectCurrent(); menu.destroy(); } } } /** * */ function onWrapperKeyPress(ev) { var menu = this._menu; // exit if default prevented or menu is closed if (ev.defaultPrevented || !menu) return; // handle query timer var self = this; clearTimeout(this._qTimeout); this._q += ev.key; this._qTimeout = setTimeout(function() {self._q = '';}, 300); // select first match alphabetically var prefixRegex = new RegExp('^' + this._q, 'i'), itemArray = menu.itemArray, pos; for (pos in itemArray) { if (prefixRegex.test(itemArray[pos].innerText)) { menu.selectPos(pos); break; } } } /** * Handle click events on wrapper element. * @param {Event} ev - The DOM event */ function onWrapperClick(ev) { // only left clicks, check default and disabled flags if (ev.button !== 0 || this._selectEl.disabled) return; // focus wrapper this.focus(); // open menu renderMenu(this); } /** * Render options menu */ function renderMenu(wrapperEl) { // check instance if (wrapperEl._menu) return; // render custom menu wrapperEl._menu = new Menu(wrapperEl, wrapperEl._selectEl, function() { wrapperEl._menu = null; // de-reference instance wrapperEl.focus(); }); } /** * Creates a new Menu * @class */ function Menu(wrapperEl, selectEl, wrapperCallbackFn) { // add scroll lock util.enableScrollLock(); // instance variables this.itemArray = []; this.origPos = null; this.currentPos = null; this.selectEl = selectEl; this.wrapperEl = wrapperEl; this.menuEl = this._createMenuEl(wrapperEl, selectEl); var cb = util.callback; this.onClickCB = cb(this, 'onClick'); this.destroyCB = cb(this, 'destroy'); this.wrapperCallbackFn = wrapperCallbackFn; // add to DOM wrapperEl.appendChild(this.menuEl); jqLite.scrollTop(this.menuEl, this.menuEl._scrollTop); // attach event handlers var destroyCB = this.destroyCB; jqLite.on(this.menuEl, 'click', this.onClickCB); jqLite.on(win, 'resize', destroyCB); // attach event handler after current event loop exits setTimeout(function() {jqLite.on(doc, 'click', destroyCB);}, 0); } /** * Create menu element * @param {Element} selectEl - The select element */ Menu.prototype._createMenuEl = function(wrapperEl, selectEl) { var menuEl = doc.createElement('div'), childEls = selectEl.children, itemArray = this.itemArray, itemPos = 0, origPos = -1, selectedPos = 0, selectedRow = 0, docFrag = document.createDocumentFragment(), // for speed loopEl, rowEl, optionEls, inGroup, i, iMax, j, jMax; menuEl.className = menuClass; for (i=0, iMax=childEls.length; i < iMax; i++) { loopEl = childEls[i]; if (loopEl.tagName === 'OPTGROUP') { // add row item to menu rowEl = doc.createElement('div'); rowEl.textContent = loopEl.label; rowEl.className = 'mui-optgroup__label'; docFrag.appendChild(rowEl); inGroup = true; optionEls = loopEl.children; } else { inGroup = false; optionEls = [loopEl]; } // loop through option elements for (j=0, jMax=optionEls.length; j < jMax; j++) { loopEl = optionEls[j]; // add row item to menu rowEl = doc.createElement('div'); rowEl.textContent = loopEl.textContent; // handle optgroup options if (inGroup) jqLite.addClass(rowEl, 'mui-optgroup__option'); if (loopEl.disabled) { // do not attach muiIndex to disable