first commit

This commit is contained in:
2024-07-15 11:28:08 +02:00
commit f52d538ea5
21891 changed files with 6161164 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
import InstanceType from './instance-type';
export default class ArgsObject extends InstanceType {
static getInstanceType() {
return 'ArgsObject';
}
/**
* Function constructor().
*
* Create ArgsObject.
*
* @param {{}} args
*/
constructor( args ) {
super();
this.args = args;
}
/**
* Function requireArgument().
*
* Validate property in args.
*
* @param {string} property
* @param {{}} args
*
* @throws {Error}
*
*/
requireArgument( property, args = this.args ) {
if ( ! args.hasOwnProperty( property ) ) {
throw Error( `${ property } is required.` );
}
}
/**
* Function requireArgumentType().
*
* Validate property in args using `type === typeof(args.whatever)`.
*
* @param {string} property
* @param {string} type
* @param {{}} args
*
* @throws {Error}
*
*/
requireArgumentType( property, type, args = this.args ) {
this.requireArgument( property, args );
if ( ( typeof args[ property ] !== type ) ) {
throw Error( `${ property } invalid type: ${ type }.` );
}
}
/**
* Function requireArgumentInstance().
*
* Validate property in args using `args.whatever instanceof instance`.
*
* @param {string} property
* @param {instanceof} instance
* @param {{}} args
*
* @throws {Error}
*
*/
requireArgumentInstance( property, instance, args = this.args ) {
this.requireArgument( property, args );
if ( ! ( args[ property ] instanceof instance ) ) {
throw Error( `${ property } invalid instance.` );
}
}
/**
* Function requireArgumentConstructor().
*
* Validate property in args using `type === args.whatever.constructor`.
*
* @param {string} property
* @param {*} type
* @param {{}} args
*
* @throws {Error}
*
*/
requireArgumentConstructor( property, type, args = this.args ) {
this.requireArgument( property, args );
if ( args[ property ].constructor !== type ) {
throw Error( `${ property } invalid constructor type.` );
}
}
}

View File

@@ -0,0 +1,31 @@
// TODO: Wrong location used as `elementorModules.ForceMethodImplementation(); should be` `elementorUtils.forceMethodImplementation()`;
export class ForceMethodImplementation extends Error {
constructor( info = {} ) {
super( `${ info.isStatic ? 'static ' : '' }${ info.fullName }() should be implemented, please provide '${ info.functionName || info.fullName }' functionality.` );
Error.captureStackTrace( this, ForceMethodImplementation );
}
}
export default () => {
const stack = Error().stack,
caller = stack.split( '\n' )[ 2 ].trim(),
callerName = caller.startsWith( 'at new' ) ?
'constructor' : caller.split( ' ' )[ 1 ],
info = {};
info.functionName = callerName;
info.fullName = callerName;
if ( info.functionName.includes( '.' ) ) {
const parts = info.functionName.split( '.' );
info.className = parts[ 0 ];
info.functionName = parts[ 1 ];
} else {
info.isStatic = true;
}
throw new ForceMethodImplementation( info );
};

View File

@@ -0,0 +1,61 @@
export default class InstanceType {
static [ Symbol.hasInstance ]( target ) {
/**
* This is function extending being called each time JS uses instanceOf, since babel use it each time it create new class
* its give's opportunity to mange capabilities of instanceOf operator.
* saving current class each time will give option later to handle instanceOf manually.
*/
let result = super[ Symbol.hasInstance ]( target );
// Act normal when validate a class, which does not have instance type.
if ( target && ! target.constructor.getInstanceType ) {
return result;
}
if ( target ) {
if ( ! target.instanceTypes ) {
target.instanceTypes = [];
}
if ( ! result ) {
if ( this.getInstanceType() === target.constructor.getInstanceType() ) {
result = true;
}
}
if ( result ) {
const name = this.getInstanceType === InstanceType.getInstanceType ? 'BaseInstanceType' : this.getInstanceType();
if ( -1 === target.instanceTypes.indexOf( name ) ) {
target.instanceTypes.push( name );
}
}
}
if ( ! result && target ) {
// Check if the given 'target', is instance of known types.
result = target.instanceTypes &&
Array.isArray( target.instanceTypes ) &&
-1 !== target.instanceTypes.indexOf( this.getInstanceType() );
}
return result;
}
constructor() {
// Since anonymous classes sometimes do not get validated by babel, do it manually.
let target = new.target;
const prototypes = [];
while ( target.__proto__ && target.__proto__.name ) {
prototypes.push( target.__proto__ );
target = target.__proto__;
}
prototypes.reverse().forEach( ( proto ) => this instanceof proto );
}
static getInstanceType() {
elementorModules.ForceMethodImplementation();
}
}

View File

