{"version":3,"file":"bootstrap-material-design.es.js","sources":["../js/src/util.js","../js/src/base.js","../js/src/baseInput.js","../js/src/baseSelection.js","../js/src/checkbox.js","../js/src/checkboxInline.js","../js/src/collapseInline.js","../js/src/file.js","../js/src/radio.js","../js/src/radioInline.js","../js/src/baseFormControl.js","../js/src/select.js","../js/src/switch.js","../js/src/text.js","../js/src/textarea.js","../js/src/baseLayout.js","../js/src/drawer.js","../js/src/ripples.js","../js/src/autofill.js","../js/src/bootstrapMaterialDesign.js"],"sourcesContent":["const Util = (() => {\n\n /**\n * ------------------------------------------------------------------------\n * Private TransitionEnd Helpers\n * ------------------------------------------------------------------------\n */\n\n let transitionEnd = false\n let transitionEndSelector = ''\n\n const TransitionEndEvent = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend'\n }\n\n function transitionEndTest() {\n if (window.QUnit) {\n return false\n }\n\n let el = document.createElement('mdb')\n\n for (let name in TransitionEndEvent) {\n if (el.style[name] !== undefined) {\n return TransitionEndEvent[name] // { end: TransitionEndEvent[name] }\n }\n }\n\n return false\n }\n\n function setTransitionEndSupport() {\n transitionEnd = transitionEndTest()\n\n // generate a concatenated transition end event selector\n for (let name in TransitionEndEvent) {\n transitionEndSelector += ` ${TransitionEndEvent[name]}`\n }\n }\n\n /**\n * --------------------------------------------------------------------------\n * Public Util Api\n * --------------------------------------------------------------------------\n */\n\n let Util = {\n\n transitionEndSupported() {\n return transitionEnd\n },\n\n transitionEndSelector() {\n return transitionEndSelector\n },\n\n isChar(event) {\n if (typeof event.which === 'undefined') {\n return true\n } else if (typeof event.which === 'number' && event.which > 0) {\n return (\n !event.ctrlKey\n && !event.metaKey\n && !event.altKey\n && event.which !== 8 // backspace\n && event.which !== 9 // tab\n && event.which !== 13 // enter\n && event.which !== 16 // shift\n && event.which !== 17 // ctrl\n && event.which !== 20 // caps lock\n && event.which !== 27 // escape\n )\n }\n return false\n },\n\n assert($element, invalidTest, message) {\n if (invalidTest) {\n if (!$element === undefined) {\n $element.css('border', '1px solid red')\n }\n console.error(message, $element) // eslint-disable-line no-console\n throw message\n }\n },\n\n describe($element) {\n if ($element === undefined) {\n return 'undefined'\n } else if ($element.length === 0) {\n return '(no matching elements)'\n }\n return `${$element[0].outerHTML.split('>')[0]}>`\n }\n }\n\n setTransitionEndSupport()\n return Util\n\n})(jQuery)\n\nexport default Util\n","import Util from './util'\n\nconst Base = (($) => {\n\n const ClassName = {\n MDB_FORM_GROUP: 'mdb-form-group',\n IS_FILLED: 'is-filled',\n IS_FOCUSED: 'is-focused'\n }\n\n const Selector = {\n MDB_FORM_GROUP: `.${ClassName.MDB_FORM_GROUP}`\n }\n\n const Default = {}\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n class Base {\n\n /**\n *\n * @param element\n * @param config\n * @param properties - anything that needs to be set as this[key] = value. Works around the need to call `super` before using `this`\n */\n constructor($element, config, properties = {}) {\n this.$element = $element\n this.config = $.extend(true, {}, Default, config)\n\n // set properties for use in the constructor initialization\n for (let key in properties) {\n this[key] = properties[key]\n }\n }\n\n dispose(dataKey) {\n $.removeData(this.$element, dataKey)\n this.$element = null\n this.config = null\n }\n\n // ------------------------------------------------------------------------\n // protected\n\n addFormGroupFocus() {\n if (!this.$element.prop('disabled')) {\n this.$mdbFormGroup.addClass(ClassName.IS_FOCUSED)\n }\n }\n\n removeFormGroupFocus() {\n this.$mdbFormGroup.removeClass(ClassName.IS_FOCUSED)\n }\n\n removeIsFilled() {\n this.$mdbFormGroup.removeClass(ClassName.IS_FILLED)\n }\n\n addIsFilled() {\n this.$mdbFormGroup.addClass(ClassName.IS_FILLED)\n }\n\n // Find mdb-form-group\n findMdbFormGroup(raiseError = true) {\n let mfg = this.$element.closest(Selector.MDB_FORM_GROUP)\n if (mfg.length === 0 && raiseError) {\n $.error(`Failed to find ${Selector.MDB_FORM_GROUP} for ${Util.describe(this.$element)}`)\n }\n return mfg\n }\n\n // ------------------------------------------------------------------------\n // private\n\n // ------------------------------------------------------------------------\n // static\n\n }\n\n return Base\n\n})(jQuery)\n\nexport default Base\n","import Base from './base'\nimport Util from './util'\n\nconst BaseInput = (($) => {\n\n const ClassName = {\n FORM_GROUP: 'form-group',\n MDB_FORM_GROUP: 'mdb-form-group',\n MDB_LABEL: 'mdb-label',\n MDB_LABEL_STATIC: 'mdb-label-static',\n MDB_LABEL_PLACEHOLDER: 'mdb-label-placeholder',\n MDB_LABEL_FLOATING: 'mdb-label-floating',\n HAS_DANGER: 'has-danger',\n IS_FILLED: 'is-filled',\n IS_FOCUSED: 'is-focused'\n }\n\n const Selector = {\n FORM_GROUP: `.${ClassName.FORM_GROUP}`,\n MDB_FORM_GROUP: `.${ClassName.MDB_FORM_GROUP}`,\n MDB_LABEL_WILDCARD: `label[class^='${ClassName.MDB_LABEL}'], label[class*=' ${ClassName.MDB_LABEL}']` // match any label variant if specified\n }\n\n const Default = {\n validate: false,\n formGroup: {\n required: false\n },\n mdbFormGroup: {\n template: ``,\n create: true, // create a wrapper if form-group not found\n required: true // not recommended to turn this off, only used for inline components\n },\n label: {\n required: false,\n\n // Prioritized find order for resolving the label to be used as an mdb-label if not specified in the markup\n // - a function(thisComponent); or\n // - a string selector used like $mdbFormGroup.find(selector)\n //\n // Note this only runs if $mdbFormGroup.find(Selector.MDB_LABEL_WILDCARD) fails to find a label (as authored in the markup)\n //\n selectors: [\n `.form-control-label`, // in the case of horizontal or inline forms, this will be marked\n `> label` // usual case for text inputs, first child. Deeper would find toggle labels so don't do that.\n ],\n className: ClassName.MDB_LABEL_STATIC\n },\n requiredClasses: [],\n invalidComponentMatches: [],\n convertInputSizeVariations: true\n }\n\n const FormControlSizeMarkers = {\n 'form-control-lg': 'mdb-form-group-lg',\n 'form-control-sm': 'mdb-form-group-sm'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n class BaseInput extends Base {\n\n /**\n *\n * @param element\n * @param config\n * @param properties - anything that needs to be set as this[key] = value. Works around the need to call `super` before using `this`\n */\n constructor($element, config, properties = {}) {\n super($element, $.extend(true, {}, Default, config), properties)\n\n // Enforce no overlap between components to prevent side effects\n this._rejectInvalidComponentMatches()\n\n // Enforce expected structure (if any)\n this.rejectWithoutRequiredStructure()\n\n // Enforce required classes for a consistent rendering\n this._rejectWithoutRequiredClasses()\n\n // Resolve the form-group first, it will be used for mdb-form-group if possible\n // note: different components have different rules\n this.$formGroup = this.findFormGroup(this.config.formGroup.required)\n\n // Will add mdb-form-group to form-group or create an mdb-form-group\n // Performance Note: for those forms that are really performance driven, create the markup with the .mdb-form-group to avoid\n // rendering changes once added.\n this.$mdbFormGroup = this.resolveMdbFormGroup()\n\n // Resolve and mark the mdbLabel if necessary as defined by the config\n this.$mdbLabel = this.resolveMdbLabel()\n\n // Signal to the mdb-form-group that a form-control-* variation is being used\n this.resolveMdbFormGroupSizing()\n\n this.addFocusListener()\n this.addChangeListener()\n }\n\n dispose(dataKey) {\n super.dispose(dataKey)\n this.$mdbFormGroup = null\n this.$formGroup = null\n }\n\n // ------------------------------------------------------------------------\n // protected\n\n rejectWithoutRequiredStructure() {\n // implement\n }\n\n addFocusListener() {\n this.$element\n .on('focus', () => {\n this.addFormGroupFocus()\n })\n .on('blur', () => {\n this.removeFormGroupFocus()\n })\n }\n\n addChangeListener() {\n this.$element\n .on('keydown paste', (event) => {\n if (Util.isChar(event)) {\n this.addIsFilled()\n }\n })\n .on('keyup change', () => {\n\n // make sure empty is added back when there is a programmatic value change.\n // NOTE: programmatic changing of value using $.val() must trigger the change event i.e. $.val('x').trigger('change')\n if (this.isEmpty()) {\n this.removeIsFilled()\n } else {\n this.addIsFilled()\n }\n\n if (this.config.validate) {\n // Validation events do not bubble, so they must be attached directly to the text: http://jsfiddle.net/PEpRM/1/\n // Further, even the bind method is being caught, but since we are already calling #checkValidity here, just alter\n // the form-group on change.\n //\n // NOTE: I'm not sure we should be intervening regarding validation, this seems better as a README and snippet of code.\n // BUT, I've left it here for backwards compatibility.\n let isValid = (typeof this.$element[0].checkValidity === 'undefined' || this.$element[0].checkValidity())\n if (isValid) {\n this.removeHasDanger()\n } else {\n this.addHasDanger()\n }\n }\n })\n }\n\n addHasDanger() {\n this.$mdbFormGroup.addClass(ClassName.HAS_DANGER)\n }\n\n removeHasDanger() {\n this.$mdbFormGroup.removeClass(ClassName.HAS_DANGER)\n }\n\n isEmpty() {\n return (this.$element.val() === null || this.$element.val() === undefined || this.$element.val() === '')\n }\n\n // Will add mdb-form-group to form-group or create a mdb-form-group if necessary\n resolveMdbFormGroup() {\n let mfg = this.findMdbFormGroup(false)\n if (mfg === undefined || mfg.length === 0) {\n if (this.config.mdbFormGroup.create && (this.$formGroup === undefined || this.$formGroup.length === 0)) {\n // If a form-group doesn't exist (not recommended), take a guess and wrap the element (assuming no label).\n // note: it's possible to make this smarter, but I need to see valid cases before adding any complexity.\n this.outerElement().wrap(this.config.mdbFormGroup.template)\n } else {\n // a form-group does exist, add our marker class to it\n this.$formGroup.addClass(ClassName.MDB_FORM_GROUP)\n\n // OLD: may want to implement this after all, see how the styling turns out, but using an existing form-group is less manipulation of the dom and therefore preferable\n // A form-group does exist, so add an mdb-form-group wrapping it's internal contents\n //fg.wrapInner(this.config.mdbFormGroup.template)\n }\n\n mfg = this.findMdbFormGroup(this.config.mdbFormGroup.required)\n }\n\n return mfg\n }\n\n // Demarcation element (e.g. first child of a form-group)\n // Subclasses such as file inputs may have different structures\n outerElement() {\n return this.$element\n }\n\n // Will add mdb-label to mdb-form-group if not already specified\n resolveMdbLabel() {\n\n let label = this.$mdbFormGroup.find(Selector.MDB_LABEL_WILDCARD)\n if (label === undefined || label.length === 0) {\n // we need to find it based on the configured selectors\n label = this.findMdbLabel(this.config.label.required)\n\n if (label === undefined || label.length === 0) {\n // no label found, and finder did not require one\n } else {\n // a candidate label was found, add the configured default class name\n label.addClass(this.config.label.className)\n }\n }\n\n return label\n }\n\n // Find mdb-label variant based on the config selectors\n findMdbLabel(raiseError = true) {\n let label = null\n\n // use the specified selector order\n for (let selector of this.config.label.selectors) {\n if ($.isFunction(selector)) {\n label = selector(this)\n } else {\n label = this.$mdbFormGroup.find(selector)\n }\n\n if (label !== undefined && label.length > 0) {\n break\n }\n }\n\n if (label.length === 0 && raiseError) {\n $.error(`Failed to find ${Selector.MDB_LABEL_WILDCARD} within form-group for ${Util.describe(this.$element)}`)\n }\n return label\n }\n\n // Find mdb-form-group\n findFormGroup(raiseError = true) {\n let fg = this.$element.closest(Selector.FORM_GROUP)\n if (fg.length === 0 && raiseError) {\n $.error(`Failed to find ${Selector.FORM_GROUP} for ${Util.describe(this.$element)}`)\n }\n return fg\n }\n\n // Due to the interconnected nature of labels/inputs/help-blocks, signal the mdb-form-group-* size variation based on\n // a found form-control-* size\n resolveMdbFormGroupSizing() {\n if (!this.config.convertInputSizeVariations) {\n return\n }\n\n // Modification - Change text-sm/lg to form-group-sm/lg instead (preferred standard and simpler css/less variants)\n for (let inputSize in FormControlSizeMarkers) {\n if (this.$element.hasClass(inputSize)) {\n //this.$element.removeClass(inputSize)\n this.$mdbFormGroup.addClass(FormControlSizeMarkers[inputSize])\n }\n }\n }\n\n // ------------------------------------------------------------------------\n // private\n _rejectInvalidComponentMatches() {\n for (let otherComponent of this.config.invalidComponentMatches) {\n otherComponent.rejectMatch(this.constructor.name, this.$element)\n }\n }\n\n _rejectWithoutRequiredClasses() {\n for (let requiredClass of this.config.requiredClasses) {\n\n let found = false\n // allow one of several classes to be passed in x||y\n if (requiredClass.indexOf('||') !== -1) {\n let oneOf = requiredClass.split('||')\n for (let requiredClass of oneOf) {\n if (this.$element.hasClass(requiredClass)) {\n found = true\n break\n }\n }\n } else if (this.$element.hasClass(requiredClass)) {\n found = true\n }\n\n // error if not found\n if (!found) {\n $.error(`${this.constructor.name} element: ${Util.describe(this.$element)} requires class: ${requiredClass}`)\n }\n }\n }\n\n // ------------------------------------------------------------------------\n // static\n\n }\n\n return BaseInput\n\n})(jQuery)\n\nexport default BaseInput\n","import BaseInput from './baseInput'\nimport Util from './util'\n\nconst BaseSelection = (($) => {\n\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n const Default = {\n label: {\n required: false\n\n // Prioritized find order for resolving the label to be used as an mdb-label if not specified in the markup\n // - a function(thisComponent); or\n // - a string selector used like $mdbFormGroup.find(selector)\n //\n // Note this only runs if $mdbFormGroup.find(Selector.MDB_LABEL_WILDCARD) fails to find a label (as authored in the markup)\n //\n //selectors: [\n // `.form-control-label`, // in the case of horizontal or inline forms, this will be marked\n // `> label` // usual case for text inputs\n //]\n }\n }\n\n const Selector = {\n LABEL: 'label'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n class BaseSelection extends BaseInput {\n\n constructor($element, config, properties) {\n // properties = {inputType: checkbox, outerClass: checkbox-inline}\n // '.checkbox|switch|radio > label > input[type=checkbox|radio]'\n // '.${this.outerClass} > label > input[type=${this.inputType}]'\n\n super($element, $.extend(true, {}, Default, config), properties)\n this.decorateMarkup()\n }\n\n // ------------------------------------------------------------------------\n // protected\n\n decorateMarkup() {\n this.$element.after(this.config.template)\n }\n\n // Demarcation element (e.g. first child of a form-group)\n outerElement() {\n // .checkbox|switch|radio > label > input[type=checkbox|radio]\n // label.checkbox-inline > input[type=checkbox|radio]\n // .${this.outerClass} > label > input[type=${this.inputType}]\n return this.$element.parent().closest(`.${this.outerClass}`)\n }\n\n rejectWithoutRequiredStructure() {\n // '.checkbox|switch|radio > label > input[type=checkbox|radio]'\n // '.${this.outerClass} > label > input[type=${this.inputType}]'\n Util.assert(this.$element, !this.$element.parent().prop('tagName') === 'label', `${this.constructor.name}'s ${Util.describe(this.$element)} parent element should be