@g2crowd/widget
Advanced tools
Comparing version 2.1.0 to 2.2.0
{ | ||
"name": "@g2crowd/widget", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"description": "Rails-friendly plugin wrapper", | ||
"repository": "https://github.com/g2crowd/widget", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/g2crowd/widget.git" | ||
}, | ||
"author": "Michael Wheeler", | ||
@@ -7,0 +10,0 @@ "license": "MIT", |
@@ -52,2 +52,4 @@ // @format | ||
import { strategies } from './strategies'; | ||
import { widgetTracker } from './widgetTracker'; | ||
import camelize from './camelize'; | ||
@@ -65,3 +67,5 @@ class AlreadyRegisteredError extends Error { | ||
const registered = {}; | ||
const initWidgets = widgetInitiator({ attr, data, registered }); | ||
const teardowns = widgetTracker(); | ||
const initiatedWidgets = widgetTracker(); | ||
const initWidgets = widgetInitiator({ attr, data, registered, teardowns, initiatedWidgets }); | ||
@@ -77,7 +81,7 @@ const register = function (name, plugin, settings = {}) { | ||
document.addEventListener(loadEvents, function () { | ||
function handleLoadEvents() { | ||
initWidgets(document.body.querySelectorAll(selector)); | ||
}); | ||
} | ||
document.addEventListener(fragmentLoadEvents, function (e) { | ||
function handleFragmentLoadEvents(e) { | ||
const targetElement = e.target; | ||
@@ -96,8 +100,57 @@ | ||
return false; | ||
}); | ||
} | ||
register.initAllWidgets = () => initWidgets(document.querySelectorAll(selector)); | ||
function teardownWidget(element, widgetName) { | ||
const teardown = teardowns.get(widgetName, element); | ||
const initiated = initiatedWidgets.get(widgetName, element); | ||
if (teardown && typeof teardown === 'function') { | ||
teardown(); | ||
teardowns.set(widgetName, element, undefined); | ||
} | ||
if (initiated) { | ||
initiatedWidgets.set(widgetName, element, undefined); | ||
delete element.dataset[`vvidget_${camelize(widgetName)}`]; | ||
} | ||
} | ||
function handleTeardownEvents(e) { | ||
const element = e.target; | ||
const widgetName = e.detail && e.detail.widgetName; | ||
if (widgetName) { | ||
teardownWidget(element, widgetName); | ||
} else { | ||
const names = `${element.dataset[camelize(data)] || ''} ${element.getAttribute(attr) || ''}`; | ||
names | ||
.split(' ') | ||
.filter((i) => i) | ||
.forEach((name) => teardownWidget(element, name)); | ||
} | ||
} | ||
document.addEventListener(loadEvents, handleLoadEvents); | ||
document.addEventListener(fragmentLoadEvents, handleFragmentLoadEvents); | ||
document.addEventListener('vvidget:teardown', handleTeardownEvents); | ||
register.strategies = strategies; | ||
register.initAllWidgets = () => initWidgets(document.querySelectorAll(selector)); | ||
register.teardownAllWidgets = () => { | ||
const event = new CustomEvent('vvidget:teardown', { bubbles: true }); | ||
document.body.querySelectorAll(selector).forEach((el) => el.dispatchEvent(event)); | ||
}; | ||
register.restartAllWidgets = () => { | ||
register.teardownAllWidgets(); | ||
register.initAllWidgets(); | ||
}; | ||
register.shutdown = () => { | ||
register.teardownAllWidgets(); | ||
document.removeEventListener(loadEvents, handleLoadEvents); | ||
document.removeEventListener(fragmentLoadEvents, handleFragmentLoadEvents); | ||
document.removeEventListener('vvidget:teardown', handleTeardownEvents); | ||
}; | ||
return register; | ||
@@ -104,0 +157,0 @@ }; |
import { extractOptions } from '@g2crowd/extract-options'; | ||
import camelize from './camelize'; | ||
import { strategies } from './strategies'; | ||
import { widgetTracker } from './widgetTracker'; | ||
const widgetTracker = function () { | ||
const elements = new WeakMap(); | ||
return { | ||
get: function (widgetName, element) { | ||
const widgets = elements.get(element); | ||
return widgets && widgets.get(widgetName); | ||
}, | ||
set: function (widgetName, element, value) { | ||
if (!elements.has(element)) { | ||
elements.set(element, new Map()); | ||
} | ||
elements.get(element).set(widgetName, value); | ||
}, | ||
has: function (widgetName, element) { | ||
return this.get(widgetName, element) !== undefined; | ||
} | ||
}; | ||
}; | ||
function simpleCaste(value) { | ||
@@ -47,47 +24,66 @@ try { | ||
function emit(element, eventName) { | ||
const event = new CustomEvent(eventName); | ||
function emit(element, eventName, data) { | ||
const event = new CustomEvent(eventName, { detail: data }); | ||
element.dispatchEvent(event); | ||
} | ||
const wrapPlugin = function wrapPlugin(name, pluginFn, element) { | ||
const ready = function ready() { | ||
emit(element, 'vvidget:initialized'); | ||
}; | ||
export const widgetInitiator = function ({ attr, data, registered, teardowns, initiatedWidgets }, fn) { | ||
const availableWidgets = registered || {}; | ||
initiatedWidgets = initiatedWidgets || widgetTracker(); | ||
return function () { | ||
const pluginName = camelize(name); | ||
const options = Object.assign({}, pluginFn.defaults, extractOptions(sanitizeDataset(element.dataset), pluginName)); | ||
pluginFn.call(element, options, ready); | ||
const wrapTeardown = function wrapTeardown(name, teardownFn, element) { | ||
return function () { | ||
if (typeof teardownFn === 'function') { | ||
teardownFn(); | ||
} | ||
initiatedWidgets.set(name, element, false); | ||
delete element.dataset[`vvidget_${camelize(name)}`]; | ||
}; | ||
}; | ||
}; | ||
async function startWidget(name, pluginFn, element) { | ||
const wrapped = wrapPlugin(name, pluginFn, element); | ||
const strategy = strategies.get(pluginFn.init); | ||
const wrapPlugin = function wrapPlugin(name, pluginFn, element) { | ||
const ready = function ready(teardown) { | ||
teardowns.set(name, element, teardown); | ||
emit(element, 'vvidget:initialized'); | ||
}; | ||
strategy(wrapped, element); | ||
} | ||
return function () { | ||
const pluginName = camelize(name); | ||
const options = Object.assign( | ||
{}, | ||
pluginFn.defaults, | ||
extractOptions(sanitizeDataset(element.dataset), pluginName) | ||
); | ||
return pluginFn.call(element, options, ready); | ||
}; | ||
}; | ||
const loadWidget = async function (element, name, availableWidgets, initiatedWidgets) { | ||
const pluginFn = availableWidgets[name]; | ||
async function startWidget(name, pluginFn, element) { | ||
const strategy = strategies.get(pluginFn.init); | ||
const wrapped = wrapPlugin(name, pluginFn, element); | ||
if (!pluginFn) { | ||
return; | ||
strategy(wrapped, element); | ||
} | ||
if (initiatedWidgets.get(name, element)) { | ||
return; | ||
} | ||
const loadWidget = async function (element, name) { | ||
const pluginFn = availableWidgets[name]; | ||
startWidget(name, pluginFn, element); | ||
if (!pluginFn) { | ||
return; | ||
} | ||
initiatedWidgets.set(name, element, true); | ||
element.dataset[`vvidget_${camelize(name)}`] = true; | ||
}; | ||
if (initiatedWidgets.get(name, element)) { | ||
return; | ||
} | ||
const initiatedWidgets = widgetTracker(); | ||
export const widgetInitiator = function ({ attr, data, registered }, fn = loadWidget) { | ||
registered = registered || {}; | ||
startWidget(name, pluginFn, element); | ||
emit(element, 'vvidget:load', { name }); | ||
initiatedWidgets.set(name, element, true); | ||
element.dataset[`vvidget_${camelize(name)}`] = true; | ||
}; | ||
fn = fn || loadWidget; | ||
return function initWidgets(elements) { | ||
@@ -100,5 +96,5 @@ elements.forEach(function (element) { | ||
.filter((i) => i) | ||
.forEach((name) => fn(element, name, registered, initiatedWidgets)); | ||
.forEach((name) => fn(element, name)); | ||
}); | ||
}; | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
11562
10
269
0