diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..f8658b4 --- /dev/null +++ b/.babelrc @@ -0,0 +1,22 @@ +{ + "plugins": [ + ["@babel/plugin-transform-runtime", { + "helpers": true, + "forceAllTransforms": false + }] + ], + "presets": [ + ["@babel/preset-env", { + "debug": false, + "useBuiltIns": "usage", + "corejs": "3.6", + "modules": "auto", + "targets": { + "browsers": [ + "last 2 versions", + "ie >= 11" + ] + } + }] + ] +} \ No newline at end of file diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 976ba4c..0000000 --- a/.eslintrc +++ /dev/null @@ -1,168 +0,0 @@ -{ - "env": { - "browser": true, - "node": true, - "jquery": true, - "es6": true - }, - - "ecmaFeatures": { - "modules": true - }, - - "rules": { - "accessor-pairs": 2, - "array-bracket-spacing": 0, - "block-scoped-var": 0, - "brace-style": [2, "stroustrup", { "allowSingleLine": true }], - "camelcase": 0, - "comma-dangle": [2, "never"], - "comma-spacing": [2, { "before": false, "after": true }], - "comma-style": [2, "last"], - "complexity": 0, - "computed-property-spacing": 0, - "consistent-return": 0, - "consistent-this": 0, - "constructor-super": 2, - "curly": [2, "multi-line"], - "default-case": 0, - "dot-location": [2, "property"], - "dot-notation": 0, - "eol-last": 0, - "eqeqeq": [2, "allow-null"], - "func-names": 0, - "func-style": 0, - "generator-star-spacing": [2, { "before": true, "after": true }], - "guard-for-in": 0, - "handle-callback-err": [2, "^(err|error)$" ], - "indent": [2, 2, { "SwitchCase": 1 }], - "key-spacing": [2, { "beforeColon": false, "afterColon": true }], - "linebreak-style": 0, - "lines-around-comment": 0, - "max-nested-callbacks": 0, - "new-cap": [2, { "newIsCap": true, "capIsNew": false }], - "new-parens": 2, - "newline-after-var": 0, - "no-alert": 0, - "no-array-constructor": 2, - "no-caller": 2, - "no-catch-shadow": 0, - "no-cond-assign": 2, - "no-console": 0, - "no-constant-condition": 0, - "no-continue": 0, - "no-control-regex": 2, - "no-debugger": 2, - "no-delete-var": 2, - "no-div-regex": 0, - "no-dupe-args": 2, - "no-dupe-keys": 2, - "no-duplicate-case": 2, - "no-else-return": 0, - "no-empty": 0, - "no-empty-character-class": 2, - "no-empty-label": 2, - "no-eq-null": 0, - "no-eval": 2, - "no-ex-assign": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-extra-boolean-cast": 2, - "no-extra-parens": 0, - "no-extra-semi": 0, - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-func-assign": 2, - "no-implied-eval": 2, - "no-inline-comments": 0, - "no-inner-declarations": [2, "functions"], - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-iterator": 2, - "no-label-var": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-lonely-if": 0, - "no-loop-func": 0, - "no-mixed-requires": 0, - "no-mixed-spaces-and-tabs": 2, - "no-multi-spaces": 2, - "no-multi-str": 2, - "no-multiple-empty-lines": [2, { "max": 1 }], - "no-native-reassign": 2, - "no-negated-in-lhs": 2, - "no-nested-ternary": 0, - "no-new": 2, - "no-new-func": 0, - "no-new-object": 2, - "no-new-require": 2, - "no-new-wrappers": 2, - "no-obj-calls": 2, - "no-octal": 2, - "no-octal-escape": 2, - "no-param-reassign": 0, - "no-path-concat": 0, - "no-process-env": 0, - "no-process-exit": 0, - "no-proto": 0, - "no-redeclare": 2, - "no-regex-spaces": 2, - "no-restricted-modules": 0, - "no-return-assign": 2, - "no-script-url": 0, - "no-self-compare": 2, - "no-sequences": 2, - "no-shadow": 0, - "no-shadow-restricted-names": 2, - "no-spaced-func": 2, - "no-sparse-arrays": 2, - "no-sync": 0, - "no-ternary": 0, - "no-this-before-super": 2, - "no-throw-literal": 2, - "no-trailing-spaces": 0, - "no-undef": 2, - "no-undef-init": 2, - "no-undefined": 0, - "no-underscore-dangle": 0, - "no-unexpected-multiline": 2, - "no-unneeded-ternary": 2, - "no-unreachable": 2, - "no-unused-expressions": 0, - "no-unused-vars": [2, { "vars": "all", "args": "none" }], - "no-use-before-define": 0, - "no-var": 0, - "no-void": 0, - "no-warning-comments": 0, - "no-with": 2, - "object-curly-spacing": 0, - "object-shorthand": 0, - "one-var": [2, { "initialized": "never" }], - "operator-assignment": 0, - "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], - "padded-blocks": 0, - "prefer-const": 0, - "quote-props": 0, - "quotes": [2, "single", "avoid-escape"], - "radix": 2, - "semi": [2, "never"], - "semi-spacing": 0, - "sort-vars": 0, - "space-after-keywords": [2, "always"], - "space-before-blocks": [2, "always"], - "space-before-function-paren": [2, "always"], - "space-in-parens": [2, "never"], - "space-infix-ops": 2, - "space-return-throw-case": 2, - "space-unary-ops": [2, { "words": true, "nonwords": false }], - "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }], - "strict": 0, - "use-isnan": 2, - "valid-jsdoc": 0, - "valid-typeof": 2, - "vars-on-top": 0, - "wrap-iife": [2, "any"], - "wrap-regex": 0, - "yoda": [2, "never"] - } -} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 40b878d..d66559d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -node_modules/ \ No newline at end of file +node_modules/ +package-lock.json +mix-manifest.json \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..9cf9495 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false \ No newline at end of file diff --git a/README.md b/README.md index 3f18362..be689b9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,15 @@ The DOM factory provides a convenient API (inspired by Polymer) to enhance HTML ## Compatibility -- Supports ES5-compliant browsers (IE9+) +> Supports the last two versions of every major browser. + +- Chrome +- Safari +- Firefox +- IE 11/Edge +- Opera +- Mobile Safari +- Chrome on Android ## Installation @@ -50,11 +58,9 @@ A component definition is nothing more than a simple object factory (a function ```js /** * A component definition - * @param {HTMLElement} element * @return {Object} */ -const buttonComponent = (element) => ({ - element, +const buttonComponent = () => ({ /** * Properties part of the component's public API. @@ -63,7 +69,7 @@ const buttonComponent = (element) => ({ properties: { /** - * Maps to [a-property="value"] attribute + * Maps to [data-a-property="value"] attribute * Also sets a default property value * and updates the attribute on the HTMLElement * @type {Object} @@ -74,13 +80,25 @@ const buttonComponent = (element) => ({ }, /** - * Maps to [b-property] attribute + * Maps to [data-b-property] attribute * It removes the attribute when the property value is `false` * @type {Object} */ bProperty: { - type: Boolean, - reflectToAttribute: true + reflectToAttribute: true, + type: Boolean + }, + + /** + * Maps to [data-c-property] attribute + * It casts the value to a Number + * Sets the initial value to 0 + * @type {Object} + */ + cProperty: { + reflectToAttribute: true, + type: Number, + value: 0 } }, @@ -137,14 +155,45 @@ const buttonComponent = (element) => ({ handler.register('my-button', buttonComponent) ``` -#### Initialize the component +#### Initializing -The component handler attempts to self-initialize all registered components which match the component CSS class. The CSS class is computed automatically from the component ID which was provided at registration. +When calling the `autoInit()` method, the component handler attempts to self-initialize all registered components which match the component CSS class. The CSS class is computed automatically from the component ID which was provided at registration, prefixed with `js-`. -In this example, since we registered the `buttonComponent` with a component ID of `my-button`, the handler will try to initialize all the HTML elements which have the `my-js-button` CSS class. +In this example, since we registered the `buttonComponent` with a component ID of `my-button`, the handler will try to initialize all the HTML elements which have the `js-my-button` CSS class. ```html - + +``` + +```js +// Initialize all components on window.DOMContentLoaded and window.load events. +handler.autoInit() +``` + +You can also initialize components manually. + +```js +// Initialize all components immediately. +handler.upgradeAll() + +// Initialize all components on a single element. +var myButtonNode = document.querySelector('.js-my-button') +handler.upgradeElement(myButtonNode) + +// Initialize a single component on a single element. +handler.upgradeElement(myButtonNode, 'my-button') + +// Upgrade all elements matching a registered component ID. +handler.upgrade('my-button') +``` + +#### Downgrade + +Sometimes we need component lifecycle control when integrating with other libraries (Vue.js, Angular, etc). + +```js +var myButtonNode = document.querySelector('.js-my-button') +handler.downgradeElement(myButtonNode) ``` #### Interact with the component API @@ -168,18 +217,58 @@ console.log(button.aProperty) ```js button.aProperty = 'something else' button.bProperty = true +button.cProperty = 5 +``` + +When using the `reflectToAttribute: true` property option, the property reflects a string representation of it's value to the corresponding `data-*` attribute on the HTML element using the `dataset` API, which means you can use the HTML element attribute to configure the property value. + +#### Casting values + +Because component properties using `reflectToAttribute: true` are using the dataset API, all values are strings by default, but you can cast them to `Boolean` or `Number`. + +> Boolean + +When using a `Boolean` property type and assigning a property value of `true`, the attribute will be created on the HTML element with an empty value and when assigning a property value of `false`, the attribute will be removed from the DOM. + +For example, an attribute with an empty value called `[data-my-boolean-attribute]` will map to `button.myBooleanAttribute`. + +```html + +``` + +```js +`console.log(button.myBooleanAttribute) // => true` ``` -When using the `reflectToAttribute: true` property option, the property reflects a string representation of it's value to the corresponding attribute on the HTML element, which means you can use the attribute to target styles or to configure the property value. +> Number + +Cast the component property value to a `Number` by adding `type: Number` to the property definition. It returns `NaN` when the value is not a valid number. -When using a `Boolean` property type and assigning a property value of `true`, the attribute will be created with the same value as the attribute name and when assigning a property value of `false`, the attribute will be removed from the DOM. +```js +button.cProperty = '50' +console.log(button.cProperty) // => 50 + +button.cProperty = 'abc' +console.log(button.cProperty) // => NaN +``` ```html - ``` +```js +console.log(button.aProperty) // => 'something else' +console.log(button.bProperty) // => true +console.log(button.cProperty) // => 13 +``` + #### Destroy Calling the `destroy` method on the component reference, removes observers and event listeners. Useful before removing the HTML element from the DOM, for example when using libraries like Vue.js or Angular2 where you need to hook into the application lifecycle. diff --git a/build/webpack.config.dev.js b/build/webpack.config.dev.js deleted file mode 100644 index 0125e57..0000000 --- a/build/webpack.config.dev.js +++ /dev/null @@ -1,2 +0,0 @@ -var config = require('./webpack.config') -module.exports = config.dev({ devtool: 'eval-source-maps' }).getConfig() \ No newline at end of file diff --git a/build/webpack.config.js b/build/webpack.config.js deleted file mode 100644 index 281cb4a..0000000 --- a/build/webpack.config.js +++ /dev/null @@ -1,10 +0,0 @@ -var path = require('path') -var WebpackConfig = require('webpack-config-api') -var config = new WebpackConfig() - .addFileExtension('js') - .register('babel', require('webpack-config-api/extensions/babel')).use('babel') - .register('eslint', require('webpack-config-api/extensions/eslint')).use('eslint') - .withStandaloneEntry('dom-factory') - .withLibrary('domFactory') - -module.exports = config \ No newline at end of file diff --git a/build/webpack.config.production.js b/build/webpack.config.production.js deleted file mode 100644 index 8e8711d..0000000 --- a/build/webpack.config.production.js +++ /dev/null @@ -1,2 +0,0 @@ -var config = require('./webpack.config') -module.exports = config.production().getConfig() \ No newline at end of file diff --git a/dist/dom-factory.common.js b/dist/dom-factory.common.js new file mode 100644 index 0000000..4442485 --- /dev/null +++ b/dist/dom-factory.common.js @@ -0,0 +1,663 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function createCommonjsModule(fn, basedir, module) { + return module = { + path: basedir, + exports: {}, + require: function (path, base) { + return commonjsRequire(path, (base === undefined || base === null) ? module.path : base); + } + }, fn(module, module.exports), module.exports; +} + +function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); +} + +var watchObject = createCommonjsModule(function (module, exports) { +!function(t,e){module.exports=e();}(commonjsGlobal,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0}),e.unwatch=e.watch=void 0;var o=n(4),i=r(o),c=n(3),a=r(c),f=(e.watch=function(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];var r=e[1];_(r)?g.apply(void 0,e):f(r)?b.apply(void 0,e):w.apply(void 0,e);},e.unwatch=function(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];var r=e[1];_(r)||void 0===r?m.apply(void 0,e):f(r)?O.apply(void 0,e):x.apply(void 0,e);},function(t){return "[object Array]"==={}.toString.call(t)}),u=function(t){return "[object Object]"==={}.toString.call(t)},_=function(t){return "[object Function]"==={}.toString.call(t)},s=function(t,e,n){(0, a["default"])(t,e,{enumerable:!1,configurable:!0,writable:!1,value:n});},l=function(t,e,n,r){(0, a["default"])(t,e,{get:n,set:function(t){r.call(this,t);},enumerable:!0,configurable:!0});},p=function(t,e,n,r,o){var i=void 0,c=t.__watchers__[e];(i=t.__watchers__.__watchall__)&&(c=c?c.concat(i):i);for(var a=c?c.length:0,f=0;a>f;f++)c[f].call(t,n,r,e,o);},v=["pop","push","reverse","shift","sort","unshift","splice"],h=function(t,e,n,r){s(t,n,function(){for(var o=0,i=void 0,c=void 0,a=arguments.length,f=Array(a),u=0;a>u;u++)f[u]=arguments[u];if("splice"===n){var _=f[0],s=_+f[1];i=t.slice(_,s),c=[];for(var l=2;l0?f:void 0:f.length>0?f[0]:void 0;var p=e.apply(t,f);return "pop"===n?(i=p,o=t.length):"push"===n?o=t.length-1:"shift"===n?i=p:"unshift"!==n&&void 0===c&&(c=p),r.call(t,o,n,c,i),p});},d=function(t,e){if(_(e)&&t&&!(t instanceof String)&&f(t))for(var n=v.length;n>0;n--){var r=v[n-1];h(t,t[r],r,e);}},y=function(t,e,n,r){var o=!1,c=f(t);void 0===t.__watchers__&&(s(t,"__watchers__",{}),c&&d(t,function(n,o,i,c){if(p(t,n,i,c,o),0!==r&&i&&(u(i)||f(i))){var a=void 0,_=t.__watchers__[e];(a=t.__watchers__.__watchall__)&&(_=_?_.concat(a):a);for(var s=_?_.length:0,l=0;s>l;l++)if("splice"!==o)g(i,_[l],void 0===r?r:r-1);else for(var v=0;vi;i++)o[i]=arguments[i];return n[e].apply(t,o)});});var i=["writable","value"];i.forEach(function(t){void 0!==n[t]&&(r[t]=n[t]);}),(0, a["default"])(t.__proxy__,e,r);}():t.__proxy__[e]=t[e];var o=function(){return t.__proxy__[e]},c=function(n){var o=t.__proxy__[e];if(0!==r&&t[e]&&(u(t[e])||f(t[e]))&&!t[e].__watchers__)for(var i=0;i0)for(var r=0;r0)&&g(t[e],n,void 0!==r?r-1:r),y(t,e,n,r)));},b=function(t,e,n,r){if("string"!=typeof t&&(t instanceof Object||f(t)))for(var o=0;o (el instanceof HTMLElement); + +const isArray = (obj) => ({}.toString.call(obj) === '[object Array]'); + +const isFunction = (fn) => typeof fn === 'function'; + +const toKebabCase = (str) => str.replace(/([A-Z])/g, ($1) => `-${ $1 }`.toLowerCase()); + +/** + * Assign descriptors + * @param {Object} target + * @param {...Object} sources + * @return {Object} + */ +const assign = (target, ...sources) => { + sources.forEach(source => { + if (!source) { + return + } + let descriptors = Object.keys(source).reduce((descriptors, key) => { + descriptors[key] = Object.getOwnPropertyDescriptor(source, key); + return descriptors + }, {}); + Object.getOwnPropertySymbols(source).forEach(sym => { + let descriptor = Object.getOwnPropertyDescriptor(source, sym); + if (descriptor.enumerable) { + descriptors[sym] = descriptor; + } + }); + Object.defineProperties(target, descriptors); + }); + return target +}; + +/** + * Set the default property options + * @param {Object} opts + * @return {Object} + */ +const propOptions = (opts = {}) => { + opts = assign({}, opts); + opts.readOnly = opts.readOnly || false; + opts.reflectToAttribute = opts.reflectToAttribute || false; + opts.value = opts.value; + opts.type = opts.type; + return opts +}; + +/** + * Create property + * @param {String} prop The property name + * @param {Object} opts The property options + * @param {Object} src The source object + */ +const createProp = (prop, opts = {}, src) => { + opts = propOptions(opts); + const property = { + enumerable: true, + configurable: true, + writable: !opts.readOnly, + value: isFunction(opts.value) ? opts.value.call(src) : opts.value + }; + Object.defineProperty(src, prop, property); +}; + +/** + * Set the initial value for a property + * @param {String} prop The property name + * @param {Object} opts The property options + * @param {Object} src The source object + */ +const propValue = (prop, opts = {}, src, element) => { + opts = propOptions(opts); + if ((!opts.value && opts.value !== 0) || !!src[prop]) { + return + } + + if (opts.type === Boolean) { + src[prop] = opts.reflectToAttribute && element.dataset[prop] === 'false' + ? false + : opts.value; + } + else if (isFunction(opts.value)) { + src[prop] = opts.value.call(src); + } + else { + src[prop] = opts.value; + } +}; + +/** + * Keep a property value in sync with a HTMLElement attribute + * @param {String} prop The property name + * @param {Object} opts The property options + * @param {Object} src The source object + */ +const reflectToAttribute = (prop, opts = {}, src) => { + opts = propOptions(opts); + if (!opts.reflectToAttribute) { + return + } + const propKebab = toKebabCase(`data-${prop}`); + const descriptor = Object.getOwnPropertyDescriptor(src, prop); + const property = { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + get: function () { + if (opts.type === Boolean) { + return this.element.dataset[prop] === '' + } + if (opts.type === Number) { + return Number(this.element.dataset[prop]) + } + return this.element.dataset[prop] + }, + set: function (value) { + const removable = !value && value !== 0; + if (opts.type === Boolean || removable) { + return this.element[!removable ? 'setAttribute' : 'removeAttribute'](propKebab, opts.type === Boolean ? '' : value) + } + this.element.dataset[prop] = value; + } + }; + Object.defineProperty(src, prop, property); +}; + +/** + * Create properties + * @param {Object} src The source object + */ +const makeProperties = (src, element) => { + if (typeof src.properties !== 'object') { + return + } + for (let prop in src.properties) { + if (src.properties.hasOwnProperty(prop)) { + let opts = src.properties[prop]; + + createProp(prop, opts, src); + reflectToAttribute(prop, opts, src); + propValue(prop, opts, src, element); + } + } +}; + +const dotObject = (str, obj) => { + return str.split('.').reduce((o, i) => o[i], obj) +}; + +const dotObjectPropParent = (str, obj) => { + let dots = str.split('.'); + let prop = dots.pop(); + let parent = dotObject(dots.join('.'), obj); + return { + parent, + prop + } +}; + +/** + * Get the configuration for observers + * @param {Object} src The source object + * @return {Array} + */ +const observers = (src) => { + if (!isArray(src.observers)) { + return [] + } + return src.observers.map(sig => { + let [, fn, args] = sig.match(/([a-zA-Z-_]+)\(([^)]*)\)/); + args = args.split(',').map(a => a.trim()).filter(a => a.length); + return { + fn, + args + } + }) + .filter(({ fn }) => isFunction(src[fn])) +}; + +/** + * Create observers + * @param {Object} src The source object + */ +const makeObservers = (src) => { + observers(src).forEach(({ fn, args }) => { + src[fn] = src[fn].bind(src); + args.forEach(arg => { + if (arg.indexOf('.') !== -1) { + const { prop, parent } = dotObjectPropParent(arg, src); + watchObject.watch(parent, prop, src[fn]); + } + else { + watchObject.watch(src, arg, src[fn]); + } + }); + }); +}; + +/** + * Get the configuration for DOM event listeners + * @param {Object} src The source object + * @return {Array} + */ +const listeners = (src) => { + if (!isArray(src.listeners)) { + return [] + } + return src.listeners.map(sig => { + let match = sig.match(/(.*\.)?([a-zA-Z-_]+)\(([^)]*)\)/); + let [, element, fn, events] = match; + events = events.split(',').map(a => a.trim()).filter(a => a.length); + element = element ? element.substr(0, element.length - 1) : 'element'; + return { + element, + fn, + events + } + }) + .filter(({ element, fn }) => { + return isFunction(src[fn]) && ( + element === 'document' || + element === 'window' || + isElement(src[element]) || + (src[element] && isElement(src[element]['element']) )) + }) +}; + +/** + * Create DOM event listeners + * @param {Object} src The source object + */ +const makeListeners = (src) => { + listeners(src).forEach(({ element, fn, events }) => { + src[fn] = src[fn].bind(src); + if (element === 'document') { + element = src.element.ownerDocument; + } + else if (element === 'window') { + element = window; + } + else if (isElement(src[element])) { + element = src[element]; + } + else if (isElement(src[element]['element'])) { + element = src[element]['element']; + } + if (element) { + events.forEach(e => element.addEventListener(e, src[fn])); + } + }); +}; + +/** + * Get mixins + * @param {Object} src The source object + * @return {Array} + */ +const mixins = (src) => { + if (!isArray(src.mixins)) { + return [] + } + return src.mixins.filter(mixin => typeof mixin === 'object') +}; + +/** + * Merge mixins + * @param {Object} src The source object + */ +const makeMixins = (src) => { + const args = mixins(src); + args.unshift({}); + return assign.apply(null, args) +}; + +const factory = (factory, element) => { + if (!factory || + typeof factory !== 'object' || + !isElement(element)) { + console.error('[dom-factory] Invalid factory.', factory, element); + return + } + + factory.element = element; + + let component = { + + /** + * Set a property on the component + * @param {String} prop The property name + * @param {?} value The property value + */ + $set (prop, value) { + if (!prop || value === undefined || this.properties === undefined || !this.properties.hasOwnProperty(prop)) { + return + } + const opts = propOptions(this.properties[prop]); + const descriptor = Object.getOwnPropertyDescriptor(this, prop); + + if (opts.readOnly && descriptor.writable !== undefined) { + let property = { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: false, + value + }; + Object.defineProperty(this, prop, property); + return + } + + this[prop] = value; + }, + + /** + * Initialize component + */ + init () { + makeObservers(this); + makeListeners(this); + if (isFunction(factory.init)) { + factory.init.call(this); + } + }, + + /** + * Destroy component + */ + destroy () { + observers(factory).forEach(({ fn, args }) => { + args.forEach(arg => { + if (arg.indexOf('.') !== -1) { + const { prop, parent } = dotObjectPropParent(arg, this); + watchObject.unwatch(parent, prop, this[fn]); + } + else { + watchObject.unwatch(this, arg, this[fn]); + } + }); + }); + + listeners(factory).forEach(({ element, fn, events }) => { + if (element === 'document') { + element = this.element.ownerDocument; + } + else if (element === 'window') { + element = window; + } + else if (isElement(this[element])) { + element = this[element]; + } + else if (isElement(this[element]['element'])) { + element = this[element]['element']; + } + if (element) { + events.forEach(e => element.removeEventListener(e, this[fn])); + } + }); + + if (isFunction(factory.destroy)) { + factory.destroy.call(this); + } + }, + + /** + * Fire a DOM Event on the HTMLElement + * @param {String} eventName The event name + */ + fire (eventName) { + let event; + let bubbles = false; + if ('CustomEvent' in window && typeof window.CustomEvent === 'object') { + try { + event = new CustomEvent(eventName, { + bubbles, + cancelable: false + }); + } + catch (e) { + event = new this.CustomEvent_(eventName, { + bubbles, + cancelable: false + }); + } + } + else { + event = document.createEvent('Event'); + event.initEvent(eventName, bubbles, true); + } + this.element.dispatchEvent(event); + }, + + CustomEvent_ (event, params) { + params = params || { bubbles: false, cancelable: false, detail: undefined }; + var evt = document.createEvent('CustomEvent'); + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); + return evt + } + }; + + makeProperties(factory, element); + + component = assign( + {}, + makeMixins(factory), + factory, + component + ); + + component.init(); + + return component +}; + +const toCamelCase = (str) => str.replace(/(\-[a-z])/g, ($1) => $1.toUpperCase().replace('-', '')); + +// The property name used to store the component config on a component reference +const CONFIG_PROPERTY = '__domFactoryConfig'; + +/** + * Component handler + * @type {Object} + */ +const handler = { + + autoInit () { + ['DOMContentLoaded', 'load'].forEach(function (e) { + window.addEventListener(e, () => handler.upgradeAll()); + }); + }, + + // Registered components + _registered: [], + + // Created component references + _created: [], + + /** + * Register a component. + * @param {String} id A unique component ID. + * @param {Object} factory The component definition object. + */ + register (id, factory) { + const callbacks = []; + const cssClass = `js-${ id }`; + + if (!this.findRegistered(id)) { + this._registered.push({ + id, + cssClass, + callbacks, + factory + }); + } + }, + + /** + * Register a callback to be called on component upgrade. + * @param {String} id The component ID. + * @param {Function} callback The callback function. + */ + registerUpgradedCallback (id, callback) { + const config = this.findRegistered(id); + if (config) { + config.callbacks.push(callback); + } + }, + + /** + * Get a registered component. + * @param {String} id The component ID. + * @return {Object} A configuration object. + */ + findRegistered (id) { + return this._registered.find(config => config.id === id) + }, + + /** + * Get a created component reference for an element. + * @param {HTMLElement} element + * @return {Object} + */ + findCreated (element) { + return this._created.filter(ref => ref.element === element) + }, + + /** + * Upgrade an element with a single component type or all of the registered components. + * @param {HTMLElement} element The element to upgrade. + * @param {String} id The component ID (optional). + */ + upgradeElement (element, id) { + if (id === undefined) { + this._registered.forEach(config => { + if (element.classList.contains(config.cssClass)) { + this.upgradeElement(element, config.id); + } + }); + return + } + + let upgraded = element.getAttribute('data-domfactory-upgraded'); + const config = this.findRegistered(id); + + if (config && (upgraded === null || upgraded.indexOf(id) === -1)) { + upgraded = upgraded === null ? [] : upgraded.split(','); + upgraded.push(id); + + let component; + try { + component = factory(config.factory(element), element); + } + catch (e) { + console.error(id, e.message, e.stack); + } + + if (component) { + element.setAttribute('data-domfactory-upgraded', upgraded.join(',')); + + const instanceConfig = Object.assign({}, config); + delete instanceConfig.factory; + component[CONFIG_PROPERTY] = instanceConfig; + + this._created.push(component); + + Object.defineProperty(element, toCamelCase(id), { + configurable: true, + writable: false, + value: component + }); + + config.callbacks.forEach(cb => cb(element)); + component.fire('domfactory-component-upgraded'); + } + } + else if (config) { + let component = element[toCamelCase(id)]; + if (typeof component._reset === 'function') { + component._reset(); + } + } + }, + + /** + * Upgrade all elements matching a registered component ID. + * @param {String} id The component ID. + */ + upgrade (id) { + if (id === undefined) { + this.upgradeAll(); + } + else { + const config = this.findRegistered(id); + if (config) { + const elements = [...document.querySelectorAll('.' + config.cssClass)]; + elements.forEach(element => this.upgradeElement(element, id)); + } + } + }, + + /** + * Upgrade all elements matching the registered components. + */ + upgradeAll () { + this._registered.forEach(config => this.upgrade(config.id)); + }, + + /** + * Downgrade a component reference. + * @param {Object} component + */ + downgradeComponent (component) { + component.destroy(); + const index = this._created.indexOf(component); + this._created.splice(index, 1); + + const upgrades = component.element.getAttribute('data-domfactory-upgraded').split(','); + const upgradeIndex = upgrades.indexOf(component[CONFIG_PROPERTY].id); + upgrades.splice(upgradeIndex, 1); + component.element.setAttribute('data-domfactory-upgraded', upgrades.join(',')); + component.fire('domfactory-component-downgraded'); + }, + + /** + * Downgrade an element. + * @param {HTMLElement} element + */ + downgradeElement (element) { + this.findCreated(element).forEach(this.downgradeComponent, this); + }, + + /** + * Downgrade all the created components. + */ + downgradeAll () { + this._created.forEach(this.downgradeComponent, this); + }, + + /** + * Downgrade a single element, a NodeList or an array of elements + * @param {Node|Array|NodeList} node + */ + downgrade (node) { + if (node instanceof Array || node instanceof NodeList) { + const nodes = node instanceof NodeList ? [...node] : node; + nodes.forEach(element => this.downgradeElement(element)); + } + else if (node instanceof Node) { + this.downgradeElement(node); + } + } +}; + +/** + * Transform style + * @param {String} value The transform value + * @param {HTMLElement} element The element to apply transforms to + */ +const transform = (value, element) => { + const properties = [ + 'transform', + 'WebkitTransform', + 'msTransform', + 'MozTransform', + 'OTransform' + ]; + properties.map(p => element.style[p] = value); +}; + +const util = { + assign, + isArray, + isElement, + isFunction, + toKebabCase, + transform +}; + +exports.factory = factory; +exports.handler = handler; +exports.util = util; diff --git a/dist/dom-factory.esm.js b/dist/dom-factory.esm.js new file mode 100644 index 0000000..71bf39c --- /dev/null +++ b/dist/dom-factory.esm.js @@ -0,0 +1,657 @@ +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function createCommonjsModule(fn, basedir, module) { + return module = { + path: basedir, + exports: {}, + require: function (path, base) { + return commonjsRequire(path, (base === undefined || base === null) ? module.path : base); + } + }, fn(module, module.exports), module.exports; +} + +function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); +} + +var watchObject = createCommonjsModule(function (module, exports) { +!function(t,e){module.exports=e();}(commonjsGlobal,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0}),e.unwatch=e.watch=void 0;var o=n(4),i=r(o),c=n(3),a=r(c),f=(e.watch=function(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];var r=e[1];_(r)?g.apply(void 0,e):f(r)?b.apply(void 0,e):w.apply(void 0,e);},e.unwatch=function(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];var r=e[1];_(r)||void 0===r?m.apply(void 0,e):f(r)?O.apply(void 0,e):x.apply(void 0,e);},function(t){return "[object Array]"==={}.toString.call(t)}),u=function(t){return "[object Object]"==={}.toString.call(t)},_=function(t){return "[object Function]"==={}.toString.call(t)},s=function(t,e,n){(0, a["default"])(t,e,{enumerable:!1,configurable:!0,writable:!1,value:n});},l=function(t,e,n,r){(0, a["default"])(t,e,{get:n,set:function(t){r.call(this,t);},enumerable:!0,configurable:!0});},p=function(t,e,n,r,o){var i=void 0,c=t.__watchers__[e];(i=t.__watchers__.__watchall__)&&(c=c?c.concat(i):i);for(var a=c?c.length:0,f=0;a>f;f++)c[f].call(t,n,r,e,o);},v=["pop","push","reverse","shift","sort","unshift","splice"],h=function(t,e,n,r){s(t,n,function(){for(var o=0,i=void 0,c=void 0,a=arguments.length,f=Array(a),u=0;a>u;u++)f[u]=arguments[u];if("splice"===n){var _=f[0],s=_+f[1];i=t.slice(_,s),c=[];for(var l=2;l0?f:void 0:f.length>0?f[0]:void 0;var p=e.apply(t,f);return "pop"===n?(i=p,o=t.length):"push"===n?o=t.length-1:"shift"===n?i=p:"unshift"!==n&&void 0===c&&(c=p),r.call(t,o,n,c,i),p});},d=function(t,e){if(_(e)&&t&&!(t instanceof String)&&f(t))for(var n=v.length;n>0;n--){var r=v[n-1];h(t,t[r],r,e);}},y=function(t,e,n,r){var o=!1,c=f(t);void 0===t.__watchers__&&(s(t,"__watchers__",{}),c&&d(t,function(n,o,i,c){if(p(t,n,i,c,o),0!==r&&i&&(u(i)||f(i))){var a=void 0,_=t.__watchers__[e];(a=t.__watchers__.__watchall__)&&(_=_?_.concat(a):a);for(var s=_?_.length:0,l=0;s>l;l++)if("splice"!==o)g(i,_[l],void 0===r?r:r-1);else for(var v=0;vi;i++)o[i]=arguments[i];return n[e].apply(t,o)});});var i=["writable","value"];i.forEach(function(t){void 0!==n[t]&&(r[t]=n[t]);}),(0, a["default"])(t.__proxy__,e,r);}():t.__proxy__[e]=t[e];var o=function(){return t.__proxy__[e]},c=function(n){var o=t.__proxy__[e];if(0!==r&&t[e]&&(u(t[e])||f(t[e]))&&!t[e].__watchers__)for(var i=0;i0)for(var r=0;r0)&&g(t[e],n,void 0!==r?r-1:r),y(t,e,n,r)));},b=function(t,e,n,r){if("string"!=typeof t&&(t instanceof Object||f(t)))for(var o=0;o (el instanceof HTMLElement); + +const isArray = (obj) => ({}.toString.call(obj) === '[object Array]'); + +const isFunction = (fn) => typeof fn === 'function'; + +const toKebabCase = (str) => str.replace(/([A-Z])/g, ($1) => `-${ $1 }`.toLowerCase()); + +/** + * Assign descriptors + * @param {Object} target + * @param {...Object} sources + * @return {Object} + */ +const assign = (target, ...sources) => { + sources.forEach(source => { + if (!source) { + return + } + let descriptors = Object.keys(source).reduce((descriptors, key) => { + descriptors[key] = Object.getOwnPropertyDescriptor(source, key); + return descriptors + }, {}); + Object.getOwnPropertySymbols(source).forEach(sym => { + let descriptor = Object.getOwnPropertyDescriptor(source, sym); + if (descriptor.enumerable) { + descriptors[sym] = descriptor; + } + }); + Object.defineProperties(target, descriptors); + }); + return target +}; + +/** + * Set the default property options + * @param {Object} opts + * @return {Object} + */ +const propOptions = (opts = {}) => { + opts = assign({}, opts); + opts.readOnly = opts.readOnly || false; + opts.reflectToAttribute = opts.reflectToAttribute || false; + opts.value = opts.value; + opts.type = opts.type; + return opts +}; + +/** + * Create property + * @param {String} prop The property name + * @param {Object} opts The property options + * @param {Object} src The source object + */ +const createProp = (prop, opts = {}, src) => { + opts = propOptions(opts); + const property = { + enumerable: true, + configurable: true, + writable: !opts.readOnly, + value: isFunction(opts.value) ? opts.value.call(src) : opts.value + }; + Object.defineProperty(src, prop, property); +}; + +/** + * Set the initial value for a property + * @param {String} prop The property name + * @param {Object} opts The property options + * @param {Object} src The source object + */ +const propValue = (prop, opts = {}, src, element) => { + opts = propOptions(opts); + if ((!opts.value && opts.value !== 0) || !!src[prop]) { + return + } + + if (opts.type === Boolean) { + src[prop] = opts.reflectToAttribute && element.dataset[prop] === 'false' + ? false + : opts.value; + } + else if (isFunction(opts.value)) { + src[prop] = opts.value.call(src); + } + else { + src[prop] = opts.value; + } +}; + +/** + * Keep a property value in sync with a HTMLElement attribute + * @param {String} prop The property name + * @param {Object} opts The property options + * @param {Object} src The source object + */ +const reflectToAttribute = (prop, opts = {}, src) => { + opts = propOptions(opts); + if (!opts.reflectToAttribute) { + return + } + const propKebab = toKebabCase(`data-${prop}`); + const descriptor = Object.getOwnPropertyDescriptor(src, prop); + const property = { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + get: function () { + if (opts.type === Boolean) { + return this.element.dataset[prop] === '' + } + if (opts.type === Number) { + return Number(this.element.dataset[prop]) + } + return this.element.dataset[prop] + }, + set: function (value) { + const removable = !value && value !== 0; + if (opts.type === Boolean || removable) { + return this.element[!removable ? 'setAttribute' : 'removeAttribute'](propKebab, opts.type === Boolean ? '' : value) + } + this.element.dataset[prop] = value; + } + }; + Object.defineProperty(src, prop, property); +}; + +/** + * Create properties + * @param {Object} src The source object + */ +const makeProperties = (src, element) => { + if (typeof src.properties !== 'object') { + return + } + for (let prop in src.properties) { + if (src.properties.hasOwnProperty(prop)) { + let opts = src.properties[prop]; + + createProp(prop, opts, src); + reflectToAttribute(prop, opts, src); + propValue(prop, opts, src, element); + } + } +}; + +const dotObject = (str, obj) => { + return str.split('.').reduce((o, i) => o[i], obj) +}; + +const dotObjectPropParent = (str, obj) => { + let dots = str.split('.'); + let prop = dots.pop(); + let parent = dotObject(dots.join('.'), obj); + return { + parent, + prop + } +}; + +/** + * Get the configuration for observers + * @param {Object} src The source object + * @return {Array} + */ +const observers = (src) => { + if (!isArray(src.observers)) { + return [] + } + return src.observers.map(sig => { + let [, fn, args] = sig.match(/([a-zA-Z-_]+)\(([^)]*)\)/); + args = args.split(',').map(a => a.trim()).filter(a => a.length); + return { + fn, + args + } + }) + .filter(({ fn }) => isFunction(src[fn])) +}; + +/** + * Create observers + * @param {Object} src The source object + */ +const makeObservers = (src) => { + observers(src).forEach(({ fn, args }) => { + src[fn] = src[fn].bind(src); + args.forEach(arg => { + if (arg.indexOf('.') !== -1) { + const { prop, parent } = dotObjectPropParent(arg, src); + watchObject.watch(parent, prop, src[fn]); + } + else { + watchObject.watch(src, arg, src[fn]); + } + }); + }); +}; + +/** + * Get the configuration for DOM event listeners + * @param {Object} src The source object + * @return {Array} + */ +const listeners = (src) => { + if (!isArray(src.listeners)) { + return [] + } + return src.listeners.map(sig => { + let match = sig.match(/(.*\.)?([a-zA-Z-_]+)\(([^)]*)\)/); + let [, element, fn, events] = match; + events = events.split(',').map(a => a.trim()).filter(a => a.length); + element = element ? element.substr(0, element.length - 1) : 'element'; + return { + element, + fn, + events + } + }) + .filter(({ element, fn }) => { + return isFunction(src[fn]) && ( + element === 'document' || + element === 'window' || + isElement(src[element]) || + (src[element] && isElement(src[element]['element']) )) + }) +}; + +/** + * Create DOM event listeners + * @param {Object} src The source object + */ +const makeListeners = (src) => { + listeners(src).forEach(({ element, fn, events }) => { + src[fn] = src[fn].bind(src); + if (element === 'document') { + element = src.element.ownerDocument; + } + else if (element === 'window') { + element = window; + } + else if (isElement(src[element])) { + element = src[element]; + } + else if (isElement(src[element]['element'])) { + element = src[element]['element']; + } + if (element) { + events.forEach(e => element.addEventListener(e, src[fn])); + } + }); +}; + +/** + * Get mixins + * @param {Object} src The source object + * @return {Array} + */ +const mixins = (src) => { + if (!isArray(src.mixins)) { + return [] + } + return src.mixins.filter(mixin => typeof mixin === 'object') +}; + +/** + * Merge mixins + * @param {Object} src The source object + */ +const makeMixins = (src) => { + const args = mixins(src); + args.unshift({}); + return assign.apply(null, args) +}; + +const factory = (factory, element) => { + if (!factory || + typeof factory !== 'object' || + !isElement(element)) { + console.error('[dom-factory] Invalid factory.', factory, element); + return + } + + factory.element = element; + + let component = { + + /** + * Set a property on the component + * @param {String} prop The property name + * @param {?} value The property value + */ + $set (prop, value) { + if (!prop || value === undefined || this.properties === undefined || !this.properties.hasOwnProperty(prop)) { + return + } + const opts = propOptions(this.properties[prop]); + const descriptor = Object.getOwnPropertyDescriptor(this, prop); + + if (opts.readOnly && descriptor.writable !== undefined) { + let property = { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: false, + value + }; + Object.defineProperty(this, prop, property); + return + } + + this[prop] = value; + }, + + /** + * Initialize component + */ + init () { + makeObservers(this); + makeListeners(this); + if (isFunction(factory.init)) { + factory.init.call(this); + } + }, + + /** + * Destroy component + */ + destroy () { + observers(factory).forEach(({ fn, args }) => { + args.forEach(arg => { + if (arg.indexOf('.') !== -1) { + const { prop, parent } = dotObjectPropParent(arg, this); + watchObject.unwatch(parent, prop, this[fn]); + } + else { + watchObject.unwatch(this, arg, this[fn]); + } + }); + }); + + listeners(factory).forEach(({ element, fn, events }) => { + if (element === 'document') { + element = this.element.ownerDocument; + } + else if (element === 'window') { + element = window; + } + else if (isElement(this[element])) { + element = this[element]; + } + else if (isElement(this[element]['element'])) { + element = this[element]['element']; + } + if (element) { + events.forEach(e => element.removeEventListener(e, this[fn])); + } + }); + + if (isFunction(factory.destroy)) { + factory.destroy.call(this); + } + }, + + /** + * Fire a DOM Event on the HTMLElement + * @param {String} eventName The event name + */ + fire (eventName) { + let event; + let bubbles = false; + if ('CustomEvent' in window && typeof window.CustomEvent === 'object') { + try { + event = new CustomEvent(eventName, { + bubbles, + cancelable: false + }); + } + catch (e) { + event = new this.CustomEvent_(eventName, { + bubbles, + cancelable: false + }); + } + } + else { + event = document.createEvent('Event'); + event.initEvent(eventName, bubbles, true); + } + this.element.dispatchEvent(event); + }, + + CustomEvent_ (event, params) { + params = params || { bubbles: false, cancelable: false, detail: undefined }; + var evt = document.createEvent('CustomEvent'); + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); + return evt + } + }; + + makeProperties(factory, element); + + component = assign( + {}, + makeMixins(factory), + factory, + component + ); + + component.init(); + + return component +}; + +const toCamelCase = (str) => str.replace(/(\-[a-z])/g, ($1) => $1.toUpperCase().replace('-', '')); + +// The property name used to store the component config on a component reference +const CONFIG_PROPERTY = '__domFactoryConfig'; + +/** + * Component handler + * @type {Object} + */ +const handler = { + + autoInit () { + ['DOMContentLoaded', 'load'].forEach(function (e) { + window.addEventListener(e, () => handler.upgradeAll()); + }); + }, + + // Registered components + _registered: [], + + // Created component references + _created: [], + + /** + * Register a component. + * @param {String} id A unique component ID. + * @param {Object} factory The component definition object. + */ + register (id, factory) { + const callbacks = []; + const cssClass = `js-${ id }`; + + if (!this.findRegistered(id)) { + this._registered.push({ + id, + cssClass, + callbacks, + factory + }); + } + }, + + /** + * Register a callback to be called on component upgrade. + * @param {String} id The component ID. + * @param {Function} callback The callback function. + */ + registerUpgradedCallback (id, callback) { + const config = this.findRegistered(id); + if (config) { + config.callbacks.push(callback); + } + }, + + /** + * Get a registered component. + * @param {String} id The component ID. + * @return {Object} A configuration object. + */ + findRegistered (id) { + return this._registered.find(config => config.id === id) + }, + + /** + * Get a created component reference for an element. + * @param {HTMLElement} element + * @return {Object} + */ + findCreated (element) { + return this._created.filter(ref => ref.element === element) + }, + + /** + * Upgrade an element with a single component type or all of the registered components. + * @param {HTMLElement} element The element to upgrade. + * @param {String} id The component ID (optional). + */ + upgradeElement (element, id) { + if (id === undefined) { + this._registered.forEach(config => { + if (element.classList.contains(config.cssClass)) { + this.upgradeElement(element, config.id); + } + }); + return + } + + let upgraded = element.getAttribute('data-domfactory-upgraded'); + const config = this.findRegistered(id); + + if (config && (upgraded === null || upgraded.indexOf(id) === -1)) { + upgraded = upgraded === null ? [] : upgraded.split(','); + upgraded.push(id); + + let component; + try { + component = factory(config.factory(element), element); + } + catch (e) { + console.error(id, e.message, e.stack); + } + + if (component) { + element.setAttribute('data-domfactory-upgraded', upgraded.join(',')); + + const instanceConfig = Object.assign({}, config); + delete instanceConfig.factory; + component[CONFIG_PROPERTY] = instanceConfig; + + this._created.push(component); + + Object.defineProperty(element, toCamelCase(id), { + configurable: true, + writable: false, + value: component + }); + + config.callbacks.forEach(cb => cb(element)); + component.fire('domfactory-component-upgraded'); + } + } + else if (config) { + let component = element[toCamelCase(id)]; + if (typeof component._reset === 'function') { + component._reset(); + } + } + }, + + /** + * Upgrade all elements matching a registered component ID. + * @param {String} id The component ID. + */ + upgrade (id) { + if (id === undefined) { + this.upgradeAll(); + } + else { + const config = this.findRegistered(id); + if (config) { + const elements = [...document.querySelectorAll('.' + config.cssClass)]; + elements.forEach(element => this.upgradeElement(element, id)); + } + } + }, + + /** + * Upgrade all elements matching the registered components. + */ + upgradeAll () { + this._registered.forEach(config => this.upgrade(config.id)); + }, + + /** + * Downgrade a component reference. + * @param {Object} component + */ + downgradeComponent (component) { + component.destroy(); + const index = this._created.indexOf(component); + this._created.splice(index, 1); + + const upgrades = component.element.getAttribute('data-domfactory-upgraded').split(','); + const upgradeIndex = upgrades.indexOf(component[CONFIG_PROPERTY].id); + upgrades.splice(upgradeIndex, 1); + component.element.setAttribute('data-domfactory-upgraded', upgrades.join(',')); + component.fire('domfactory-component-downgraded'); + }, + + /** + * Downgrade an element. + * @param {HTMLElement} element + */ + downgradeElement (element) { + this.findCreated(element).forEach(this.downgradeComponent, this); + }, + + /** + * Downgrade all the created components. + */ + downgradeAll () { + this._created.forEach(this.downgradeComponent, this); + }, + + /** + * Downgrade a single element, a NodeList or an array of elements + * @param {Node|Array|NodeList} node + */ + downgrade (node) { + if (node instanceof Array || node instanceof NodeList) { + const nodes = node instanceof NodeList ? [...node] : node; + nodes.forEach(element => this.downgradeElement(element)); + } + else if (node instanceof Node) { + this.downgradeElement(node); + } + } +}; + +/** + * Transform style + * @param {String} value The transform value + * @param {HTMLElement} element The element to apply transforms to + */ +const transform = (value, element) => { + const properties = [ + 'transform', + 'WebkitTransform', + 'msTransform', + 'MozTransform', + 'OTransform' + ]; + properties.map(p => element.style[p] = value); +}; + +const util = { + assign, + isArray, + isElement, + isFunction, + toKebabCase, + transform +}; + +export { factory, handler, util }; diff --git a/dist/dom-factory.js b/dist/dom-factory.js index 0138b12..4c638b1 100644 --- a/dist/dom-factory.js +++ b/dist/dom-factory.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.domFactory=e():t.domFactory=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.util=e.handler=e.factory=void 0;var r=n(18);Object.defineProperty(e,"factory",{enumerable:!0,get:function(){return r.factory}});var o=n(42);Object.defineProperty(e,"handler",{enumerable:!0,get:function(){return o.handler}});var i=n(21),u=n(20),c=n(22),a=n(23),f=n(19),s=n(43);e.util={assign:f.assign,isArray:u.isArray,isElement:i.isElement,isFunction:c.isFunction,toKebabCase:a.toKebabCase,transform:s.transform}},function(t,e){var n=Object;t.exports={create:n.create,getProto:n.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:n.getOwnPropertyDescriptor,setDesc:n.defineProperty,setDescs:n.defineProperties,getKeys:n.keys,getNames:n.getOwnPropertyNames,getSymbols:n.getOwnPropertySymbols,each:[].forEach}},function(t,e){var n=t.exports={version:"1.2.6"};"number"==typeof __e&&(__e=n)},function(t,e,n){var r=n(34)("wks"),o=n(36),i=n(8).Symbol;t.exports=function(t){return r[t]||(r[t]=i&&i[t]||(i||o)("Symbol."+t))}},function(t,e){t.exports={}},function(t,e,n){var r=n(8),o=n(2),i=n(27),u="prototype",c=function(t,e,n){var a,f,s,l=t&c.F,d=t&c.G,p=t&c.S,v=t&c.P,h=t&c.B,_=t&c.W,y=d?o:o[e]||(o[e]={}),g=d?r:p?r[e]:(r[e]||{})[u];d&&(n=e);for(a in n)f=!l&&g&&a in g,f&&a in y||(s=f?g[a]:n[a],y[a]=d&&"function"!=typeof g[a]?n[a]:h&&f?i(s,r):_&&g[a]==s?function(t){var e=function(e){return this instanceof t?new t(e):t(e)};return e[u]=t[u],e}(s):v&&"function"==typeof s?i(Function.call,s):s,v&&((y[u]||(y[u]={}))[a]=s))};c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,t.exports=c},function(t,e,n){var r=n(29),o=n(11);t.exports=function(t){return r(o(t))}},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(t,e,n){var r=n(71);t.exports=function(t){if(!r(t))throw TypeError(t+" is not an object!");return t}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e,n){var r=n(1),o=n(14);t.exports=n(28)?function(t,e,n){return r.setDesc(t,e,o(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var r=n(1).setDesc,o=n(12),i=n(3)("toStringTag");t.exports=function(t,e,n){t&&!o(t=n?t:t.prototype,i)&&r(t,i,{configurable:!0,value:e})}},function(t,e,n){var r=n(11);t.exports=function(t){return Object(r(t))}},function(t,e,n){"use strict";var r=n(78)(!0);n(30)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,e=this._t,n=this._i;return n>=e.length?{value:void 0,done:!0}:(t=r(e,n),this._i+=t.length,{value:t,done:!1})})},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(40);Object.defineProperty(e,"factory",{enumerable:!0,get:function(){return r.factory}})},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0}),e.assign=void 0;var o=n(48),i=r(o),u=n(49),c=r(u),a=n(25),f=r(a),s=n(50),l=r(s);e.assign=function(t){for(var e=arguments.length,n=Array(e>1?e-1:0),r=1;r0?r:n)(t)}},function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+r).toString(36))}},function(t,e,n){var r=n(26),o=n(3)("iterator"),i=n(4);t.exports=n(2).getIteratorMethod=function(t){if(void 0!=t)return t[o]||t["@@iterator"]||i[r(t)]}},function(t,e,n){"use strict";var r=n(1),o=n(8),i=n(12),u=n(28),c=n(5),a=n(33),f=n(7),s=n(34),l=n(15),d=n(36),p=n(3),v=n(76),h=n(68),_=n(67),y=n(70),g=n(9),b=n(6),m=n(14),w=r.getDesc,x=r.setDesc,O=r.create,j=h.get,E=o.Symbol,A=o.JSON,S=A&&A.stringify,P=!1,M=p("_hidden"),F=r.isEnum,C=s("symbol-registry"),D=s("symbols"),k="function"==typeof E,N=Object.prototype,T=u&&f(function(){return 7!=O(x({},"a",{get:function(){return x(this,"a",{value:7}).a}})).a})?function(t,e,n){var r=w(N,e);r&&delete N[e],x(t,e,n),r&&t!==N&&x(N,e,r)}:x,I=function(t){var e=D[t]=O(E.prototype);return e._k=t,u&&P&&T(N,t,{configurable:!0,set:function(e){i(this,M)&&i(this[M],t)&&(this[M][t]=!1),T(this,t,m(1,e))}}),e},L=function(t){return"symbol"==typeof t},K=function(t,e,n){return n&&i(D,e)?(n.enumerable?(i(t,M)&&t[M][e]&&(t[M][e]=!1),n=O(n,{enumerable:m(0,!1)})):(i(t,M)||x(t,M,m(1,{})),t[M][e]=!0),T(t,e,n)):x(t,e,n)},W=function(t,e){g(t);for(var n,r=_(e=b(e)),o=0,i=r.length;i>o;)K(t,n=r[o++],e[n]);return t},z=function(t,e){return void 0===e?O(t):W(O(t),e)},B=function(t){var e=F.call(this,t);return!(e||!i(this,t)||!i(D,t)||i(this,M)&&this[M][t])||e},G=function(t,e){var n=w(t=b(t),e);return!n||!i(D,e)||i(t,M)&&t[M][e]||(n.enumerable=!0),n},R=function(t){for(var e,n=j(b(t)),r=[],o=0;n.length>o;)i(D,e=n[o++])||e==M||r.push(e);return r},J=function(t){for(var e,n=j(b(t)),r=[],o=0;n.length>o;)i(D,e=n[o++])&&r.push(D[e]);return r},U=function(t){if(void 0!==t&&!L(t)){for(var e,n,r=[t],o=1,i=arguments;i.length>o;)r.push(i[o++]);return e=r[1],"function"==typeof e&&(n=e),!n&&y(e)||(e=function(t,e){if(n&&(e=n.call(this,t,e)),!L(e))return e}),r[1]=e,S.apply(A,r)}},Z=f(function(){var t=E();return"[null]"!=S([t])||"{}"!=S({a:t})||"{}"!=S(Object(t))});k||(E=function(){if(L(this))throw TypeError("Symbol is not a constructor");return I(d(arguments.length>0?arguments[0]:void 0))},a(E.prototype,"toString",function(){return this._k}),L=function(t){return t instanceof E},r.create=z,r.isEnum=B,r.getDesc=G,r.setDesc=K,r.setDescs=W,r.getNames=h.get=R,r.getSymbols=J,u&&!n(31)&&a(N,"propertyIsEnumerable",B,!0));var q={for:function(t){return i(C,t+="")?C[t]:C[t]=E(t)},keyFor:function(t){return v(C,t)},useSetter:function(){P=!0},useSimple:function(){P=!1}};r.each.call("hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),function(t){var e=p(t);q[t]=k?e:I(e)}),P=!0,c(c.G+c.W,{Symbol:E}),c(c.S,"Symbol",q),c(c.S+c.F*!k,"Object",{create:z,defineProperty:K,defineProperties:W,getOwnPropertyDescriptor:G,getOwnPropertyNames:R,getOwnPropertySymbols:J}),A&&c(c.S+c.F*(!k||Z),"JSON",{stringify:U}),l(E,"Symbol"),l(Math,"Math",!0),l(o.JSON,"JSON",!0)},function(t,e,n){n(83);var r=n(4);r.NodeList=r.HTMLCollection=r.Array},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0}),e.factory=void 0;var o=n(52),i=r(o),u=n(54),c=r(u),a=n(25),f=r(a),s=n(24),l=r(s),d=n(88),p=n(21),v=n(20),h=n(22),_=n(23),y=n(19),g=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return t=(0,y.assign)({},t),t.readOnly=t.readOnly||!1,t.reflectToAttribute=t.reflectToAttribute||!1,t.value=t.value,t.type=t.type,t},b=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2];e=g(e);var r={enumerable:!0,configurable:!0,writable:!e.readOnly,value:(0,h.isFunction)(e.value)?e.value.call(n):e.value};(0,l.default)(n,t,r)},m=function(t,e,n){e&&!n[t]&&((0,h.isFunction)(e)?n[t]=e.call(n):n[t]=e)},w=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2];if(e=g(e),e.reflectToAttribute){var r=(0,_.toKebabCase)(t),o=(0,f.default)(n,t),i={enumerable:o.enumerable,configurable:o.configurable,get:function(){return e.type===Boolean?this.element.hasAttribute(r):this.element.getAttribute(r)},set:function(n){this.element[n?"setAttribute":"removeAttribute"](r,e.type===Boolean?t:n)}};(0,l.default)(n,t,i)}},x=function(t){if("object"===(0,c.default)(t.properties))for(var e in t.properties)if(t.properties.hasOwnProperty(e)){var n=t.properties[e];b(e,n,t),w(e,n,t),m(e,n.value,t)}},O=function(t,e){return t.split(".").reduce(function(t,e){return t[e]},e)},j=function(t,e){var n=t.split("."),r=n.pop(),o=O(n.join("."),e);return{parent:o,prop:r}},E=function(t){return(0,v.isArray)(t.observers)?t.observers.map(function(t){var e=t.match(/([a-zA-Z-_]+)\(([^)]*)\)/),n=(0,i.default)(e,3),r=n[1],o=n[2];return o=o.split(",").map(function(t){return t.trim()}).filter(function(t){return t.length}),{fn:r,args:o}}).filter(function(e){var n=e.fn;return(0,h.isFunction)(t[n])}):[]},A=function(t){E(t).forEach(function(e){var n=e.fn,r=e.args;t[n]=t[n].bind(t),r.forEach(function(e){if(e.indexOf(".")!==-1){var r=j(e,t),o=r.prop,i=r.parent;(0,d.watch)(i,o,t[n])}else(0,d.watch)(t,e,t[n])})})},S=function(t){return(0,v.isArray)(t.listeners)?t.listeners.map(function(t){var e=t.match(/(.*\.)?([a-zA-Z-_]+)\(([^)]*)\)/),n=(0,i.default)(e,4),r=n[1],o=n[2],u=n[3];return u=u.split(",").map(function(t){return t.trim()}).filter(function(t){return t.length}),r=r?r.substr(0,r.length-1):"element",{element:r,fn:o,events:u}}).filter(function(e){var n=e.element,r=e.fn;return(0,h.isFunction)(t[r])&&("document"===n||"window"===n||(0,p.isElement)(t[n])||(0,p.isElement)(t[n].element))}):[]},P=function(t){S(t).forEach(function(e){var n=e.element,r=e.fn,o=e.events;t[r]=t[r].bind(t),"document"===n?n=t.element.ownerDocument:"window"===n?n=window:(0,p.isElement)(t[n])?n=t[n]:(0,p.isElement)(t[n].element)&&(n=t[n].element),n&&o.forEach(function(e){return n.addEventListener(e,t[r])})})},M=function(t){return(0,v.isArray)(t.mixins)?t.mixins.filter(function(t){return"object"===("undefined"==typeof t?"undefined":(0,c.default)(t))}):[]},F=function(t){var e=M(t);return e.unshift({}),y.assign.apply(null,e)};e.factory=function(t,e){if(!t||"object"!==("undefined"==typeof t?"undefined":(0,c.default)(t))||!(0,p.isElement)(e))return void console.error("[dom-factory] Invalid factory.",t,e);t.element=e;var n={$set:function(t,e){if(t&&void 0!==e&&void 0!==this.properties&&this.properties.hasOwnProperty(t)){var n=g(this.properties[t]),r=(0,f.default)(this,t);if(n.readOnly&&void 0!==r.writable){var o={enumerable:r.enumerable,configurable:r.configurable,writable:!1,value:e};return void(0,l.default)(this,t,o)}this[t]=e}},init:function(){A(this),P(this),(0,h.isFunction)(t.init)&&t.init.call(this)},destroy:function(){var e=this;E(t).forEach(function(t){var n=t.fn,r=t.args;r.forEach(function(t){if(t.indexOf(".")!==-1){var r=j(t,e),o=r.prop,i=r.parent;(0,d.unwatch)(i,o,e[n])}else(0,d.unwatch)(e,t,e[n])})}),S(t).forEach(function(t){var n=t.element,r=t.fn,o=t.events;"document"===n?n=e.element.ownerDocument:"window"===n?n=window:(0,p.isElement)(e[n])?n=e[n]:(0,p.isElement)(e[n].element)&&(n=e[n].element),n&&o.forEach(function(t){return n.removeEventListener(t,e[r])})}),(0,h.isFunction)(t.destroy)&&t.destroy.call(this)},fire:function(t){var e=void 0;"CustomEvent"in window&&"object"===(0,c.default)(window.CustomEvent)?e=new CustomEvent(t,{bubbles:!0,cancelable:!1}):(e=document.createEvent("Event"),e.initEvent(t,!0,!0)),this.element.dispatchEvent(e)}};return x(t),n=(0,y.assign)({},F(t),t,n),n.init(),n}},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0}),e.handler=void 0;var o=n(53),i=r(o),u=n(24),c=r(u),a=n(47),f=r(a),s=n(18),l=function(t){return t.replace(/(\-[a-z])/g,function(t){return t.toUpperCase().replace("-","")})},d="__domFactoryConfig",p=e.handler={_registered:[],_created:[],register:function(t,e){var n=[],r=t.split("-");r.splice(1,0,"js");var o=r.join("-");this.findRegistered(t)||this._registered.push({id:t,cssClass:o,callbacks:n,factory:e}),this.upgrade(t)},registerUpgradedCallback:function(t,e){var n=this.findRegistered(t);n&&n.callbacks.push(e)},findRegistered:function(t){return this._registered.find(function(e){return e.id===t})},findCreated:function(t){return this._created.filter(function(e){return e.element===t})},upgradeElement:function(t,e){var n=this;if(void 0===e)return void this._registered.forEach(function(e){t.classList.contains(e.cssClass)&&n.upgradeElement(t,e.id)});var r=t.getAttribute("data-domfactory-upgraded"),o=this.findRegistered(e);if(!o||null!==r&&r.indexOf(e)!==-1){if(o){var i=t[l(e)];"function"==typeof i._reset&&i._reset()}}else{r=null===r?[]:r.split(","),r.push(e);var u=void 0;try{u=(0,s.factory)(o.factory(t),t)}catch(t){console.error(e,t.message,t.stack)}if(u){t.setAttribute("data-domfactory-upgraded",r.join(","));var a=(0,f.default)({},o);delete a.factory,u[d]=a,this._created.push(u),(0,c.default)(t,l(e),{configurable:!0,writable:!1,value:u}),o.callbacks.forEach(function(e){return e(t)}),u.fire("domfactory-component-upgraded")}}},upgrade:function(t){var e=this;if(void 0===t)this.upgradeAll();else{var n=this.findRegistered(t);if(n){var r=[].concat((0,i.default)(document.querySelectorAll("."+n.cssClass)));r.forEach(function(n){return e.upgradeElement(n,t)})}}},upgradeAll:function(){var t=this;this._registered.forEach(function(e){return t.upgrade(e.id)})},downgradeComponent:function(t){var e=this._created.indexOf(t);this._created.splice(e,1);var n=t.element.getAttribute("data-domfactory-upgraded").split(","),r=n.indexOf(t[d].id);n.splice(r,1),t.element.setAttribute("data-domfactory-upgraded",n.join(",")),t.fire("domfactory-component-downgraded")},downgradeElement:function(t){this.findCreated(t).forEach(this.downgradeComponent)},downgradeAll:function(){this._created.forEach(this.downgradeComponent)},downgrade:function(t){var e=this;if(t instanceof Array||t instanceof NodeList){var n=t instanceof NodeList?[].concat((0,i.default)(t)):t;n.forEach(function(t){return e.downgradeElement(t)})}else t instanceof Node&&this.downgradeElement(t)}};window.addEventListener("load",function(){return p.upgradeAll()})},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(41);Object.defineProperty(e,"handler",{enumerable:!0,get:function(){return r.handler}})},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.transform=function(t,e){var n=["transform","WebkitTransform","msTransform","MozTransform","OTransform"];n.map(function(n){return e.style[n]=t})}},function(t,e,n){t.exports={default:n(55),__esModule:!0}},function(t,e,n){t.exports={default:n(56),__esModule:!0}},function(t,e,n){t.exports={default:n(57),__esModule:!0}},function(t,e,n){t.exports={default:n(58),__esModule:!0}},function(t,e,n){t.exports={default:n(59),__esModule:!0}},function(t,e,n){t.exports={default:n(62),__esModule:!0}},function(t,e,n){t.exports={default:n(63),__esModule:!0}},function(t,e,n){t.exports={default:n(64),__esModule:!0}},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}e.__esModule=!0;var o=n(46),i=r(o),u=n(45),c=r(u);e.default=function(){function t(t,e){var n=[],r=!0,o=!1,i=void 0;try{for(var u,a=(0,c.default)(t);!(r=(u=a.next()).done)&&(n.push(u.value),!e||n.length!==e);r=!0);}catch(t){o=!0,i=t}finally{try{!r&&a.return&&a.return()}finally{if(o)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if((0,i.default)(Object(e)))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}()},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}e.__esModule=!0;var o=n(44),i=r(o);e.default=function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);ec;)u.call(t,o=i[c++])&&e.push(o);return e}},function(t,e,n){var r=n(6),o=n(1).getNames,i={}.toString,u="object"==typeof window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],c=function(t){try{return o(t)}catch(t){return u.slice()}};t.exports.get=function(t){return u&&"[object Window]"==i.call(t)?c(t):o(r(t))}},function(t,e,n){var r=n(4),o=n(3)("iterator"),i=Array.prototype;t.exports=function(t){return void 0!==t&&(r.Array===t||i[o]===t)}},function(t,e,n){var r=n(10);t.exports=Array.isArray||function(t){return"Array"==r(t)}},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e,n){var r=n(9);t.exports=function(t,e,n,o){try{return o?e(r(n)[0],n[1]):e(n)}catch(e){var i=t.return;throw void 0!==i&&r(i.call(t)),e}}},function(t,e,n){"use strict";var r=n(1),o=n(14),i=n(15),u={};n(13)(u,n(3)("iterator"),function(){return this}),t.exports=function(t,e,n){t.prototype=r.create(u,{next:o(1,n)}),i(t,e+" Iterator")}},function(t,e,n){var r=n(3)("iterator"),o=!1;try{var i=[7][r]();i.return=function(){o=!0},Array.from(i,function(){throw 2})}catch(t){}t.exports=function(t,e){if(!e&&!o)return!1;var n=!1;try{var i=[7],u=i[r]();u.next=function(){return{done:n=!0}},i[r]=function(){return u},t(i)}catch(t){}return n}},function(t,e){t.exports=function(t,e){return{value:e,done:!!t}}},function(t,e,n){var r=n(1),o=n(6);t.exports=function(t,e){for(var n,i=o(t),u=r.getKeys(i),c=u.length,a=0;c>a;)if(i[n=u[a++]]===e)return n}},function(t,e,n){var r=n(1),o=n(16),i=n(29);t.exports=n(7)(function(){var t=Object.assign,e={},n={},r=Symbol(),o="abcdefghijklmnopqrst";return e[r]=7,o.split("").forEach(function(t){n[t]=t}),7!=t({},e)[r]||Object.keys(t({},n)).join("")!=o})?function(t,e){for(var n=o(t),u=arguments,c=u.length,a=1,f=r.getKeys,s=r.getSymbols,l=r.isEnum;c>a;)for(var d,p=i(u[a++]),v=s?f(p).concat(s(p)):f(p),h=v.length,_=0;h>_;)l.call(p,d=v[_++])&&(n[d]=p[d]);return n}:Object.assign},function(t,e,n){var r=n(35),o=n(11);t.exports=function(t){return function(e,n){var i,u,c=String(o(e)),a=r(n),f=c.length;return a<0||a>=f?t?"":void 0:(i=c.charCodeAt(a),i<55296||i>56319||a+1===f||(u=c.charCodeAt(a+1))<56320||u>57343?t?c.charAt(a):i:t?c.slice(a,a+2):(i-55296<<10)+(u-56320)+65536)}}},function(t,e,n){var r=n(35),o=Math.min;t.exports=function(t){return t>0?o(r(t),9007199254740991):0}},function(t,e,n){var r=n(9),o=n(37);t.exports=n(2).getIterator=function(t){var e=o(t);if("function"!=typeof e)throw TypeError(t+" is not iterable!");return r(e.call(t))}},function(t,e,n){var r=n(26),o=n(3)("iterator"),i=n(4);t.exports=n(2).isIterable=function(t){var e=Object(t);return void 0!==e[o]||"@@iterator"in e||i.hasOwnProperty(r(e))}},function(t,e,n){"use strict";var r=n(27),o=n(5),i=n(16),u=n(72),c=n(69),a=n(79),f=n(37);o(o.S+o.F*!n(74)(function(t){Array.from(t)}),"Array",{from:function(t){var e,n,o,s,l=i(t),d="function"==typeof this?this:Array,p=arguments,v=p.length,h=v>1?p[1]:void 0,_=void 0!==h,y=0,g=f(l);if(_&&(h=r(h,v>2?p[2]:void 0,2)),void 0==g||d==Array&&c(g))for(e=a(l.length),n=new d(e);e>y;y++)n[y]=_?h(l[y],y):l[y];else for(s=g.call(l),n=new d;!(o=s.next()).done;y++)n[y]=_?u(s,h,[o.value,y],!0):o.value;return n.length=y,n}})},function(t,e,n){"use strict";var r=n(66),o=n(75),i=n(4),u=n(6);t.exports=n(30)(Array,"Array",function(t,e){this._t=u(t),this._i=0,this._k=e},function(){var t=this._t,e=this._k,n=this._i++;return!t||n>=t.length?(this._t=void 0,o(1)):"keys"==e?o(0,n):"values"==e?o(0,t[n]):o(0,[n,t[n]])},"values"),i.Arguments=i.Array,r("keys"),r("values"),r("entries")},function(t,e,n){var r=n(5);r(r.S+r.F,"Object",{assign:n(77)})},function(t,e,n){var r=n(6);n(32)("getOwnPropertyDescriptor",function(t){return function(e,n){return t(r(e),n)}})},function(t,e,n){var r=n(16);n(32)("keys",function(t){return function(e){return t(r(e))}})},function(t,e){},function(t,e,n){!function(e,n){t.exports=n()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0}),e.unwatch=e.watch=void 0;var o=n(4),i=r(o),u=n(3),c=r(u),a=(e.watch=function(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];var r=e[1];s(r)?g.apply(void 0,e):a(r)?m.apply(void 0,e):b.apply(void 0,e)},e.unwatch=function(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];var r=e[1];s(r)||void 0===r?j.apply(void 0,e):a(r)?x.apply(void 0,e):w.apply(void 0,e)},function(t){return"[object Array]"==={}.toString.call(t)}),f=function(t){return"[object Object]"==={}.toString.call(t)},s=function(t){return"[object Function]"==={}.toString.call(t)},l=function(t,e,n){(0,c.default)(t,e,{enumerable:!1,configurable:!0,writable:!1,value:n})},d=function(t,e,n,r){(0,c.default)(t,e,{get:n,set:function(t){r.call(this,t)},enumerable:!0,configurable:!0})},p=function(t,e,n,r,o){var i=void 0,u=t.__watchers__[e];(i=t.__watchers__.__watchall__)&&(u=u?u.concat(i):i);for(var c=u?u.length:0,a=0;c>a;a++)u[a].call(t,n,r,e,o)},v=["pop","push","reverse","shift","sort","unshift","splice"],h=function(t,e,n,r){l(t,n,function(){for(var o=0,i=void 0,u=void 0,c=arguments.length,a=Array(c),f=0;c>f;f++)a[f]=arguments[f];if("splice"===n){var s=a[0],l=s+a[1];i=t.slice(s,l),u=[];for(var d=2;d0?a:void 0:a.length>0?a[0]:void 0;var p=e.apply(t,a);return"pop"===n?(i=p,o=t.length):"push"===n?o=t.length-1:"shift"===n?i=p:"unshift"!==n&&void 0===u&&(u=p),r.call(t,o,n,u,i),p})},_=function(t,e){if(s(e)&&t&&!(t instanceof String)&&a(t))for(var n=v.length;n>0;n--){var r=v[n-1];h(t,t[r],r,e)}},y=function(t,e,n,r){var o=!1,u=a(t);void 0===t.__watchers__&&(l(t,"__watchers__",{}),u&&_(t,function(n,o,i,u){if(p(t,n,i,u,o),0!==r&&i&&(f(i)||a(i))){var c=void 0,s=t.__watchers__[e];(c=t.__watchers__.__watchall__)&&(s=s?s.concat(c):c);for(var l=s?s.length:0,d=0;l>d;d++)if("splice"!==o)g(i,s[d],void 0===r?r:r-1);else for(var v=0;vi;i++)o[i]=arguments[i];return n[e].apply(t,o)})});var i=["writable","value"];i.forEach(function(t){void 0!==n[t]&&(r[t]=n[t])}),(0,c.default)(t.__proxy__,e,r)}():t.__proxy__[e]=t[e];var o=function(){return t.__proxy__[e]},u=function(n){var o=t.__proxy__[e];if(0!==r&&t[e]&&(f(t[e])||a(t[e]))&&!t[e].__watchers__)for(var i=0;i0)for(var o=0;o0)&&g(t[e],n,void 0!==r?r-1:r),y(t,e,n,r)))},m=function(t,e,n,r){if("string"!=typeof t&&(t instanceof Object||a(t)))for(var o=0;o<2?it(ot[t])||it(o[t]):ot[t]&&ot[t][e]||o[t]&&o[t][e]},ct=Math.ceil,ut=Math.floor,ft=function(t){return isNaN(t=+t)?0:(t>0?ut:ct)(t)},lt=Math.min,st=function(t){return t>0?lt(ft(t),9007199254740991):0},pt=Math.max,dt=Math.min,ht=function(t,e){var n=ft(t);return n<0?pt(n+e,0):dt(n,e)},vt=function(t){return function(e,n,r){var o,i=g(e),a=st(i.length),c=ht(r,a);if(t&&n!=n){for(;a>c;)if((o=i[c++])!=o)return!0}else for(;a>c;c++)if((t||c in i)&&i[c]===n)return t||c||0;return!t&&-1}},gt={includes:vt(!0),indexOf:vt(!1)},yt=gt.indexOf,bt=function(t,e){var n,r=g(t),o=0,i=[];for(n in r)!_(q,n)&&_(r,n)&&i.push(n);for(;e.length>o;)_(r,n=e[o++])&&(~yt(i,n)||i.push(n));return i},mt=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],_t=mt.concat("length","prototype"),wt={f:Object.getOwnPropertyNames||function(t){return bt(t,_t)}},Et={f:Object.getOwnPropertySymbols},St=at("Reflect","ownKeys")||function(t){var e=wt.f(A(t)),n=Et.f;return n?e.concat(n(t)):e},Ot=function(t,e){for(var n=St(e),r=T.f,o=j.f,i=0;ib;b++)if((a||b in v)&&(p=g(s=v[b],b,d),t))if(e)_[b]=p;else if(p)switch(t){case 3:return!0;case 5:return s;case 6:return b;case 2:Wt.call(_,s)}else if(o)return!1;return i?-1:r||o?o:_}},qt={forEach:Kt(0),map:Kt(1),filter:Kt(2),some:Kt(3),every:Kt(4),find:Kt(5),findIndex:Kt(6)},Ht=at("navigator","userAgent")||"",Xt=o.process,Yt=Xt&&Xt.versions,Zt=Yt&&Yt.v8;Zt?et=(tt=Zt.split("."))[0]+tt[1]:Ht&&(!(tt=Ht.match(/Edge\/(\d+)/))||tt[1]>=74)&&(tt=Ht.match(/Chrome\/(\d+)/))&&(et=tt[1]);var Jt=et&&+et,Qt=Bt("species"),te=function(t){return Jt>=51||!i((function(){var e=[];return(e.constructor={})[Qt]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},ee=Object.defineProperty,ne={},re=function(t){throw t},oe=function(t,e){if(_(ne,t))return ne[t];e||(e={});var n=[][t],r=!!_(e,"ACCESSORS")&&e.ACCESSORS,o=_(e,0)?e[0]:re,c=_(e,1)?e[1]:void 0;return ne[t]=!!n&&!i((function(){if(r&&!a)return!0;var t={length:-1};r?ee(t,1,{enumerable:!0,get:re}):t[1]=1,n.call(t,o,c)}))},ie=qt.filter,ae=te("filter"),ce=oe("filter");Rt({target:"Array",proto:!0,forced:!ae||!ce},{filter:function(t){return ie(this,t,arguments.length>1?arguments[1]:void 0)}});var ue=function(t,e){var n=[][t];return!!n&&i((function(){n.call(null,e||function(){throw 1},1)}))},fe=qt.forEach,le=ue("forEach"),se=oe("forEach"),pe=le&&se?[].forEach:function(t){return fe(this,t,arguments.length>1?arguments[1]:void 0)};Rt({target:"Array",proto:!0,forced:[].forEach!=pe},{forEach:pe});var de=gt.indexOf,he=[].indexOf,ve=!!he&&1/[1].indexOf(1,-0)<0,ge=ue("indexOf"),ye=oe("indexOf",{ACCESSORS:!0,1:0});Rt({target:"Array",proto:!0,forced:ve||!ge||!ye},{indexOf:function(t){return ve?he.apply(this,arguments)||0:de(this,t,arguments.length>1?arguments[1]:void 0)}});var be=[].join,me=h!=Object,_e=ue("join",",");Rt({target:"Array",proto:!0,forced:me||!_e},{join:function(t){return be.call(g(this),void 0===t?",":t)}});var we=qt.map,Ee=te("map"),Se=oe("map");Rt({target:"Array",proto:!0,forced:!Ee||!Se},{map:function(t){return we(this,t,arguments.length>1?arguments[1]:void 0)}});var Oe=function(t){return function(e,n,r,o){Lt(n);var i=Mt(e),a=h(i),c=st(i.length),u=t?c-1:0,f=t?-1:1;if(r<2)for(;;){if(u in a){o=a[u],u+=f;break}if(u+=f,t?u<0:c<=u)throw TypeError("Reduce of empty array with no initial value")}for(;t?u>=0:c>u;u+=f)u in a&&(o=n(o,a[u],u,i));return o}},xe={left:Oe(!1),right:Oe(!0)}.left,je=ue("reduce"),Ae=oe("reduce",{1:0});Rt({target:"Array",proto:!0,forced:!je||!Ae},{reduce:function(t){return xe(this,t,arguments.length,arguments.length>1?arguments[1]:void 0)}});var Pe,Te=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{(t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(n,[]),e=n instanceof Array}catch(t){}return function(n,r){return A(n),function(t){if(!y(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype")}(r),e?t.call(n,r):n.__proto__=r,n}}():void 0),Ie=function(t,e,n){var r,o;return Te&&"function"==typeof(r=e.constructor)&&r!==n&&y(o=r.prototype)&&o!==n.prototype&&Te(t,o),t},Ce=Object.keys||function(t){return bt(t,mt)},Ne=a?Object.defineProperties:function(t,e){A(t);for(var n,r=Ce(e),o=r.length,i=0;o>i;)T.f(t,n=r[i++],e[n]);return t},Re=at("document","documentElement"),Le=K("IE_PROTO"),Me=function(){},De=function(t){return""+t+""},ke=function(){try{Pe=document.domain&&new ActiveXObject("htmlfile")}catch(t){}var t,e;ke=Pe?function(t){t.write(De("")),t.close();var e=t.parentWindow.Object;return t=null,e}(Pe):((e=S("iframe")).style.display="none",Re.appendChild(e),e.src=String("javascript:"),(t=e.contentWindow.document).open(),t.write(De("document.F=Object")),t.close(),t.F);for(var n=mt.length;n--;)delete ke.prototype[mt[n]];return ke()};q[Le]=!0;var Fe=Object.create||function(t,e){var n;return null!==t?(Me.prototype=A(t),n=new Me,Me.prototype=null,n[Le]=t):n=ke(),void 0===e?n:Ne(n,e)},Ue="\t\n\v\f\r                 \u2028\u2029\ufeff",$e="["+Ue+"]",Ge=RegExp("^"+$e+$e+"*"),Be=RegExp($e+$e+"*$"),Ve=function(t){return function(e){var n=String(v(e));return 1&t&&(n=n.replace(Ge,"")),2&t&&(n=n.replace(Be,"")),n}},ze={start:Ve(1),end:Ve(2),trim:Ve(3)},We=wt.f,Ke=j.f,qe=T.f,He=ze.trim,Xe="Number",Ye=o.Number,Ze=Ye.prototype,Je=p(Fe(Ze))==Xe,Qe=function(t){var e,n,r,o,i,a,c,u,f=b(t,!1);if("string"==typeof f&&f.length>2)if(43===(e=(f=He(f)).charCodeAt(0))||45===e){if(88===(n=f.charCodeAt(2))||120===n)return NaN}else if(48===e){switch(f.charCodeAt(1)){case 66:case 98:r=2,o=49;break;case 79:case 111:r=8,o=55;break;default:return+f}for(a=(i=f.slice(2)).length,c=0;c<48||u>o)return NaN;return parseInt(i,r)}return+f};if(Ct(Xe,!Ye(" 0o1")||!Ye("0b1")||Ye("+0x1"))){for(var tn,en=function(t){var e=arguments.length<1?0:t,n=this;return n instanceof en&&(Je?i((function(){Ze.valueOf.call(n)})):p(n)!=Xe)?Ie(new Ye(Qe(e)),n,en):Qe(e)},nn=a?We(Ye):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),rn=0;nn.length>rn;rn++)_(Ye,tn=nn[rn])&&!_(en,tn)&&qe(en,tn,Ke(Ye,tn));en.prototype=Ze,Ze.constructor=en,rt(o,Xe,en)}var on=j.f,an=i((function(){on(1)}));Rt({target:"Object",stat:!0,forced:!a||an,sham:!a},{getOwnPropertyDescriptor:function(t,e){return on(g(t),e)}});var cn=function(){var t=A(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e};function un(t,e){return RegExp(t,e)}var fn,ln,sn={UNSUPPORTED_Y:i((function(){var t=un("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),BROKEN_CARET:i((function(){var t=un("^r","gy");return t.lastIndex=2,null!=t.exec("str")}))},pn=RegExp.prototype.exec,dn=String.prototype.replace,hn=pn,vn=(fn=/a/,ln=/b*/g,pn.call(fn,"a"),pn.call(ln,"a"),0!==fn.lastIndex||0!==ln.lastIndex),gn=sn.UNSUPPORTED_Y||sn.BROKEN_CARET,yn=void 0!==/()??/.exec("")[1];(vn||yn||gn)&&(hn=function(t){var e,n,r,o,i=this,a=gn&&i.sticky,c=cn.call(i),u=i.source,f=0,l=t;return a&&(-1===(c=c.replace("y","")).indexOf("g")&&(c+="g"),l=String(t).slice(i.lastIndex),i.lastIndex>0&&(!i.multiline||i.multiline&&"\n"!==t[i.lastIndex-1])&&(u="(?: "+u+")",l=" "+l,f++),n=new RegExp("^(?:"+u+")",c)),yn&&(n=new RegExp("^"+u+"$(?!\\s)",c)),vn&&(e=i.lastIndex),r=pn.call(a?n:i,l),a?r?(r.input=r.input.slice(f),r[0]=r[0].slice(f),r.index=i.lastIndex,i.lastIndex+=r[0].length):i.lastIndex=0:vn&&r&&(i.lastIndex=i.global?r.index+r[0].length:e),yn&&r&&r.length>1&&dn.call(r[0],n,(function(){for(o=1;o")})),wn="$0"==="a".replace(/./,"$0"),En=Bt("replace"),Sn=!!/./[En]&&""===/./[En]("a","$0"),On=!i((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]})),xn=function(t,e,n,r){var o=Bt(t),a=!i((function(){var e={};return e[o]=function(){return 7},7!=""[t](e)})),c=a&&!i((function(){var e=!1,n=/a/;return"split"===t&&((n={}).constructor={},n.constructor[mn]=function(){return n},n.flags="",n[o]=/./[o]),n.exec=function(){return e=!0,null},n[o](""),!e}));if(!a||!c||"replace"===t&&(!_n||!wn||Sn)||"split"===t&&!On){var u=/./[o],f=n(o,""[t],(function(t,e,n,r,o){return e.exec===bn?a&&!o?{done:!0,value:u.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),{REPLACE_KEEPS_$0:wn,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:Sn}),l=f[0],s=f[1];rt(String.prototype,t,l),rt(RegExp.prototype,o,2==e?function(t,e){return s.call(t,this,e)}:function(t){return s.call(t,this)})}r&&I(RegExp.prototype[o],"sham",!0)},jn=function(t){return function(e,n){var r,o,i=String(v(e)),a=ft(n),c=i.length;return a<0||a>=c?t?"":void 0:(r=i.charCodeAt(a))<55296||r>56319||a+1===c||(o=i.charCodeAt(a+1))<56320||o>57343?t?i.charAt(a):r:t?i.slice(a,a+2):o-56320+(r-55296<<10)+65536}},An={codeAt:jn(!1),charAt:jn(!0)}.charAt,Pn=function(t,e,n){return e+(n?An(t,e).length:1)},Tn=function(t,e){var n=t.exec;if("function"==typeof n){var r=n.call(t,e);if("object"!=typeof r)throw TypeError("RegExp exec method returned something other than an Object or null");return r}if("RegExp"!==p(t))throw TypeError("RegExp#exec called on incompatible receiver");return bn.call(t,e)};xn("match",1,(function(t,e,n){return[function(e){var n=v(this),r=null==e?void 0:e[t];return void 0!==r?r.call(e,n):new RegExp(e)[t](String(n))},function(t){var r=n(e,t,this);if(r.done)return r.value;var o=A(t),i=String(this);if(!o.global)return Tn(o,i);var a=o.unicode;o.lastIndex=0;for(var c,u=[],f=0;null!==(c=Tn(o,i));){var l=String(c[0]);u[f]=l,""===l&&(o.lastIndex=Pn(i,st(o.lastIndex),a)),f++}return 0===f?null:u}]}));var In=Bt("match"),Cn=Bt("species"),Nn=[].push,Rn=Math.min,Ln=4294967295,Mn=!i((function(){return!RegExp(Ln,"y")}));xn("split",2,(function(t,e,n){var r;return r="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,n){var r,o,i=String(v(this)),a=void 0===n?Ln:n>>>0;if(0===a)return[];if(void 0===t)return[i];if(!y(r=t)||!(void 0!==(o=r[In])?o:"RegExp"==p(r)))return e.call(i,t,a);for(var c,u,f,l=[],s=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),d=0,h=new RegExp(t.source,s+"g");(c=bn.call(h,i))&&!((u=h.lastIndex)>d&&(l.push(i.slice(d,c.index)),c.length>1&&c.index=a));)h.lastIndex===c.index&&h.lastIndex++;return d===i.length?!f&&h.test("")||l.push(""):l.push(i.slice(d)),l.length>a?l.slice(0,a):l}:"0".split(void 0,0).length?function(t,n){return void 0===t&&0===n?[]:e.call(this,t,n)}:e,[function(e,n){var o=v(this),i=null==e?void 0:e[t];return void 0!==i?i.call(e,o,n):r.call(String(o),e,n)},function(t,o){var i=n(r,t,this,o,r!==e);if(i.done)return i.value;var a=A(t),c=String(this),u=function(t,e){var n,r=A(t).constructor;return void 0===r||null==(n=A(r)[Cn])?e:Lt(n)}(a,RegExp),f=a.unicode,l=(a.ignoreCase?"i":"")+(a.multiline?"m":"")+(a.unicode?"u":"")+(Mn?"y":"g"),s=new u(Mn?a:"^(?:"+a.source+")",l),p=void 0===o?Ln:o>>>0;if(0===p)return[];if(0===c.length)return null===Tn(s,c)?[c]:[];for(var d=0,h=0,v=[];ht.length)&&(e=t.length);for(var n=0,r=new Array(e);nn;n++)e[n]=arguments[n];var r=e[1];u(r)?g.apply(void 0,e):a(r)?b.apply(void 0,e):y.apply(void 0,e)},e.unwatch=function(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];var r=e[1];u(r)||void 0===r?E.apply(void 0,e):a(r)?_.apply(void 0,e):m.apply(void 0,e)},function(t){return"[object Array]"==={}.toString.call(t)}),c=function(t){return"[object Object]"==={}.toString.call(t)},u=function(t){return"[object Function]"==={}.toString.call(t)},f=function(t,e,n){(0,i.default)(t,e,{enumerable:!1,configurable:!0,writable:!1,value:n})},l=function(t,e,n,r){(0,i.default)(t,e,{get:n,set:function(t){r.call(this,t)},enumerable:!0,configurable:!0})},s=function(t,e,n,r,o){var i=void 0,a=t.__watchers__[e];(i=t.__watchers__.__watchall__)&&(a=a?a.concat(i):i);for(var c=a?a.length:0,u=0;c>u;u++)a[u].call(t,n,r,e,o)},p=["pop","push","reverse","shift","sort","unshift","splice"],d=function(t,e,n,r){f(t,n,(function(){for(var o=0,i=void 0,a=void 0,c=arguments.length,u=Array(c),f=0;c>f;f++)u[f]=arguments[f];if("splice"===n){var l=u[0],s=l+u[1];i=t.slice(l,s),a=[];for(var p=2;p0?u:void 0:u.length>0?u[0]:void 0;var d=e.apply(t,u);return"pop"===n?(i=d,o=t.length):"push"===n?o=t.length-1:"shift"===n?i=d:"unshift"!==n&&void 0===a&&(a=d),r.call(t,o,n,a,i),d}))},h=function(t,e){if(u(e)&&t&&!(t instanceof String)&&a(t))for(var n=p.length;n>0;n--){var r=p[n-1];d(t,t[r],r,e)}},v=function(t,e,n,r){var u=!1,p=a(t);void 0===t.__watchers__&&(f(t,"__watchers__",{}),p&&h(t,(function(n,o,i,u){if(s(t,n,i,u,o),0!==r&&i&&(c(i)||a(i))){var f=void 0,l=t.__watchers__[e];(f=t.__watchers__.__watchall__)&&(l=l?l.concat(f):f);for(var p=l?l.length:0,d=0;p>d;d++)if("splice"!==o)g(i,l[d],void 0===r?r:r-1);else for(var h=0;hi;i++)o[i]=arguments[i];return n[e].apply(t,o)})})),["writable","value"].forEach((function(t){void 0!==n[t]&&(r[t]=n[t])})),(0,i.default)(t.__proxy__,e,r)}():t.__proxy__[e]=t[e];var u=function(n){var o=t.__proxy__[e];if(0!==r&&t[e]&&(c(t[e])||a(t[e]))&&!t[e].__watchers__)for(var i=0;i0)for(var o=0;o0)&&g(t[e],n,void 0!==r?r-1:r),v(t,e,n,r)))},b=function(t,e,n,r){if("string"!=typeof t&&(t instanceof Object||a(t)))for(var o=0;o]*>)/g,ar=/\$([$&'`]|\d\d?)/g;xn("replace",2,(function(t,e,n,r){var o=r.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,i=r.REPLACE_KEEPS_$0,a=o?"$":"$0";return[function(n,r){var o=v(this),i=null==n?void 0:n[t];return void 0!==i?i.call(n,o,r):e.call(String(o),n,r)},function(t,r){if(!o&&i||"string"==typeof r&&-1===r.indexOf(a)){var u=n(e,t,this,r);if(u.done)return u.value}var f=A(t),l=String(this),s="function"==typeof r;s||(r=String(r));var p=f.global;if(p){var d=f.unicode;f.lastIndex=0}for(var h=[];;){var v=Tn(f,l);if(null===v)break;if(h.push(v),!p)break;""===String(v[0])&&(f.lastIndex=Pn(l,st(f.lastIndex),d))}for(var g,y="",b=0,m=0;m=b&&(y+=l.slice(b,w)+j,b=w+_.length)}return y+l.slice(b)}];function c(t,n,r,o,i,a){var c=r+t.length,u=o.length,f=ar;return void 0!==i&&(i=Mt(i),f=ir),e.call(a,f,(function(e,a){var f;switch(a.charAt(0)){case"$":return"$";case"&":return t;case"`":return n.slice(0,r);case"'":return n.slice(c);case"<":f=i[a.slice(1,-1)];break;default:var l=+a;if(0===l)return e;if(l>u){var s=or(l/10);return 0===s?e:s<=u?void 0===o[s-1]?a.charAt(1):o[s-1]+a.charAt(1):e}f=o[l-1]}return void 0===f?"":f}))}}));var cr,ur,fr,lr=function(t){return t.replace(/([A-Z])/g,(function(t){return"-".concat(t).toLowerCase()}))},sr=wt.f,pr={}.toString,dr="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],hr={f:function(t){return dr&&"[object Window]"==pr.call(t)?function(t){try{return sr(t)}catch(t){return dr.slice()}}(t):sr(g(t))}},vr={f:Bt},gr=T.f,yr=T.f,br=Bt("toStringTag"),mr=qt.forEach,_r=K("hidden"),wr="Symbol",Er=Bt("toPrimitive"),Sr=nt.set,Or=nt.getterFor(wr),xr=Object.prototype,jr=o.Symbol,Ar=at("JSON","stringify"),Pr=j.f,Tr=T.f,Ir=hr.f,Cr=f.f,Nr=G("symbols"),Rr=G("op-symbols"),Lr=G("string-to-symbol-registry"),Mr=G("symbol-to-string-registry"),Dr=G("wks"),kr=o.QObject,Fr=!kr||!kr.prototype||!kr.prototype.findChild,Ur=a&&i((function(){return 7!=Fe(Tr({},"a",{get:function(){return Tr(this,"a",{value:7}).a}})).a}))?function(t,e,n){var r=Pr(xr,e);r&&delete xr[e],Tr(t,e,n),r&&t!==xr&&Tr(xr,e,r)}:Tr,$r=function(t,e){var n=Nr[t]=Fe(jr.prototype);return Sr(n,{type:wr,tag:t,description:e}),a||(n.description=e),n},Gr=Ft?function(t){return"symbol"==typeof t}:function(t){return Object(t)instanceof jr},Br=function(t,e,n){t===xr&&Br(Rr,e,n),A(t);var r=b(e,!0);return A(n),_(Nr,r)?(n.enumerable?(_(t,_r)&&t[_r][r]&&(t[_r][r]=!1),n=Fe(n,{enumerable:l(0,!1)})):(_(t,_r)||Tr(t,_r,l(1,{})),t[_r][r]=!0),Ur(t,r,n)):Tr(t,r,n)},Vr=function(t,e){A(t);var n=g(e),r=Ce(n).concat(qr(n));return mr(r,(function(e){a&&!zr.call(n,e)||Br(t,e,n[e])})),t},zr=function(t){var e=b(t,!0),n=Cr.call(this,e);return!(this===xr&&_(Nr,e)&&!_(Rr,e))&&(!(n||!_(this,e)||!_(Nr,e)||_(this,_r)&&this[_r][e])||n)},Wr=function(t,e){var n=g(t),r=b(e,!0);if(n!==xr||!_(Nr,r)||_(Rr,r)){var o=Pr(n,r);return!o||!_(Nr,r)||_(n,_r)&&n[_r][r]||(o.enumerable=!0),o}},Kr=function(t){var e=Ir(g(t)),n=[];return mr(e,(function(t){_(Nr,t)||_(q,t)||n.push(t)})),n},qr=function(t){var e=t===xr,n=Ir(e?Rr:g(t)),r=[];return mr(n,(function(t){!_(Nr,t)||e&&!_(xr,t)||r.push(Nr[t])})),r};(kt||(rt((jr=function(){if(this instanceof jr)throw TypeError("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?String(arguments[0]):void 0,e=z(t),n=function(t){this===xr&&n.call(Rr,t),_(this,_r)&&_(this[_r],e)&&(this[_r][e]=!1),Ur(this,e,l(1,t))};return a&&Fr&&Ur(xr,e,{configurable:!0,set:n}),$r(e,t)}).prototype,"toString",(function(){return Or(this).tag})),rt(jr,"withoutSetter",(function(t){return $r(z(t),t)})),f.f=zr,T.f=Br,j.f=Wr,wt.f=hr.f=Kr,Et.f=qr,vr.f=function(t){return $r(Bt(t),t)},a&&(Tr(jr.prototype,"description",{configurable:!0,get:function(){return Or(this).description}}),rt(xr,"propertyIsEnumerable",zr,{unsafe:!0}))),Rt({global:!0,wrap:!0,forced:!kt,sham:!kt},{Symbol:jr}),mr(Ce(Dr),(function(t){!function(t){var e=ot.Symbol||(ot.Symbol={});_(e,t)||gr(e,t,{value:vr.f(t)})}(t)})),Rt({target:wr,stat:!0,forced:!kt},{for:function(t){var e=String(t);if(_(Lr,e))return Lr[e];var n=jr(e);return Lr[e]=n,Mr[n]=e,n},keyFor:function(t){if(!Gr(t))throw TypeError(t+" is not a symbol");if(_(Mr,t))return Mr[t]},useSetter:function(){Fr=!0},useSimple:function(){Fr=!1}}),Rt({target:"Object",stat:!0,forced:!kt,sham:!a},{create:function(t,e){return void 0===e?Fe(t):Vr(Fe(t),e)},defineProperty:Br,defineProperties:Vr,getOwnPropertyDescriptor:Wr}),Rt({target:"Object",stat:!0,forced:!kt},{getOwnPropertyNames:Kr,getOwnPropertySymbols:qr}),Rt({target:"Object",stat:!0,forced:i((function(){Et.f(1)}))},{getOwnPropertySymbols:function(t){return Et.f(Mt(t))}}),Ar)&&Rt({target:"JSON",stat:!0,forced:!kt||i((function(){var t=jr();return"[null]"!=Ar([t])||"{}"!=Ar({a:t})||"{}"!=Ar(Object(t))}))},{stringify:function(t,e,n){for(var r,o=[t],i=1;arguments.length>i;)o.push(arguments[i++]);if(r=e,(y(e)||void 0!==t)&&!Gr(t))return Dt(e)||(e=function(t,e){if("function"==typeof r&&(e=r.call(this,t,e)),!Gr(e))return e}),o[1]=e,Ar.apply(null,o)}});jr.prototype[Er]||I(jr.prototype,Er,jr.prototype.valueOf),ur=wr,(cr=jr)&&!_(cr=fr?cr:cr.prototype,br)&&yr(cr,br,{configurable:!0,value:ur}),q[_r]=!0,Rt({target:"Object",stat:!0,forced:i((function(){Ce(1)}))},{keys:function(t){return Ce(Mt(t))}});var Hr=function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r0&&void 0!==arguments[0]?arguments[0]:{};return(t=Hr({},t)).readOnly=t.readOnly||!1,t.reflectToAttribute=t.reflectToAttribute||!1,t.value=t.value,t.type=t.type,t},Yr=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0,r={enumerable:!0,configurable:!0,writable:!(e=Xr(e)).readOnly,value:er(e.value)?e.value.call(n):e.value};Object.defineProperty(n,t,r)},Zr=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0,r=arguments.length>3?arguments[3]:void 0;!(e=Xr(e)).value&&0!==e.value||n[t]||(e.type===Boolean?n[t]=(!e.reflectToAttribute||"false"!==r.dataset[t])&&e.value:er(e.value)?n[t]=e.value.call(n):n[t]=e.value)},Jr=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;if((e=Xr(e)).reflectToAttribute){var r=lr("data-".concat(t)),o=Object.getOwnPropertyDescriptor(n,t),i={enumerable:o.enumerable,configurable:o.configurable,get:function(){return e.type===Boolean?""===this.element.dataset[t]:e.type===Number?Number(this.element.dataset[t]):this.element.dataset[t]},set:function(n){var o=!n&&0!==n;if(e.type===Boolean||o)return this.element[o?"removeAttribute":"setAttribute"](r,e.type===Boolean?"":n);this.element.dataset[t]=n}};Object.defineProperty(n,t,i)}},Qr=function(t,e){var n=t.split("."),r=n.pop();return{parent:function(t,e){return t.split(".").reduce((function(t,e){return t[e]}),e)}(n.join("."),e),prop:r}},to=function(t){return tr(t.observers)?t.observers.map((function(t){var e=Bn(t.match(/([a-zA-Z-_]+)\(([^)]*)\)/),3),n=e[1],r=e[2];return{fn:n,args:r=r.split(",").map((function(t){return t.trim()})).filter((function(t){return t.length}))}})).filter((function(e){var n=e.fn;return er(t[n])})):[]},eo=function(t){return tr(t.listeners)?t.listeners.map((function(t){var e=Bn(t.match(/(.*\.)?([a-zA-Z-_]+)\(([^)]*)\)/),4),n=e[1],r=e[2],o=e[3];return o=o.split(",").map((function(t){return t.trim()})).filter((function(t){return t.length})),{element:n=n?n.substr(0,n.length-1):"element",fn:r,events:o}})).filter((function(e){var n=e.element,r=e.fn;return er(t[r])&&("document"===n||"window"===n||qn(t[n])||t[n]&&qn(t[n].element))})):[]},no=function(t){var e=function(t){return tr(t.mixins)?t.mixins.filter((function(t){return"object"===Gn(t)})):[]}(t);return e.unshift({}),Hr.apply(null,e)},ro=function(t,e){if(t&&"object"===Gn(t)&&qn(e)){t.element=e;var n={$set:function(t,e){if(t&&void 0!==e&&void 0!==this.properties&&this.properties.hasOwnProperty(t)){var n=Xr(this.properties[t]),r=Object.getOwnPropertyDescriptor(this,t);if(n.readOnly&&void 0!==r.writable){var o={enumerable:r.enumerable,configurable:r.configurable,writable:!1,value:e};Object.defineProperty(this,t,o)}else this[t]=e}},init:function(){var e;to(e=this).forEach((function(t){var n=t.fn,r=t.args;e[n]=e[n].bind(e),r.forEach((function(t){if(-1!==t.indexOf(".")){var r=Qr(t,e),o=r.prop,i=r.parent;Kn.watch(i,o,e[n])}else Kn.watch(e,t,e[n])}))})),function(t){eo(t).forEach((function(e){var n=e.element,r=e.fn,o=e.events;t[r]=t[r].bind(t),"document"===n?n=t.element.ownerDocument:"window"===n?n=window:qn(t[n])?n=t[n]:qn(t[n].element)&&(n=t[n].element),n&&o.forEach((function(e){return n.addEventListener(e,t[r])}))}))}(this),er(t.init)&&t.init.call(this)},destroy:function(){var e=this;to(t).forEach((function(t){var n=t.fn;t.args.forEach((function(t){if(-1!==t.indexOf(".")){var r=Qr(t,e),o=r.prop,i=r.parent;Kn.unwatch(i,o,e[n])}else Kn.unwatch(e,t,e[n])}))})),eo(t).forEach((function(t){var n=t.element,r=t.fn,o=t.events;"document"===n?n=e.element.ownerDocument:"window"===n?n=window:qn(e[n])?n=e[n]:qn(e[n].element)&&(n=e[n].element),n&&o.forEach((function(t){return n.removeEventListener(t,e[r])}))})),er(t.destroy)&&t.destroy.call(this)},fire:function(t){var e,n=!1;if("CustomEvent"in window&&"object"===Gn(window.CustomEvent))try{e=new CustomEvent(t,{bubbles:n,cancelable:!1})}catch(r){e=new this.CustomEvent_(t,{bubbles:n,cancelable:!1})}else(e=document.createEvent("Event")).initEvent(t,n,!0);this.element.dispatchEvent(e)},CustomEvent_:function(t,e){e=e||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(t,e.bubbles,e.cancelable,e.detail),n}};return function(t,e){if("object"===Gn(t.properties))for(var n in t.properties)if(t.properties.hasOwnProperty(n)){var r=t.properties[n];Yr(n,r,t),Jr(n,r,t),Zr(n,r,t,e)}}(t,e),(n=Hr({},no(t),t,n)).init(),n}console.error("[dom-factory] Invalid factory.",t,e)},oo=Bt("unscopables"),io=Array.prototype;null==io[oo]&&T.f(io,oo,{configurable:!0,value:Fe(null)});var ao=qt.find,co="find",uo=!0,fo=oe(co);co in[]&&Array(1).find((function(){uo=!1})),Rt({target:"Array",proto:!0,forced:uo||!fo},{find:function(t){return ao(this,t,arguments.length>1?arguments[1]:void 0)}}),function(t){io[oo][t]=!0}(co);var lo=function(t,e,n){var r=b(e);r in t?T.f(t,r,l(0,n)):t[r]=n},so=te("splice"),po=oe("splice",{ACCESSORS:!0,0:0,1:2}),ho=Math.max,vo=Math.min,go=9007199254740991,yo="Maximum allowed length exceeded";Rt({target:"Array",proto:!0,forced:!so||!po},{splice:function(t,e){var n,r,o,i,a,c,u=Mt(this),f=st(u.length),l=ht(t,f),s=arguments.length;if(0===s?n=r=0:1===s?(n=0,r=f-l):(n=s-2,r=vo(ho(ft(e),0),f-l)),f+n-r>go)throw TypeError(yo);for(o=zt(u,r),i=0;if-r+n;i--)delete u[i-1]}else if(n>r)for(i=f-r;i>l;i--)c=i+n-1,(a=i+r-1)in u?u[c]=u[a]:delete u[c];for(i=0;io;)for(var u,l=h(arguments[o++]),s=i?Ce(l).concat(i(l)):Ce(l),p=s.length,d=0;p>d;)u=s[d++],a&&!c.call(l,u)||(n[u]=l[u]);return n}:bo;Rt({target:"Object",stat:!0,forced:Object.assign!==_o},{assign:_o});var wo=function(t){return t.replace(/(\-[a-z])/g,(function(t){return t.toUpperCase().replace("-","")}))},Eo="__domFactoryConfig",So={autoInit:function(){["DOMContentLoaded","load"].forEach((function(t){window.addEventListener(t,(function(){return So.upgradeAll()}))}))},_registered:[],_created:[],register:function(t,e){var n="js-".concat(t);this.findRegistered(t)||this._registered.push({id:t,cssClass:n,callbacks:[],factory:e})},registerUpgradedCallback:function(t,e){var n=this.findRegistered(t);n&&n.callbacks.push(e)},findRegistered:function(t){return this._registered.find((function(e){return e.id===t}))},findCreated:function(t){return this._created.filter((function(e){return e.element===t}))},upgradeElement:function(t,e){var n=this;if(void 0!==e){var r=t.getAttribute("data-domfactory-upgraded"),o=this.findRegistered(e);if(!o||null!==r&&-1!==r.indexOf(e)){if(o){var i=t[wo(e)];"function"==typeof i._reset&&i._reset()}}else{var a;(r=null===r?[]:r.split(",")).push(e);try{a=ro(o.factory(t),t)}catch(t){console.error(e,t.message,t.stack)}if(a){t.setAttribute("data-domfactory-upgraded",r.join(","));var c=Object.assign({},o);delete c.factory,a[Eo]=c,this._created.push(a),Object.defineProperty(t,wo(e),{configurable:!0,writable:!1,value:a}),o.callbacks.forEach((function(e){return e(t)})),a.fire("domfactory-component-upgraded")}}}else this._registered.forEach((function(e){t.classList.contains(e.cssClass)&&n.upgradeElement(t,e.id)}))},upgrade:function(t){var e=this;if(void 0===t)this.upgradeAll();else{var n=this.findRegistered(t);if(n)Vn(document.querySelectorAll("."+n.cssClass)).forEach((function(n){return e.upgradeElement(n,t)}))}},upgradeAll:function(){var t=this;this._registered.forEach((function(e){return t.upgrade(e.id)}))},downgradeComponent:function(t){t.destroy();var e=this._created.indexOf(t);this._created.splice(e,1);var n=t.element.getAttribute("data-domfactory-upgraded").split(","),r=n.indexOf(t[Eo].id);n.splice(r,1),t.element.setAttribute("data-domfactory-upgraded",n.join(",")),t.fire("domfactory-component-downgraded")},downgradeElement:function(t){this.findCreated(t).forEach(this.downgradeComponent,this)},downgradeAll:function(){this._created.forEach(this.downgradeComponent,this)},downgrade:function(t){var e=this;t instanceof Array||t instanceof NodeList?(t instanceof NodeList?Vn(t):t).forEach((function(t){return e.downgradeElement(t)})):t instanceof Node&&this.downgradeElement(t)}},Oo={assign:Hr,isArray:tr,isElement:qn,isFunction:er,toKebabCase:lr,transform:function(t,e){["transform","WebkitTransform","msTransform","MozTransform","OTransform"].map((function(n){return e.style[n]=t}))}};t.factory=ro,t.handler=So,t.util=Oo,Object.defineProperty(t,"__esModule",{value:!0})})); diff --git a/package.json b/package.json index b690a38..9af3987 100644 --- a/package.json +++ b/package.json @@ -1,29 +1,31 @@ { "name": "dom-factory", - "version": "1.0.0-alpha.4", + "version": "1.1.0", "description": "Enhance HTML elements using plain JavaScript objects.", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "dev": "webpack --config build/webpack.config.dev.js --progress --watch", - "build": "NODE_ENV=production webpack --config build/webpack.config.production.js --progress", - "build-dev": "webpack --config build/webpack.config.dev.js --progress" + "build": "rollup -c --environment BUILD:production", + "watch": "rollup -c --watch" }, - "main": "dist/dom-factory.js", + "main": "dist/dom-factory.common.js", + "module": "dist/dom-factory.esm.js", + "browser": "dist/dom-factory.js", "author": "Laza Bogdan ", "license": "ISC", "devDependencies": { - "babel-core": "^6.4.0", - "babel-loader": "^6.2.1", - "babel-plugin-transform-runtime": "^6.4.3", - "babel-preset-es2015": "^6.3.13", - "babel-runtime": "^5.8.34", - "eslint": "^1.10.3", - "eslint-loader": "^1.2.0", - "webpack": "^1.12.11", - "webpack-config-api": "^0.2.1" + "@babel/core": "^7.11.6", + "@babel/plugin-transform-runtime": "^7.11.5", + "@babel/preset-env": "^7.11.5", + "@rollup/plugin-alias": "^3.1.1", + "@rollup/plugin-babel": "^5.2.1", + "@rollup/plugin-commonjs": "^15.1.0", + "@rollup/plugin-node-resolve": "^9.0.0", + "rollup": "^2.28.2", + "rollup-plugin-peer-deps-external": "^2.2.0", + "rollup-plugin-terser": "^7.0.2", + "watch-object": "^1.1.2" }, "dependencies": { - "watch-object": "^1.1.2" + "core-js": "^3.6.5" }, "keywords": [ "dom", @@ -38,10 +40,10 @@ ], "repository": { "type": "git", - "url": "git+https://github.com/themekit/dom-factory.git" + "url": "git+https://github.com/FrontendMatter/dom-factory.git" }, "bugs": { - "url": "https://github.com/themekit/dom-factory/issues" + "url": "https://github.com/FrontendMatter/dom-factory/issues" }, - "homepage": "https://github.com/themekit/dom-factory#readme" + "homepage": "https://github.com/FrontendMatter/dom-factory#readme" } diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..685e56b --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,65 @@ +import alias from '@rollup/plugin-alias' +import resolve from '@rollup/plugin-node-resolve' +import commonjs from '@rollup/plugin-commonjs' +import babel from '@rollup/plugin-babel' +import { terser } from 'rollup-plugin-terser' + +const path = require('path') + +const plugins = [ + alias({ + entries: [ + { + find: '~', + replacement: path.resolve(__dirname, 'src') + } + ] + }), + resolve(), + commonjs() +] + +const baseConfig = { + input: 'src/index.js' +} + +export default [ + // EMS Module + { + ...baseConfig, + output: [{ + format: 'es', + file: 'dist/dom-factory.esm.js' + }], + plugins + }, + + // SSR build. + { + ...baseConfig, + output: { + format: 'cjs', + file: 'dist/dom-factory.common.js' + }, + plugins + }, + + // UMD Browser + { + ...baseConfig, + output: { + format: 'umd', + name: 'domFactory', + file: 'dist/dom-factory.js' + }, + plugins: [ + ...plugins, + babel({ + babelHelpers: 'bundled', + skipPreflightCheck: true, + exclude: 'node_modules/**' + }), + terser() + ] + } +] \ No newline at end of file diff --git a/src/factory/factory.js b/src/factory/factory.js index f0fcac0..f17c620 100644 --- a/src/factory/factory.js +++ b/src/factory/factory.js @@ -39,18 +39,25 @@ const createProp = (prop, opts = {}, src) => { /** * Set the initial value for a property * @param {String} prop The property name - * @param {?} value The property value + * @param {Object} opts The property options * @param {Object} src The source object */ -const propValue = (prop, value, src) => { - if (!value || !!src[prop]) { +const propValue = (prop, opts = {}, src, element) => { + opts = propOptions(opts) + if ((!opts.value && opts.value !== 0) || !!src[prop]) { return } - if (isFunction(value)) { - src[prop] = value.call(src) + + if (opts.type === Boolean) { + src[prop] = opts.reflectToAttribute && element.dataset[prop] === 'false' + ? false + : opts.value + } + else if (isFunction(opts.value)) { + src[prop] = opts.value.call(src) } else { - src[prop] = value + src[prop] = opts.value } } @@ -65,18 +72,26 @@ const reflectToAttribute = (prop, opts = {}, src) => { if (!opts.reflectToAttribute) { return } - const propKebab = toKebabCase(prop) + const propKebab = toKebabCase(`data-${prop}`) const descriptor = Object.getOwnPropertyDescriptor(src, prop) const property = { enumerable: descriptor.enumerable, configurable: descriptor.configurable, get: function () { - return opts.type === Boolean - ? this.element.hasAttribute(propKebab) - : this.element.getAttribute(propKebab) + if (opts.type === Boolean) { + return this.element.dataset[prop] === '' + } + if (opts.type === Number) { + return Number(this.element.dataset[prop]) + } + return this.element.dataset[prop] }, set: function (value) { - this.element[value ? 'setAttribute' : 'removeAttribute'](propKebab, opts.type === Boolean ? prop : value) + const removable = !value && value !== 0 + if (opts.type === Boolean || removable) { + return this.element[!removable ? 'setAttribute' : 'removeAttribute'](propKebab, opts.type === Boolean ? '' : value) + } + this.element.dataset[prop] = value } } Object.defineProperty(src, prop, property) @@ -86,7 +101,7 @@ const reflectToAttribute = (prop, opts = {}, src) => { * Create properties * @param {Object} src The source object */ -const makeProperties = (src) => { +const makeProperties = (src, element) => { if (typeof src.properties !== 'object') { return } @@ -96,7 +111,7 @@ const makeProperties = (src) => { createProp(prop, opts, src) reflectToAttribute(prop, opts, src) - propValue(prop, opts.value, src) + propValue(prop, opts, src, element) } } } @@ -179,7 +194,7 @@ const listeners = (src) => { element === 'document' || element === 'window' || isElement(src[element]) || - isElement(src[element]['element'])) + (src[element] && isElement(src[element]['element']) )) }) } @@ -324,21 +339,37 @@ export const factory = (factory, element) => { */ fire (eventName) { let event + let bubbles = false if ('CustomEvent' in window && typeof window.CustomEvent === 'object') { - event = new CustomEvent(eventName, { - bubbles: true, - cancelable: false - }) + try { + event = new CustomEvent(eventName, { + bubbles, + cancelable: false + }) + } + catch (e) { + event = new this.CustomEvent_(eventName, { + bubbles, + cancelable: false + }) + } } else { event = document.createEvent('Event') - event.initEvent(eventName, true, true) + event.initEvent(eventName, bubbles, true) } this.element.dispatchEvent(event) + }, + + CustomEvent_ (event, params) { + params = params || { bubbles: false, cancelable: false, detail: undefined } + var evt = document.createEvent('CustomEvent') + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail) + return evt } } - makeProperties(factory) + makeProperties(factory, element) component = assign( {}, diff --git a/src/handler/handler.js b/src/handler/handler.js index 3df3ea3..bfd82b2 100644 --- a/src/handler/handler.js +++ b/src/handler/handler.js @@ -11,6 +11,12 @@ const CONFIG_PROPERTY = '__domFactoryConfig' */ export const handler = { + autoInit () { + ['DOMContentLoaded', 'load'].forEach(function (e) { + window.addEventListener(e, () => handler.upgradeAll()) + }) + }, + // Registered components _registered: [], @@ -24,11 +30,7 @@ export const handler = { */ register (id, factory) { const callbacks = [] - - let idChunks = id.split('-') - idChunks.splice(1, 0, 'js') - - const cssClass = idChunks.join('-') + const cssClass = `js-${ id }` if (!this.findRegistered(id)) { this._registered.push({ @@ -38,7 +40,6 @@ export const handler = { factory }) } - this.upgrade(id) }, /** @@ -157,6 +158,7 @@ export const handler = { * @param {Object} component */ downgradeComponent (component) { + component.destroy() const index = this._created.indexOf(component) this._created.splice(index, 1) @@ -172,14 +174,14 @@ export const handler = { * @param {HTMLElement} element */ downgradeElement (element) { - this.findCreated(element).forEach(this.downgradeComponent) + this.findCreated(element).forEach(this.downgradeComponent, this) }, /** * Downgrade all the created components. */ downgradeAll () { - this._created.forEach(this.downgradeComponent) + this._created.forEach(this.downgradeComponent, this) }, /** @@ -195,6 +197,4 @@ export const handler = { this.downgradeElement(node) } } -} - -window.addEventListener('load', () => handler.upgradeAll()) \ No newline at end of file +} \ No newline at end of file