mdb-ui-kit/js/bootstrapMaterialDesign.js

213 lines
6.9 KiB
JavaScript
Raw Normal View History

/* globals Popper */
Popper.Defaults.modifiers.computeStyle.gpuAcceleration = false
/**
* $.bootstrapMaterialDesign(config) is a macro class to configure the components generally
2017-03-22 16:10:37 +03:00
* used in Material Design for Bootstrap. You may pass overrides to the configurations
* which will be passed into each component, or you may omit use of this class and
* configure each component separately.
*/
2017-08-11 17:59:31 +03:00
const BootstrapMaterialDesign = ($ => {
/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/
2017-08-11 17:59:31 +03:00
const NAME = "bootstrapMaterialDesign";
const DATA_KEY = `bmd.${NAME}`;
const JQUERY_NAME = NAME; // retain this full name since it is long enough not to conflict
const JQUERY_NO_CONFLICT = $.fn[JQUERY_NAME];
/**
* Global configuration:
* The global configuration hash will be mixed in to each components' config.
* e.g. calling $.bootstrapMaterialDesign({global: { validate: true } }) would pass `validate:true` to every component
*
*
* Component configuration:
* - selector: may be a string or an array. Any array will be joined with a comma to generate the selector
* - disable any component by defining it as false with an override. e.g. $.bootstrapMaterialDesign({ autofill: false })
*
* @see each individual component for more configuration settings.
*/
const Default = {
global: {
validate: false,
label: {
2017-08-11 17:59:31 +03:00
className: "bmd-label-static" // default style of label to be used if not specified in the html markup
}
},
autofill: {
2017-08-11 17:59:31 +03:00
selector: "body"
},
checkbox: {
2017-08-11 17:59:31 +03:00
selector: ".checkbox > label > input[type=checkbox]"
},
checkboxInline: {
2017-08-11 17:59:31 +03:00
selector: "label.checkbox-inline > input[type=checkbox]"
},
collapseInline: {
selector: '.bmd-collapse-inline [data-toggle="collapse"]'
},
drawer: {
2017-08-11 17:59:31 +03:00
selector: ".bmd-layout-drawer"
},
file: {
2017-08-11 17:59:31 +03:00
selector: "input[type=file]"
},
radio: {
2017-08-11 17:59:31 +03:00
selector: ".radio > label > input[type=radio]"
},
radioInline: {
2017-08-11 17:59:31 +03:00
selector: "label.radio-inline > input[type=radio]"
},
ripples: {
//selector: ['.btn:not(.btn-link):not(.ripple-none)'] // testing only
selector: [
2017-08-11 17:59:31 +03:00
".btn:not(.btn-link):not(.ripple-none)",
".card-image:not(.ripple-none)",
".navbar a:not(.ripple-none)",
".dropdown-menu a:not(.ripple-none)",
".nav-tabs a:not(.ripple-none)",
".pagination li:not(.active):not(.disabled) a:not(.ripple-none)",
".ripple" // generic marker class to add ripple to elements
]
},
select: {
2017-08-11 17:59:31 +03:00
selector: ["select"]
},
switch: {
2017-08-11 17:59:31 +03:00
selector: ".switch > label > input[type=checkbox]"
},
text: {
// omit inputs we have specialized components to handle - we need to match text, email, etc. The easiest way to do this appears to be just omit the ones we don't want to match and let the rest fall through to this.
2017-08-11 17:59:31 +03:00
selector: [
`input:not([type=hidden]):not([type=checkbox]):not([type=radio]):not([type=file]):not([type=button]):not([type=submit]):not([type=reset])`
]
},
textarea: {
2017-08-11 17:59:31 +03:00
selector: ["textarea"]
},
arrive: true,
// create an ordered component list for instantiation
instantiation: [
2017-08-11 17:59:31 +03:00
"ripples",
"checkbox",
"checkboxInline",
"collapseInline",
"drawer",
//'file',
2017-08-11 17:59:31 +03:00
"radio",
"radioInline",
"switch",
"text",
"textarea",
"select",
"autofill"
]
2017-08-11 17:59:31 +03:00
};
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
class BootstrapMaterialDesign {
constructor($element, config) {
2017-08-11 17:59:31 +03:00
this.$element = $element;
this.config = $.extend(true, {}, Default, config);
let $document = $(document);
for (let component of this.config.instantiation) {
// the component's config fragment is passed in directly, allowing users to override
2017-08-11 17:59:31 +03:00
let componentConfig = this.config[component];
// check to make sure component config is enabled (not `false`)
if (componentConfig) {
// assemble the selector as it may be an array
2017-08-11 17:59:31 +03:00
let selector = this._resolveSelector(componentConfig);
// mix in global options
2017-08-11 17:59:31 +03:00
componentConfig = $.extend(
true,
{},
this.config.global,
componentConfig
);
// create the jquery fn name e.g. 'bmdText' for 'text'
2017-08-11 17:59:31 +03:00
let componentName = `${component.charAt(0).toUpperCase() +
component.slice(1)}`;
let jqueryFn = `bmd${componentName}`;
try {
// safely instantiate component on selector elements with config, report errors and move on.
// console.debug(`instantiating: $('${selector}')[${jqueryFn}](${componentConfig})`) // eslint-disable-line no-console
2017-08-11 17:59:31 +03:00
$(selector)[jqueryFn](componentConfig);
// add to arrive if present and enabled
if (document.arrive && this.config.arrive) {
2017-08-11 17:59:31 +03:00
$document.arrive(selector, function() {
// eslint-disable-line no-loop-func
$(this)[jqueryFn](componentConfig);
});
}
} catch (e) {
2017-08-11 17:59:31 +03:00
let message = `Failed to instantiate component: $('${selector}')[${jqueryFn}](${componentConfig})`;
console.error(message, e, `\nSelected elements: `, $(selector)); // eslint-disable-line no-console
throw e;
}
}
}
}
dispose() {
2017-08-11 17:59:31 +03:00
this.$element.data(DATA_KEY, null);
this.$element = null;
this.config = null;
}
// ------------------------------------------------------------------------
// private
_resolveSelector(componentConfig) {
2017-08-11 17:59:31 +03:00
let selector = componentConfig.selector;
if (Array.isArray(selector)) {
2017-08-11 17:59:31 +03:00
selector = selector.join(", ");
}
2017-08-11 17:59:31 +03:00
return selector;
}
// ------------------------------------------------------------------------
// static
static _jQueryInterface(config) {
2017-08-11 17:59:31 +03:00
return this.each(function() {
let $element = $(this);
let data = $element.data(DATA_KEY);
if (!data) {
2017-08-11 17:59:31 +03:00
data = new BootstrapMaterialDesign($element, config);
$element.data(DATA_KEY, data);
}
2017-08-11 17:59:31 +03:00
});
}
}
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/
2017-08-11 17:59:31 +03:00
$.fn[JQUERY_NAME] = BootstrapMaterialDesign._jQueryInterface;
$.fn[JQUERY_NAME].Constructor = BootstrapMaterialDesign;
$.fn[JQUERY_NAME].noConflict = () => {
2017-08-11 17:59:31 +03:00
$.fn[JQUERY_NAME] = JQUERY_NO_CONFLICT;
return BootstrapMaterialDesign._jQueryInterface;
};
2017-08-11 17:59:31 +03:00
return BootstrapMaterialDesign;
})(jQuery);
2017-08-11 17:59:31 +03:00
export default BootstrapMaterialDesign;