(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('bootstrap/js/src/alert'), require('bootstrap/js/src/button'), require('bootstrap/js/src/carousel'), require('bootstrap/js/src/collapse'), require('bootstrap/js/src/modal'), require('bootstrap/js/src/popover'), require('bootstrap/js/src/scrollspy'), require('bootstrap/js/src/tab'), require('bootstrap/js/src/tooltip'), require('bootstrap/js/src/util')) : typeof define === 'function' && define.amd ? define(['bootstrap/js/src/alert', 'bootstrap/js/src/button', 'bootstrap/js/src/carousel', 'bootstrap/js/src/collapse', 'bootstrap/js/src/modal', 'bootstrap/js/src/popover', 'bootstrap/js/src/scrollspy', 'bootstrap/js/src/tab', 'bootstrap/js/src/tooltip', 'bootstrap/js/src/util'], factory) : (factory(null,null,null,null,null,null,null,null,null,global.Util)); }(this, (function (alert,button,carousel,collapse,modal,popover,scrollspy,tab,tooltip,Util) { 'use strict'; Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var Util$1 = function () { /** * ------------------------------------------------------------------------ * Private TransitionEnd Helpers * ------------------------------------------------------------------------ */ var transitionEnd = false; var _transitionEndSelector = ""; var TransitionEndEvent = { WebkitTransition: "webkitTransitionEnd", MozTransition: "transitionend", OTransition: "oTransitionEnd otransitionend", transition: "transitionend" }; function transitionEndTest() { if (window.QUnit) { return false; } var el = document.createElement("bmd"); for (var name in TransitionEndEvent) { if (el.style[name] !== undefined) { return TransitionEndEvent[name]; // { end: TransitionEndEvent[name] } } } return false; } function setTransitionEndSupport() { transitionEnd = transitionEndTest(); // generate a concatenated transition end event selector for (var name in TransitionEndEvent) { _transitionEndSelector += " " + TransitionEndEvent[name]; } } /** * -------------------------------------------------------------------------- * Public Util Api * -------------------------------------------------------------------------- */ var Util$$1 = { transitionEndSupported: function transitionEndSupported() { return transitionEnd; }, transitionEndSelector: function transitionEndSelector() { return _transitionEndSelector; }, isChar: function isChar(event) { if (typeof event.which === "undefined") { return true; } else if (typeof event.which === "number" && event.which > 0) { return !event.ctrlKey && !event.metaKey && !event.altKey && event.which !== 8 && // backspace event.which !== 9 && // tab event.which !== 13 && // enter event.which !== 16 && // shift event.which !== 17 && // ctrl event.which !== 20 && // caps lock event.which !== 27 // escape ; } return false; }, assert: function assert($element, invalidTest, message) { if (invalidTest) { if (!$element === undefined) { $element.css("border", "1px solid red"); } console.error(message, $element); // eslint-disable-line no-console throw message; } }, describe: function describe($element) { if ($element === undefined) { return "undefined"; } else if ($element.length === 0) { return "(no matching elements)"; } return $element[0].outerHTML.split(">")[0] + ">"; } }; setTransitionEndSupport(); return Util$$1; }(jQuery); var Base = function ($) { var ClassName = { BMD_FORM_GROUP: "bmd-form-group", IS_FILLED: "is-filled", IS_FOCUSED: "is-focused" }; var Selector = { BMD_FORM_GROUP: "." + ClassName.BMD_FORM_GROUP }; var Default = {}; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ var Base = /*#__PURE__*/ function () { /** * * @param element * @param config * @param properties - anything that needs to be set as this[key] = value. Works around the need to call `super` before using `this` */ function Base($element, config, properties) { if (properties === void 0) { properties = {}; } this.$element = $element; this.config = $.extend(true, {}, Default, config); // set properties for use in the constructor initialization for (var key in properties) { this[key] = properties[key]; } } var _proto = Base.prototype; _proto.dispose = function dispose(dataKey) { this.$element.data(dataKey, null); this.$element = null; this.config = null; }; // ------------------------------------------------------------------------ // protected _proto.addFormGroupFocus = function addFormGroupFocus() { if (!this.$element.prop("disabled")) { this.$bmdFormGroup.addClass(ClassName.IS_FOCUSED); } }; _proto.removeFormGroupFocus = function removeFormGroupFocus() { this.$bmdFormGroup.removeClass(ClassName.IS_FOCUSED); }; _proto.removeIsFilled = function removeIsFilled() { this.$bmdFormGroup.removeClass(ClassName.IS_FILLED); }; _proto.addIsFilled = function addIsFilled() { this.$bmdFormGroup.addClass(ClassName.IS_FILLED); }; // Find bmd-form-group _proto.findMdbFormGroup = function findMdbFormGroup(raiseError) { if (raiseError === void 0) { raiseError = true; } var mfg = this.$element.closest(Selector.BMD_FORM_GROUP); if (mfg.length === 0 && raiseError) { $.error("Failed to find " + Selector.BMD_FORM_GROUP + " for " + Util$1.describe(this.$element)); } return mfg; }; // ------------------------------------------------------------------------ // private // ------------------------------------------------------------------------ // static return Base; }(); return Base; }(jQuery); var BaseInput = function ($) { var ClassName = { FORM_GROUP: "form-group", BMD_FORM_GROUP: "bmd-form-group", BMD_LABEL: "bmd-label", BMD_LABEL_STATIC: "bmd-label-static", BMD_LABEL_PLACEHOLDER: "bmd-label-placeholder", BMD_LABEL_FLOATING: "bmd-label-floating", HAS_DANGER: "has-danger", IS_FILLED: "is-filled", IS_FOCUSED: "is-focused", INPUT_GROUP: "input-group" }; var Selector = { FORM_GROUP: "." + ClassName.FORM_GROUP, BMD_FORM_GROUP: "." + ClassName.BMD_FORM_GROUP, BMD_LABEL_WILDCARD: "label[class^='" + ClassName.BMD_LABEL + "'], label[class*=' " + ClassName.BMD_LABEL + "']" // match any label variant if specified }; var Default = { validate: false, formGroup: { required: false }, bmdFormGroup: { template: "", create: true, // create a wrapper if form-group not found required: true // not recommended to turn this off, only used for inline components }, label: { required: false, // Prioritized find order for resolving the label to be used as an bmd-label if not specified in the markup // - a function(thisComponent); or // - a string selector used like $bmdFormGroup.find(selector) // // Note this only runs if $bmdFormGroup.find(Selector.BMD_LABEL_WILDCARD) fails to find a label (as authored in the markup) // selectors: [".form-control-label", // in the case of horizontal or inline forms, this will be marked "> label" // usual case for text inputs, first child. Deeper would find toggle labels so don't do that. ], className: ClassName.BMD_LABEL_STATIC }, requiredClasses: [], invalidComponentMatches: [], convertInputSizeVariations: true }; var FormControlSizeMarkers = { "form-control-lg": "bmd-form-group-lg", "form-control-sm": "bmd-form-group-sm" }; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ var BaseInput = /*#__PURE__*/ function (_Base) { _inheritsLoose(BaseInput, _Base); /** * * @param element * @param config * @param properties - anything that needs to be set as this[key] = value. Works around the need to call `super` before using `this` */ function BaseInput($element, config, properties) { var _this; if (properties === void 0) { properties = {}; } _this = _Base.call(this, $element, $.extend(true, {}, Default, config), properties) || this; // Enforce no overlap between components to prevent side effects _this._rejectInvalidComponentMatches(); // Enforce expected structure (if any) _this.rejectWithoutRequiredStructure(); // Enforce required classes for a consistent rendering _this._rejectWithoutRequiredClasses(); // Resolve the form-group first, it will be used for bmd-form-group if possible // note: different components have different rules _this.$formGroup = _this.findFormGroup(_this.config.formGroup.required); // Will add bmd-form-group to form-group or create an bmd-form-group // Performance Note: for those forms that are really performance driven, create the markup with the .bmd-form-group to avoid // rendering changes once added. _this.$bmdFormGroup = _this.resolveMdbFormGroup(); // Resolve and mark the bmdLabel if necessary as defined by the config _this.$bmdLabel = _this.resolveMdbLabel(); // Signal to the bmd-form-group that a form-control-* variation is being used _this.resolveMdbFormGroupSizing(); _this.addFocusListener(); _this.addChangeListener(); if (_this.$element.val() != "") { _this.addIsFilled(); } return _this; } var _proto = BaseInput.prototype; _proto.dispose = function dispose(dataKey) { _Base.prototype.dispose.call(this, dataKey); this.$bmdFormGroup = null; this.$formGroup = null; }; // ------------------------------------------------------------------------ // protected _proto.rejectWithoutRequiredStructure = function rejectWithoutRequiredStructure() {// implement }; _proto.addFocusListener = function addFocusListener() { var _this2 = this; this.$element.on("focus", function () { _this2.addFormGroupFocus(); }).on("blur", function () { _this2.removeFormGroupFocus(); }); }; _proto.addChangeListener = function addChangeListener() { var _this3 = this; this.$element.on("keydown paste", function (event) { if (Util$1.isChar(event)) { _this3.addIsFilled(); } }).on("keyup change", function () { // make sure empty is added back when there is a programmatic value change. // NOTE: programmatic changing of value using $.val() must trigger the change event i.e. $.val('x').trigger('change') if (_this3.isEmpty()) { _this3.removeIsFilled(); } else { _this3.addIsFilled(); } if (_this3.config.validate) { // Validation events do not bubble, so they must be attached directly to the text: http://jsfiddle.net/PEpRM/1/ // Further, even the bind method is being caught, but since we are already calling #checkValidity here, just alter // the form-group on change. // // NOTE: I'm not sure we should be intervening regarding validation, this seems better as a README and snippet of code. // BUT, I've left it here for backwards compatibility. var isValid = typeof _this3.$element[0].checkValidity === "undefined" || _this3.$element[0].checkValidity(); if (isValid) { _this3.removeHasDanger(); } else { _this3.addHasDanger(); } } }); }; _proto.addHasDanger = function addHasDanger() { this.$bmdFormGroup.addClass(ClassName.HAS_DANGER); }; _proto.removeHasDanger = function removeHasDanger() { this.$bmdFormGroup.removeClass(ClassName.HAS_DANGER); }; _proto.isEmpty = function isEmpty() { return this.$element.val() === null || this.$element.val() === undefined || this.$element.val() === ""; }; // Will add bmd-form-group to form-group or create a bmd-form-group if necessary _proto.resolveMdbFormGroup = function resolveMdbFormGroup() { var mfg = this.findMdbFormGroup(false); if (mfg === undefined || mfg.length === 0) { if (this.config.bmdFormGroup.create && (this.$formGroup === undefined || this.$formGroup.length === 0)) { // If a form-group doesn't exist (not recommended), take a guess and wrap the element (assuming no label). // note: it's possible to make this smarter, but I need to see valid cases before adding any complexity. // this may be an input-group, wrap that instead if (this.outerElement().parent().hasClass(ClassName.INPUT_GROUP)) { this.outerElement().parent().wrap(this.config.bmdFormGroup.template); } else { this.outerElement().wrap(this.config.bmdFormGroup.template); } } else { // a form-group does exist, add our marker class to it this.$formGroup.addClass(ClassName.BMD_FORM_GROUP); // 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 // A form-group does exist, so add an bmd-form-group wrapping it's internal contents //fg.wrapInner(this.config.bmdFormGroup.template) } mfg = this.findMdbFormGroup(this.config.bmdFormGroup.required); } return mfg; }; // Demarcation element (e.g. first child of a form-group) // Subclasses such as file inputs may have different structures _proto.outerElement = function outerElement() { return this.$element; }; // Will add bmd-label to bmd-form-group if not already specified _proto.resolveMdbLabel = function resolveMdbLabel() { var label = this.$bmdFormGroup.find(Selector.BMD_LABEL_WILDCARD); if (label === undefined || label.length === 0) { // we need to find it based on the configured selectors label = this.findMdbLabel(this.config.label.required); if (label === undefined || label.length === 0) {// no label found, and finder did not require one } else { // a candidate label was found, add the configured default class name label.addClass(this.config.label.className); } } return label; }; // Find bmd-label variant based on the config selectors _proto.findMdbLabel = function findMdbLabel(raiseError) { if (raiseError === void 0) { raiseError = true; } var label = null; // use the specified selector order for (var _iterator = this.config.label.selectors, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref; if (_isArray) { if (_i >= _iterator.length) break; _ref = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) break; _ref = _i.value; } var _selector = _ref; if ($.isFunction(_selector)) { label = _selector(this); } else { label = this.$bmdFormGroup.find(_selector); } if (label !== undefined && label.length > 0) { break; } } if (label.length === 0 && raiseError) { $.error("Failed to find " + Selector.BMD_LABEL_WILDCARD + " within form-group for " + Util$1.describe(this.$element)); } return label; }; // Find bmd-form-group _proto.findFormGroup = function findFormGroup(raiseError) { if (raiseError === void 0) { raiseError = true; } var fg = this.$element.closest(Selector.FORM_GROUP); if (fg.length === 0 && raiseError) { $.error("Failed to find " + Selector.FORM_GROUP + " for " + Util$1.describe(this.$element)); } return fg; }; // Due to the interconnected nature of labels/inputs/help-blocks, signal the bmd-form-group-* size variation based on // a found form-control-* size _proto.resolveMdbFormGroupSizing = function resolveMdbFormGroupSizing() { if (!this.config.convertInputSizeVariations) { return; } // Modification - Change text-sm/lg to form-group-sm/lg instead (preferred standard and simpler css/less variants) for (var inputSize in FormControlSizeMarkers) { if (this.$element.hasClass(inputSize)) { //this.$element.removeClass(inputSize) this.$bmdFormGroup.addClass(FormControlSizeMarkers[inputSize]); } } }; // ------------------------------------------------------------------------ // private _proto._rejectInvalidComponentMatches = function _rejectInvalidComponentMatches() { for (var _iterator2 = this.config.invalidComponentMatches, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { var _ref2; if (_isArray2) { if (_i2 >= _iterator2.length) break; _ref2 = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; _ref2 = _i2.value; } var _otherComponent = _ref2; _otherComponent.rejectMatch(this.constructor.name, this.$element); } }; _proto._rejectWithoutRequiredClasses = function _rejectWithoutRequiredClasses() { for (var _iterator3 = this.config.requiredClasses, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { var _ref3; if (_isArray3) { if (_i3 >= _iterator3.length) break; _ref3 = _iterator3[_i3++]; } else { _i3 = _iterator3.next(); if (_i3.done) break; _ref3 = _i3.value; } var _requiredClass = _ref3; if (_requiredClass.indexOf("||") !== -1) { var oneOf = _requiredClass.split("||"); for (var _iterator4 = oneOf, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { var _ref4; if (_isArray4) { if (_i4 >= _iterator4.length) break; _ref4 = _iterator4[_i4++]; } else { _i4 = _iterator4.next(); if (_i4.done) break; _ref4 = _i4.value; } var _requiredClass3 = _ref4; if (this.$element.hasClass(_requiredClass3)) { break; } } } else if (this.$element.hasClass(_requiredClass)) { } } }; // ------------------------------------------------------------------------ // static return BaseInput; }(Base); return BaseInput; }(jQuery); var BaseSelection = function ($) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var Default = { label: { required: false // Prioritized find order for resolving the label to be used as an bmd-label if not specified in the markup // - a function(thisComponent); or // - a string selector used like $bmdFormGroup.find(selector) // // Note this only runs if $bmdFormGroup.find(Selector.BMD_LABEL_WILDCARD) fails to find a label (as authored in the markup) // //selectors: [ // `.form-control-label`, // in the case of horizontal or inline forms, this will be marked // `> label` // usual case for text inputs //] } }; var Selector = { LABEL: "label" }; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ var BaseSelection = /*#__PURE__*/ function (_BaseInput) { _inheritsLoose(BaseSelection, _BaseInput); function BaseSelection($element, config, properties) { var _this; // properties = {inputType: checkbox, outerClass: checkbox-inline} // '.checkbox|switch|radio > label > input[type=checkbox|radio]' // '.${this.outerClass} > label > input[type=${this.inputType}]' _this = _BaseInput.call(this, $element, $.extend(true, {}, Default, config), properties) || this; _this.decorateMarkup(); return _this; } // ------------------------------------------------------------------------ // protected var _proto = BaseSelection.prototype; _proto.decorateMarkup = function decorateMarkup() { var $decorator = $(this.config.template); this.$element.after($decorator); // initialize ripples after decorator has been inserted into DOM if (this.config.ripples !== false) { $decorator.bmdRipples(); } }; // Demarcation element (e.g. first child of a form-group) _proto.outerElement = function outerElement() { // .checkbox|switch|radio > label > input[type=checkbox|radio] // label.checkbox-inline > input[type=checkbox|radio] // .${this.outerClass} > label > input[type=${this.inputType}] return this.$element.parent().closest("." + this.outerClass); }; _proto.rejectWithoutRequiredStructure = function rejectWithoutRequiredStructure() { // '.checkbox|switch|radio > label > input[type=checkbox|radio]' // '.${this.outerClass} > label > input[type=${this.inputType}]' Util$1.assert(this.$element, !this.$element.parent().prop("tagName") === "label", this.constructor.name + "'s " + Util$1.describe(this.$element) + " parent element should be