@@ -0,0 +1,210 @@
const Module = function() {
const $ = jQuery,
instanceParams = arguments,
self = this,
events = {};
let settings;
const ensureClosureMethods = function() {
$.each( self, function( methodName ) {
const oldMethod = self[ methodName ];
if ( 'function' !== typeof oldMethod ) {
return;
}
self[ methodName ] = function() {
return oldMethod.apply( self, arguments );
};
} );
};
const initSettings = function() {
settings = self.getDefaultSettings();
const instanceSettings = instanceParams[ 0 ];
if ( instanceSettings ) {
$.extend( true, settings, instanceSettings );
}
};
const init = function() {
self.__construct.apply( self, instanceParams );
ensureClosureMethods();
initSettings();
self.trigger( 'init' );
};
this.getItems = function( items, itemKey ) {
if ( itemKey ) {
const keyStack = itemKey.split( '.' ),
currentKey = keyStack.splice( 0, 1 );
if ( ! keyStack.length ) {
return items[ currentKey ];
}
if ( ! items[ currentKey ] ) {
return;
}
return this.getItems( items[ currentKey ], keyStack.join( '.' ) );
}
return items;
};
this.getSettings = function( setting ) {
return this.getItems( settings, setting );
};
this.setSettings = function( settingKey, value, settingsContainer ) {
if ( ! settingsContainer ) {
settingsContainer = settings;
}
if ( 'object' === typeof settingKey ) {
$.extend( settingsContainer, settingKey );
return self;
}
const keyStack = settingKey.split( '.' ),
currentKey = keyStack.splice( 0, 1 );
if ( ! keyStack.length ) {
settingsContainer[ currentKey ] = value;
return self;
}
if ( ! settingsContainer[ currentKey ] ) {
settingsContainer[ currentKey ] = {};
}
return self.setSettings( keyStack.join( '.' ), value, settingsContainer[ currentKey ] );
};
this.getErrorMessage = function( type, functionName ) {
let message;
switch ( type ) {
case 'forceMethodImplementation':
message = `The method '${ functionName }' must to be implemented in the inheritor child.`;
break;
default:
message = 'An error occurs';
}
return message;
};
// TODO: This function should be deleted ?.
this.forceMethodImplementation = function( functionName ) {
throw new Error( this.getErrorMessage( 'forceMethodImplementation', functionName ) );
};
this.on = function( eventName, callback ) {
if ( 'object' === typeof eventName ) {
$.each( eventName, function( singleEventName ) {
self.on( singleEventName, this );
} );
return self;
}
const eventNames = eventName.split( ' ' );
eventNames.forEach( function( singleEventName ) {
if ( ! events[ singleEventName ] ) {
events[ singleEventName ] = [];
}
events[ singleEventName ].push( callback );
} );
return self;
};
this.off = function( eventName, callback ) {
if ( ! events[ eventName ] ) {
return self;
}
if ( ! callback ) {
delete events[ eventName ];
return self;
}
const callbackIndex = events[ eventName ].indexOf( callback );
if ( -1 !== callbackIndex ) {
delete events[ eventName ][ callbackIndex ];
// Reset array index (for next off on same event).
events[ eventName ] = events[ eventName ].filter( ( val ) => val );
}
return self;
};
this.trigger = function( eventName ) {
const methodName = 'on' + eventName[ 0 ].toUpperCase() + eventName.slice( 1 ),
params = Array.prototype.slice.call( arguments, 1 );
if ( self[ methodName ] ) {
self[ methodName ].apply( self, params );
}
const callbacks = events[ eventName ];
if ( ! callbacks ) {
return self;
}
$.each( callbacks, function( index, callback ) {
callback.apply( self, params );
} );
return self;
};
init();
};
Module.prototype.__construct = function() {};
Module.prototype.getDefaultSettings = function() {
return {};
};
Module.prototype.getConstructorID = function() {
return this.constructor.name;
};
Module.extend = function( properties ) {
const $ = jQuery,
parent = this;
const child = function() {
return parent.apply( this, arguments );
};
$.extend( child, parent );
child.prototype = Object.create( $.extend( {}, parent.prototype, properties ) );
child.prototype.constructor = child;
child.__super__ = parent.prototype;
return child;
};
module.exports = Module;

View File

@@ -0,0 +1,51 @@
import ViewModule from '../view-module';
module.exports = ViewModule.extend( {
getDefaultSettings: function() {
return {
container: null,
items: null,
columnsCount: 3,
verticalSpaceBetween: 30,
};
},
getDefaultElements: function() {
return {
$container: jQuery( this.getSettings( 'container' ) ),
$items: jQuery( this.getSettings( 'items' ) ),
};
},
run: function() {
var heights = [],
distanceFromTop = this.elements.$container.position().top,
settings = this.getSettings(),
columnsCount = settings.columnsCount;
distanceFromTop += parseInt( this.elements.$container.css( 'margin-top' ), 10 );
this.elements.$items.each( function( index ) {
var row = Math.floor( index / columnsCount ),
$item = jQuery( this ),
itemHeight = $item[ 0 ].getBoundingClientRect().height + settings.verticalSpaceBetween;
if ( row ) {
var itemPosition = $item.position(),
indexAtRow = index % columnsCount,
pullHeight = itemPosition.top - distanceFromTop - heights[ indexAtRow ];
pullHeight -= parseInt( $item.css( 'margin-top' ), 10 );
pullHeight *= -1;
$item.css( 'margin-top', pullHeight + 'px' );
heights[ indexAtRow ] += itemHeight;
} else {
heights.push( itemHeight );
}
} );
},
} );

