diff options
Diffstat (limited to 'node_modules/materialize-css/js/global.js')
-rw-r--r-- | node_modules/materialize-css/js/global.js | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/node_modules/materialize-css/js/global.js b/node_modules/materialize-css/js/global.js new file mode 100644 index 0000000000..779edd33fc --- /dev/null +++ b/node_modules/materialize-css/js/global.js @@ -0,0 +1,427 @@ +// Required for Meteor package, the use of window prevents export by Meteor +(function(window) { + if (window.Package) { + M = {}; + } else { + window.M = {}; + } + + // Check for jQuery + M.jQueryLoaded = !!window.jQuery; +})(window); + +// AMD +if (typeof define === 'function' && define.amd) { + define('M', [], function() { + return M; + }); + + // Common JS +} else if (typeof exports !== 'undefined' && !exports.nodeType) { + if (typeof module !== 'undefined' && !module.nodeType && module.exports) { + exports = module.exports = M; + } + exports.default = M; +} + +M.version = '1.0.0'; + +M.keys = { + TAB: 9, + ENTER: 13, + ESC: 27, + ARROW_UP: 38, + ARROW_DOWN: 40 +}; + +/** + * TabPress Keydown handler + */ +M.tabPressed = false; +M.keyDown = false; +let docHandleKeydown = function(e) { + M.keyDown = true; + if (e.which === M.keys.TAB || e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) { + M.tabPressed = true; + } +}; +let docHandleKeyup = function(e) { + M.keyDown = false; + if (e.which === M.keys.TAB || e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) { + M.tabPressed = false; + } +}; +let docHandleFocus = function(e) { + if (M.keyDown) { + document.body.classList.add('keyboard-focused'); + } +}; +let docHandleBlur = function(e) { + document.body.classList.remove('keyboard-focused'); +}; +document.addEventListener('keydown', docHandleKeydown, true); +document.addEventListener('keyup', docHandleKeyup, true); +document.addEventListener('focus', docHandleFocus, true); +document.addEventListener('blur', docHandleBlur, true); + +/** + * Initialize jQuery wrapper for plugin + * @param {Class} plugin javascript class + * @param {string} pluginName jQuery plugin name + * @param {string} classRef Class reference name + */ +M.initializeJqueryWrapper = function(plugin, pluginName, classRef) { + jQuery.fn[pluginName] = function(methodOrOptions) { + // Call plugin method if valid method name is passed in + if (plugin.prototype[methodOrOptions]) { + let params = Array.prototype.slice.call(arguments, 1); + + // Getter methods + if (methodOrOptions.slice(0, 3) === 'get') { + let instance = this.first()[0][classRef]; + return instance[methodOrOptions].apply(instance, params); + } + + // Void methods + return this.each(function() { + let instance = this[classRef]; + instance[methodOrOptions].apply(instance, params); + }); + + // Initialize plugin if options or no argument is passed in + } else if (typeof methodOrOptions === 'object' || !methodOrOptions) { + plugin.init(this, arguments[0]); + return this; + } + + // Return error if an unrecognized method name is passed in + jQuery.error(`Method ${methodOrOptions} does not exist on jQuery.${pluginName}`); + }; +}; + +/** + * Automatically initialize components + * @param {Element} context DOM Element to search within for components + */ +M.AutoInit = function(context) { + // Use document.body if no context is given + let root = !!context ? context : document.body; + + let registry = { + Autocomplete: root.querySelectorAll('.autocomplete:not(.no-autoinit)'), + Carousel: root.querySelectorAll('.carousel:not(.no-autoinit)'), + Chips: root.querySelectorAll('.chips:not(.no-autoinit)'), + Collapsible: root.querySelectorAll('.collapsible:not(.no-autoinit)'), + Datepicker: root.querySelectorAll('.datepicker:not(.no-autoinit)'), + Dropdown: root.querySelectorAll('.dropdown-trigger:not(.no-autoinit)'), + Materialbox: root.querySelectorAll('.materialboxed:not(.no-autoinit)'), + Modal: root.querySelectorAll('.modal:not(.no-autoinit)'), + Parallax: root.querySelectorAll('.parallax:not(.no-autoinit)'), + Pushpin: root.querySelectorAll('.pushpin:not(.no-autoinit)'), + ScrollSpy: root.querySelectorAll('.scrollspy:not(.no-autoinit)'), + FormSelect: root.querySelectorAll('select:not(.no-autoinit)'), + Sidenav: root.querySelectorAll('.sidenav:not(.no-autoinit)'), + Tabs: root.querySelectorAll('.tabs:not(.no-autoinit)'), + TapTarget: root.querySelectorAll('.tap-target:not(.no-autoinit)'), + Timepicker: root.querySelectorAll('.timepicker:not(.no-autoinit)'), + Tooltip: root.querySelectorAll('.tooltipped:not(.no-autoinit)'), + FloatingActionButton: root.querySelectorAll('.fixed-action-btn:not(.no-autoinit)') + }; + + for (let pluginName in registry) { + let plugin = M[pluginName]; + plugin.init(registry[pluginName]); + } +}; + +/** + * Generate approximated selector string for a jQuery object + * @param {jQuery} obj jQuery object to be parsed + * @returns {string} + */ +M.objectSelectorString = function(obj) { + let tagStr = obj.prop('tagName') || ''; + let idStr = obj.attr('id') || ''; + let classStr = obj.attr('class') || ''; + return (tagStr + idStr + classStr).replace(/\s/g, ''); +}; + +// Unique Random ID +M.guid = (function() { + function s4() { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + } + return function() { + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); + }; +})(); + +/** + * Escapes hash from special characters + * @param {string} hash String returned from this.hash + * @returns {string} + */ +M.escapeHash = function(hash) { + return hash.replace(/(:|\.|\[|\]|,|=|\/)/g, '\\$1'); +}; + +M.elementOrParentIsFixed = function(element) { + let $element = $(element); + let $checkElements = $element.add($element.parents()); + let isFixed = false; + $checkElements.each(function() { + if ($(this).css('position') === 'fixed') { + isFixed = true; + return false; + } + }); + return isFixed; +}; + +/** + * @typedef {Object} Edges + * @property {Boolean} top If the top edge was exceeded + * @property {Boolean} right If the right edge was exceeded + * @property {Boolean} bottom If the bottom edge was exceeded + * @property {Boolean} left If the left edge was exceeded + */ + +/** + * @typedef {Object} Bounding + * @property {Number} left left offset coordinate + * @property {Number} top top offset coordinate + * @property {Number} width + * @property {Number} height + */ + +/** + * Escapes hash from special characters + * @param {Element} container Container element that acts as the boundary + * @param {Bounding} bounding element bounding that is being checked + * @param {Number} offset offset from edge that counts as exceeding + * @returns {Edges} + */ +M.checkWithinContainer = function(container, bounding, offset) { + let edges = { + top: false, + right: false, + bottom: false, + left: false + }; + + let containerRect = container.getBoundingClientRect(); + // If body element is smaller than viewport, use viewport height instead. + let containerBottom = + container === document.body + ? Math.max(containerRect.bottom, window.innerHeight) + : containerRect.bottom; + + let scrollLeft = container.scrollLeft; + let scrollTop = container.scrollTop; + + let scrolledX = bounding.left - scrollLeft; + let scrolledY = bounding.top - scrollTop; + + // Check for container and viewport for each edge + if (scrolledX < containerRect.left + offset || scrolledX < offset) { + edges.left = true; + } + + if ( + scrolledX + bounding.width > containerRect.right - offset || + scrolledX + bounding.width > window.innerWidth - offset + ) { + edges.right = true; + } + + if (scrolledY < containerRect.top + offset || scrolledY < offset) { + edges.top = true; + } + + if ( + scrolledY + bounding.height > containerBottom - offset || + scrolledY + bounding.height > window.innerHeight - offset + ) { + edges.bottom = true; + } + + return edges; +}; + +M.checkPossibleAlignments = function(el, container, bounding, offset) { + let canAlign = { + top: true, + right: true, + bottom: true, + left: true, + spaceOnTop: null, + spaceOnRight: null, + spaceOnBottom: null, + spaceOnLeft: null + }; + + let containerAllowsOverflow = getComputedStyle(container).overflow === 'visible'; + let containerRect = container.getBoundingClientRect(); + let containerHeight = Math.min(containerRect.height, window.innerHeight); + let containerWidth = Math.min(containerRect.width, window.innerWidth); + let elOffsetRect = el.getBoundingClientRect(); + + let scrollLeft = container.scrollLeft; + let scrollTop = container.scrollTop; + + let scrolledX = bounding.left - scrollLeft; + let scrolledYTopEdge = bounding.top - scrollTop; + let scrolledYBottomEdge = bounding.top + elOffsetRect.height - scrollTop; + + // Check for container and viewport for left + canAlign.spaceOnRight = !containerAllowsOverflow + ? containerWidth - (scrolledX + bounding.width) + : window.innerWidth - (elOffsetRect.left + bounding.width); + if (canAlign.spaceOnRight < 0) { + canAlign.left = false; + } + + // Check for container and viewport for Right + canAlign.spaceOnLeft = !containerAllowsOverflow + ? scrolledX - bounding.width + elOffsetRect.width + : elOffsetRect.right - bounding.width; + if (canAlign.spaceOnLeft < 0) { + canAlign.right = false; + } + + // Check for container and viewport for Top + canAlign.spaceOnBottom = !containerAllowsOverflow + ? containerHeight - (scrolledYTopEdge + bounding.height + offset) + : window.innerHeight - (elOffsetRect.top + bounding.height + offset); + if (canAlign.spaceOnBottom < 0) { + canAlign.top = false; + } + + // Check for container and viewport for Bottom + canAlign.spaceOnTop = !containerAllowsOverflow + ? scrolledYBottomEdge - (bounding.height - offset) + : elOffsetRect.bottom - (bounding.height + offset); + if (canAlign.spaceOnTop < 0) { + canAlign.bottom = false; + } + + return canAlign; +}; + +M.getOverflowParent = function(element) { + if (element == null) { + return null; + } + + if (element === document.body || getComputedStyle(element).overflow !== 'visible') { + return element; + } + + return M.getOverflowParent(element.parentElement); +}; + +/** + * Gets id of component from a trigger + * @param {Element} trigger trigger + * @returns {string} + */ +M.getIdFromTrigger = function(trigger) { + let id = trigger.getAttribute('data-target'); + if (!id) { + id = trigger.getAttribute('href'); + if (id) { + id = id.slice(1); + } else { + id = ''; + } + } + return id; +}; + +/** + * Multi browser support for document scroll top + * @returns {Number} + */ +M.getDocumentScrollTop = function() { + return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; +}; + +/** + * Multi browser support for document scroll left + * @returns {Number} + */ +M.getDocumentScrollLeft = function() { + return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; +}; + +/** + * @typedef {Object} Edges + * @property {Boolean} top If the top edge was exceeded + * @property {Boolean} right If the right edge was exceeded + * @property {Boolean} bottom If the bottom edge was exceeded + * @property {Boolean} left If the left edge was exceeded + */ + +/** + * @typedef {Object} Bounding + * @property {Number} left left offset coordinate + * @property {Number} top top offset coordinate + * @property {Number} width + * @property {Number} height + */ + +/** + * Get time in ms + * @license https://raw.github.com/jashkenas/underscore/master/LICENSE + * @type {function} + * @return {number} + */ +let getTime = + Date.now || + function() { + return new Date().getTime(); + }; + +/** + * Returns a function, that, when invoked, will only be triggered at most once + * during a given window of time. Normally, the throttled function will run + * as much as it can, without ever going more than once per `wait` duration; + * but if you'd like to disable the execution on the leading edge, pass + * `{leading: false}`. To disable execution on the trailing edge, ditto. + * @license https://raw.github.com/jashkenas/underscore/master/LICENSE + * @param {function} func + * @param {number} wait + * @param {Object=} options + * @returns {Function} + */ +M.throttle = function(func, wait, options) { + let context, args, result; + let timeout = null; + let previous = 0; + options || (options = {}); + let later = function() { + previous = options.leading === false ? 0 : getTime(); + timeout = null; + result = func.apply(context, args); + context = args = null; + }; + return function() { + let now = getTime(); + if (!previous && options.leading === false) previous = now; + let remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; +}; |