115 lines
3.9 KiB
JavaScript
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);
|
|
});
|
|
});
|
|
}
|