Files
medicalalert-web-reloaded/wp/wp-content/plugins/divi-builder/includes/builder/scripts/frontend/sticky-elements.js
Tony Volpe 4eb982d7a8 Merged in feature/from-pantheon (pull request #16)
code from pantheon

* code from pantheon
2024-01-10 17:03:02 +00:00

115 lines
3.9 KiB
JavaScript

// External Dependencies
import difference from 'lodash/difference';
import forEach from 'lodash/forEach';
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import keys from 'lodash/keys';
import pick from 'lodash/pick';
import $ from 'jquery';
// Internal dependencies
import ETScriptStickyElement from './sticky-element';
import ETScriptStickyStore from '../stores/sticky';
import {
isBFB,
isLBB,
isTB,
isVB,
} from '../utils/utils';
// Modules that use sticky element feature
const stickyInstances = {};
/**
* Initialize Sticky Elements;
* Front-end: loads settings from store (which is loaded from global variable passed
* via wp_localize_script())
* Builder: adds store listener which will listen to Sticky Element settings change
* pushed by builder's ETBuilderCustomCSSOutput component.
*
* @since 4.6.0
*/
if (isVB || isBFB || isTB || isLBB) {
/**
* Get Sticky Elements instances that need to be removed and unset from currently initialized
* stickyInstances list by incoming settings from store and stickyInstances.
*
* @since 4.6.0
*
* @returns {Array}
*/
function getUnsetStickyElements() {
// Get id of currently initialized ETScriptStickyElement
const currentInstanceIds = keys(stickyInstances);
// Get sticky settings from store
const stickyModules = ETScriptStickyStore.modules;
// Get id of settings from store
const stickyModuleIds = keys(stickyModules);
// If currently initialized ETScriptStickyElement id doesn't exist on store's settings id, it
// means the ETScriptStickyElement is either removed or has its sticky status removed
// (sticky_position attribute is set to `none`)
return difference(currentInstanceIds, stickyModuleIds);
}
/**
* Store's setting change listener callback.
*
* @since 4.6.0
*/
function onStickySettingsChange() {
// Loop over unset sticky elements then remove their instances
forEach(getUnsetStickyElements(), id => {
// End sticky state, and removed isSticky prop
stickyInstances[id].endSticky();
stickyInstances[id].setProp('isSticky', false);
// Remove ETScriptStickyElement listener
stickyInstances[id].removeListeners();
// Remove instance
delete stickyInstances[id];
});
// Loop over incoming sticky element settings from store
forEach(ETScriptStickyStore.modules, (settings, id) => {
// Check whether current setting has been initialized; if true, it means the sticky element
// is being updated
const currentStickyInstance = get(stickyInstances, id);
// Update sticky element
if (currentStickyInstance) {
// Check if current instance is equal to incoming settings from store. Current instance
// has less attribute than store's because some attribute are generated on the fly at store.
// Thus, omit attribute differences during comparison
const instanceSettingsKeys = keys(currentStickyInstance.getSettings());
const instanceInSettings = pick(settings, instanceSettingsKeys);
// If incoming settings are equal with current instance's settings, bail
if (isEqual(currentStickyInstance.getSettings(), instanceInSettings)) {
return;
}
// Update settings, then set initial props
stickyInstances[id].setSettings(settings, true);
} else {
// Create new ETScriptStickyElement instance
stickyInstances[id] = new ETScriptStickyElement(settings);
}
});
}
// Attach callback to store's settings change event
ETScriptStickyStore.addSettingsChangeListener(onStickySettingsChange);
} else {
// Need to wait until document is ready to get correct offset values
$(() => {
forEach(ETScriptStickyStore.modules, (settings, id) => {
// Create sticky element instance
stickyInstances[id] = new ETScriptStickyElement(settings);
});
});
}