View File

@@ -0,0 +1,93 @@
// Moved from elementor pro: 'assets/dev/js/frontend/utils'
export default class Scroll {
/**
* @param {object} obj
* @param {number} obj.sensitivity - Value between 0-100 - Will determine the intersection trigger points on the element
* @param {function} obj.callback - Will be triggered on each intersection point between the element and the viewport top/bottom
* @param {string} obj.offset - Offset between the element intersection points and the viewport, written like in CSS: '-50% 0 -25%'
* @param {HTMLElement} obj.root - The element that the events will be relative to, if 'null' will be relative to the viewport
*/
static scrollObserver( obj ) {
let lastScrollY = 0;
// Generating threshholds points along the animation height
// More threshholds points = more trigger points of the callback
const buildThreshholds = ( sensitivityPercentage = 0 ) => {
const threshholds = [];
if ( sensitivityPercentage > 0 && sensitivityPercentage <= 100 ) {
const increment = 100 / sensitivityPercentage;
for ( let i = 0; i <= 100; i += increment ) {
threshholds.push( i / 100 );
}
} else {
threshholds.push( 0 );
}
return threshholds;
};
const options = {
root: obj.root || null,
rootMargin: obj.offset || '0px',
threshold: buildThreshholds( obj.sensitivity ),
};
function handleIntersect( entries, observer ) {
const currentScrollY = entries[ 0 ].boundingClientRect.y,
isInViewport = entries[ 0 ].isIntersecting,
intersectionScrollDirection = ( currentScrollY < lastScrollY ) ? 'down' : 'up',
scrollPercentage = Math.abs( parseFloat( ( entries[ 0 ].intersectionRatio * 100 ).toFixed( 2 ) ) );
obj.callback( {
sensitivity: obj.sensitivity,
isInViewport,
scrollPercentage,
intersectionScrollDirection,
} );
lastScrollY = currentScrollY;
}
return new IntersectionObserver( handleIntersect, options );
}
/**
* @param {jQuery Element} $element
* @param {object} offsetObj
* @param {number} offsetObj.start - Offset start value in percentages
* @param {number} offsetObj.end - Offset end value in percentages
*/
static getElementViewportPercentage( $element, offsetObj = {} ) {
const elementOffset = $element[ 0 ].getBoundingClientRect(),
offsetStart = offsetObj.start || 0,
offsetEnd = offsetObj.end || 0,
windowStartOffset = window.innerHeight * offsetStart / 100,
windowEndOffset = window.innerHeight * offsetEnd / 100,
y1 = elementOffset.top - window.innerHeight,
y2 = ( elementOffset.top + windowStartOffset ) + $element.height(),
startPosition = ( 0 - y1 ) + windowStartOffset,
endPosition = ( y2 - y1 ) + windowEndOffset,
percent = Math.max( 0, Math.min( startPosition / endPosition, 1 ) );
return parseFloat( ( percent * 100 ).toFixed( 2 ) );
}
/**
* @param {object} offsetObj
* @param {number} offsetObj.start - Offset start value in percentages
* @param {number} offsetObj.end - Offset end value in percentages
* @param {number} limitPageHeight - Will limit the page height calculation
*/
static getPageScrollPercentage( offsetObj = {}, limitPageHeight ) {
const offsetStart = offsetObj.start || 0,
offsetEnd = offsetObj.end || 0,
initialPageHeight = limitPageHeight || ( document.documentElement.scrollHeight - document.documentElement.clientHeight ),
heightOffset = initialPageHeight * offsetStart / 100,
pageRange = initialPageHeight + heightOffset + ( initialPageHeight * offsetEnd / 100 ),
scrollPos = ( document.documentElement.scrollTop + document.body.scrollTop ) + heightOffset;
return ( scrollPos / pageRange * 100 );
}
}

View File

@@ -0,0 +1,21 @@
import Module from './module';
module.exports = Module.extend( {
elements: null,
getDefaultElements: function() {
return {};
},
bindEvents: function() {},
onInit: function() {
this.initElements();
this.bindEvents();
},
initElements: function() {
this.elements = this.getDefaultElements();
},
} );

View File

@@ -0,0 +1,18 @@
import Module from './imports/module';
import ViewModule from './imports/view-module';
import ArgsObject from './imports/args-object';
import Masonry from './imports/utils/masonry';
import Scroll from './imports/utils/scroll';
import ForceMethodImplementation from './imports/force-method-implementation';
export default window.elementorModules = {
Module,
ViewModule,
ArgsObject,
ForceMethodImplementation,
utils: {
Masonry: Masonry,
Scroll: Scroll,
},
};