Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save matipojo/044fd89844ab6b7c63a43984cf84df2e to your computer and use it in GitHub Desktop.

Select an option

Save matipojo/044fd89844ab6b7c63a43984cf84df2e to your computer and use it in GitHub Desktop.
A demonstration of advanced elements manipulation before save in Elementor Editor
class Component extends $e.modules.ComponentBase {
getNamespace() {
return 'elements-checker';
}
defaultHooks() {
// It should be in a separated file and imported with `import * as hooks from './hooks';`
// this.importHooks( hooks );
return {
// The `dependency` hook runs before the specified command.
// It returns true/false whether to continue the save or not.
'check-elements-before-save': new class extends $e.modules.hookData.Dependency {
getCommand() {
return 'document/save/save';
}
getId() {
return 'check-elements-before-save';
}
getConditions( args ) {
return 'publish' === args.status && ! args.force; // Don't check if it's a forced save.
}
apply() {
const restoreEditorState = this.switchToDesktopTop();
const hideNotification = this.showNotification();
// Check elements here
const elements = this.getFlattedElementsList( elementor.getPreviewContainer().children );
// Reset all elements
this.setAboveTheFold( elements, false );
const devices = elementor.breakpoints.getActiveBreakpointsList( { largeToSmall: true, withDesktop: true } );
devices.forEach( ( device ) => {
$e.run( 'panel/change-device-mode', { device } );
// Filter elements that are above the fold
const aboveTheFoldElements = this.getElementsAboveTheFold( elements );
this.setAboveTheFold( aboveTheFoldElements, true );
} );
restoreEditorState();
hideNotification();
return true; // Continue the save
}
switchToDesktopTop() {
const currentDeviceMode = elementor.channels.deviceMode.request( 'currentMode' ),
iframeWindow = elementor.$preview[ 0 ].contentWindow,
currentScrollPosition = iframeWindow.scrollY;
$e.run( 'panel/change-device-mode', { device: 'desktop' } );
iframeWindow.scrollTo( 0, 0 );
return () => {
$e.run( 'panel/change-device-mode', { device: currentDeviceMode } );
iframeWindow.scrollTo( 0, currentScrollPosition );
};
}
showNotification() {
const notification = elementor.notifications.showToast( {
message: 'Performance Improving. Checking elements above the fold...',
} );
return () => {
// Show the notification for at least 2 seconds
setTimeout( () => {
notification.hide();
}, 2000 );
};
}
getFlattedElementsList( elements ) {
let flatted = [];
for ( const element of elements ) {
flatted.push( element );
if ( element.children.length ) {
flatted = flatted.concat( this.getFlattedElementsList( element.children ) );
}
}
return flatted;
}
setAboveTheFold( elements, value ) {
elements.forEach( ( element ) => {
if ( ( !! element.settings.get( 'is_above_the_fold' ) ) === value ) {
return;
}
// Use the internal command because it's not a user action
$e.internal( 'document/elements/set-settings', {
container: element,
settings: {
is_above_the_fold: value, // Todo: if `false` then remove the setting
},
options: {
external: true, // Update panel if it's open
render: false, // Don't re-render the element
},
} );
} );
}
getElementsAboveTheFold( elements ) {
return elements.filter( ( element ) => {
// Is the element visible?
if ( ! element.view.el.offsetParent ) {
return false;
}
const elementRect = element.view.el.getBoundingClientRect();
return elementRect.top < window.innerHeight;
} );
}
},
};
}
}
// Should be registered from the module file
$e.components.register( new Component() );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment