Best JavaScript code snippet using storybook-root
Addons.ts
Source:Addons.ts  
1import fs from 'fs';2import originalFs from 'original-fs';3import Path from 'path';4import { app, ipcMain } from 'electron';5import { spawn, spawnSync } from 'child_process';6import compareVersions from 'compare-versions';7import winston from 'winston';8import TTVSTMain from '../TTVSTMain';9import { IAddon, AddonFlag } from './AddonsTypes';10import got from 'got';11import BroadcastMain from '../BroadcastMain';12declare var logger: winston.Logger;13declare var TTVST: TTVSTMain;14export default class Addons {15	installedAddons: Array<IAddon> = [];16	availableAddons: Array<IAddon> = [];17	static snippedIndex: number = 0;18	static batchLines: { [addonid: string] : Array<string> } = {};19	constructor() {20		this.checkForAddons(Path.join('.', 'addons'));21		this.checkForAddons(Path.join('.', 'resources'));22		this.loadAddons = this.loadAddons.bind(this);23		this.loadResporitory = this.loadResporitory.bind(this);24		this.loadError = this.loadError.bind(this);25		this.languageError = this.languageError.bind(this);26		this.onUpdate = this.onUpdate.bind(this);27		this.onUninstall = this.onUninstall.bind(this);28		this.onInstall = this.onInstall.bind(this);29		this.onRestart = this.onRestart.bind(this);30		ipcMain.on('Addons.loadInstalled', this.loadAddons);31		ipcMain.on('Addons.loadRepository', this.loadResporitory);32		ipcMain.on('Addons.loadError', this.loadError);33		ipcMain.on('Addons.languageError', this.languageError);34		ipcMain.on('Addons.update', this.onUpdate);35		ipcMain.on('Addons.uninstall', this.onUninstall);36		ipcMain.on('Addons.install', this.onInstall);37		ipcMain.on('Addons.restart', this.onRestart);38		let batchPath = Path.join(app.getPath('temp'), 'addons.bat');39		fs.access(batchPath, fs.constants.W_OK, (err) => {40			if(err) return;41			fs.unlink(batchPath, (err) => {42				if(err) {43					logger.error('[Addons]', err);44				}45			});46		})47	}48	checkForAddons(directory: string): Promise<void> {49		logger.info(`[Addons] Checking ${directory} for addons`);50		return new Promise((resolve) => {51			fs.readdir(directory, async (err: NodeJS.ErrnoException, files: string[]) => {52				if(err === null) {53					for(let i = 0; i < files.length; i++) {54						let p = Path.join(directory, files[i]);55						await new Promise((re) => {56							fs.stat(p, async (e: NodeJS.ErrnoException, stats: fs.Stats) => {57								if(e === null) {58									if(stats.isDirectory()) {59										await this.checkAddon(p);60									}61								}62								re(null);63							});64						});65					}66				} else {67					logger.info(`[Addons] Directory ${directory} could not be read`);68					logger.verbose(err);69				}70				resolve();71			})72		});73	}74	checkAddon(path: string): Promise<void> {75		const self = this;76		return new Promise((resolve) => {77			let packagePath = Path.join(path, 'package.json');78			fs.readFile(packagePath, { encoding: 'utf8' }, (err: NodeJS.ErrnoException, data: string) => {79				if(err === null) {80					try {81						let packageJson = JSON.parse(data);82						if(83							typeof(packageJson.addonid) === 'string' &&84							typeof(packageJson.name) === 'string' &&85							typeof(packageJson.version) === 'string' &&86							typeof(packageJson.description) === 'string' &&87							typeof(packageJson.author) === 'object' &&88							typeof(packageJson.toolversion) === 'string' &&89							(typeof(packageJson.main) === 'string' || typeof(packageJson.renderer) === 'string')90						) {91							if(compareVersions.compare(packageJson.toolversion, app.getVersion(), '>=') && !this.addonInstalled(packageJson.addonid)) {92								self.installedAddons.push(Object.assign(packageJson, { path, flags: ['compatible'], loaderror: '', updateAvaiable: '' }));93							} else {94								self.installedAddons.push(Object.assign(packageJson, { path, flags: [], loaderror: 'Addon is not compatible with the current version of TTVStreamerTool', updateAvaiable: '' }));95							}96						} else {97							logger.debug(`[Addons] Addon package.json at ${packagePath} missing fields`);98						}99					} catch(e) {100						logger.debug(`[Addons] Addon package.json at ${packagePath} could not be loaded`);101						logger.debug(e);102					}103				} else {104					logger.debug(`[Addons] Could not read ${packagePath}`);105					logger.debug(err);106				}107				resolve();108			});109		});110	}111	addonInstalled(addonid: string): boolean {112		for(let i = 0; i < this.installedAddons.length; i++) {113			if(this.installedAddons[i].addonid === addonid) {114				return true;115			}116		}117		return false;118	}119	async loadAddons() {120		for(let i = 0; i < this.installedAddons.length; i++) {121			let addon = this.installedAddons[i];122			if(!this.hasFlag(addon, 'compatible')) {123				continue;124			}125			if(this.hasFlag(addon, 'loaded')) {126				this.checkForRendererStuff(addon);127				continue;128			}129			if(typeof(addon.path) === 'string') {130				if(typeof(addon.main) === 'string') {131					try {132						let modpath = Path.relative(__dirname, Path.join(process.cwd(), addon.path, addon.main.substring(0, addon.main.lastIndexOf('.')))).replace(new RegExp('\\'+Path.sep, 'g'), '/');133						logger.debug(`[Addons] Loading addon main module for ${addon.name} at ${modpath}`);134						require(modpath);135						this.setFlag(this.installedAddons[i].addonid, 'loaded');136						this.checkForRendererStuff(addon);137						this.checkForBroadcastStuff(addon);138					} catch(e) {139						logger.error(`[Addons] Addon (main) at ${addon.path} could not be loaded`);140						logger.error(e);141						this.removeFlag(this.installedAddons[i].addonid, 'compatible');142						this.installedAddons[i].loaderror = 'Addon loader on main thread failed';143					}144				} else if(typeof(addon.renderer) === 'string') {145					TTVST.mainWindow.ipcSend('Addons.load', addon.path, addon.renderer.substring(0, addon.renderer.lastIndexOf('.')));146				}147			}148		}149		let newAvailable: Array<IAddon> = [];150		for(let i = 0; i < this.availableAddons.length; i++) {151			if(!this.addonInstalled(this.availableAddons[i].addonid)) {152				newAvailable.push(this.availableAddons[i]);153			}154		}155		this.availableAddons = newAvailable;156		this.sendAddonUpdate();157	}158	checkForRendererStuff(addon: IAddon) {159		fs.access(Path.join(process.cwd(), addon.path, 'language.json'), fs.constants.R_OK, (err) => {160			if(!err && TTVST.mainWindow.window !== null && TTVST.mainWindow.window.isVisible()) {161				logger.debug(`[Addons] Remind renderer to load language file for ${addon.name}`);162				TTVST.mainWindow.ipcSend('Addons.language', addon.path);163			}164			if(typeof(addon.renderer) === 'string' && TTVST.mainWindow.window !== null && TTVST.mainWindow.window.isVisible()) {165				logger.debug(`[Addons] Remind renderer load renderer module for ${addon.name}`);166				TTVST.mainWindow.ipcSend('Addons.load', addon.path, addon.renderer.substring(0, addon.renderer.lastIndexOf('.')));167			}168		});169	}170	checkForBroadcastStuff(addon: IAddon) {171		fs.readFile(Path.join(process.cwd(), addon.path, 'broadcast.json'), { encoding: 'utf8' }, (err: NodeJS.ErrnoException, data: string) => {172			if(err) {173				return;174			}175			try {176				logger.debug(`[Addons] Adding broadcast information for ${addon.name}`);177				let broadcastData = JSON.parse(data);178				if(Array.isArray(broadcastData.triggers)) {179					for(let i = 0; i < broadcastData.triggers.length; i++) {180						BroadcastMain.registerTrigger(broadcastData.triggers[i]);181					}182				}183				if(Array.isArray(broadcastData.actions)) {184					for(let i = 0; i < broadcastData.actions.length; i++) {185						BroadcastMain.registerAction(broadcastData.actions[i]);186					}187				}188			} catch(e) {189				logger.error(e);190			}191		});192	}193	loadError(event: Electron.IpcMainEvent, addonpath: string, error: { code: string, message: string, stack: string }) {194		for(let i = 0; i < this.installedAddons.length; i++) {195			if(this.installedAddons[i].path === addonpath) {196				this.removeFlag(this.installedAddons[i].addonid, 'loaded');197				this.installedAddons[i].loaderror = 'Addon loader on renderer thread failed';198				this.setFlag(this.installedAddons[i].addonid, 'compatible');199				logger.error(`[Addons] Addon (renderer) at ${addonpath} could not be loaded`);200				logger.error(error);201				this.sendAddonUpdate();202				break;203			}204		}205	}206	languageError(event: Electron.IpcMainEvent, addonpath: string, error: { code: string, message: string, stack: string }) {207		logger.error(`[Addons] Addon language pack ${addonpath} could not be loaded`);208		logger.error(error);209	}210	async loadResporitory(event: Electron.IpcMainEvent, url: string) {211		for(let i = 0; i < TTVST.startpage.currentStatus.length; i++) {212			if(TTVST.startpage.currentStatus[i].key == 'app.ttvst.update') {213				if(TTVST.startpage.currentStatus[i].status == 'good') {214					return;215				}216				break;217			}218		}219		if(!url.startsWith('https://')) return;220		try {221			logger.info(`[Addons] Load addons at repository ${url}`);222			let response = await got(url, { responseType: 'json', timeout: 10000 });223			if(response.statusCode == 200) {224				let body = response.body;225				if(Array.isArray(body)) {226					for(let i = 0; i < body.length; i++) {227						let pack = body[i];228						if(229							typeof(pack.addonid) === 'string' &&230							typeof(pack.name) === 'string' &&231							typeof(pack.version) === 'string' &&232							typeof(pack.description) === 'string' &&233							typeof(pack.author) === 'object' &&234							typeof(pack.toolversion) === 'string' &&235							typeof(pack.download) === 'string'236						) {237							let compatible: boolean = compareVersions(pack.toolversion, app.getVersion()) >= 0;238							Object.assign(pack, { flags: compatible ? ['compatible'] : [] });239							this.overwriteAddon(pack);240						} else {241							logger.debug(`[Addons] Addon description missing fields at repository ${url} (${i})`);242						}243					}244				} else {245					logger.error(`[Addons] Repository at ${url} responded with an invalid format`);246				}247			} else {248				logger.error(`[Addons] Repository at ${url} responded with a status code ${response.statusCode}`);249			}250		} catch(e) {251			logger.error(`[Addons] Something went wrong while loading repository at ${url}`);252			logger.error(e);253		}254		255		this.sendAddonUpdate();256	}257	overwriteAddon(addon: IAddon) {258		for(let i = 0; i < this.installedAddons.length; i++) {259			if(this.installedAddons[i].addonid === addon.addonid) {260				if(this.installedAddons[i].version !== addon.version && this.hasFlag(addon, 'compatible')) {261					this.installedAddons[i].updateAvaiable = addon.version;262					this.installedAddons[i].download = addon.download;263					this.setFlag(this.installedAddons[i].addonid, 'updateavailable');264				}265				return;266			}267		}268		for(let i = 0; i < this.availableAddons.length; i++) {269			if(this.availableAddons[i].addonid === addon.addonid) {270				this.availableAddons[i] = addon;271				return;272			}273		}274		this.availableAddons.push(addon);275	}276	sendAddonUpdate() {277		TTVST.mainWindow.ipcSend('Addons.update', this.installedAddons.concat(this.availableAddons));278	}279	static getRetryDeleteSnippet(file: string) {280		Addons.snippedIndex++281		let index = Addons.snippedIndex.toString()282		return ':LOOP' + index + '\r\ndel "' + file + '"\r\nIF EXIST "' + file + '" (\r\ntimeout /T 1 /Nobreak >nul\r\nGOTO LOOP' + index + '\r\n)'283	}284	async onUpdate(event: Electron.IpcMainEvent, addons: Array<IAddon>) {285		for(let i = 0; i < addons.length; i++) {286			let addon = addons[i];287			if(typeof(addon.download) !== 'string' || !addon.download.startsWith('https://')) {288				TTVST.mainWindow.ipcSend('Addons.updateFailed', addon);289				continue;290			}291			try {292				this.setFlag(addon.addonid, 'updating');293				let resp = await got(addon.download, { responseType: 'buffer', timeout: 20000 })294				if(resp.statusCode === 200) {295					let sanitizedAddonName = addon.addonid.replace(/[^a-z0-9\.\-]/ig, '');296					let addonDownload = Path.join(app.getPath('temp'), sanitizedAddonName + '.asar');297					await new Promise((res, rej) => {298						originalFs.writeFile(addonDownload, resp.body, (err) => {299							if(err === null) {300								res(null);301							} else {302								rej(err);303							}304						});305					});306					Addons.batchLines[addon.addonid] = [];307					Addons.batchLines[addon.addonid].push(Addons.getRetryDeleteSnippet(addon.path));308					Addons.batchLines[addon.addonid].push(`move "${addonDownload}" resources\\${sanitizedAddonName}.asar`);309					310					this.setFlag(addon.addonid, 'updateready');311				} else {312					this.setFlag(addon.addonid, 'updatefailed');313					logger.error(`[Addons] Addon download failed. Server responded with status code ${resp.statusCode}`);314				}315			} catch(e) {316				this.setFlag(addon.addonid, 'updatefailed');317				logger.error(`[Addons] Addon update failed`);318				logger.error(e);319			}320		}321	}322	async onUninstall(event: Electron.IpcMainEvent, addons: Array<IAddon>) {323		for(let i = 0; i < addons.length; i++) {324			let addon = addons[i];325			if(typeof(addon.path) !== 'string' || addon.path.length <= 0) continue;326			327			await new Promise((res) => {328				originalFs.stat(addon.path, (err: NodeJS.ErrnoException, stats: fs.Stats) => {329					if(err === null) {330						if(stats.isFile()) {331							Addons.batchLines[addon.addonid] = [Addons.getRetryDeleteSnippet(addon.path)];332							this.setFlag(addon.addonid, 'uninstallready');333						} else {334							this.setFlag(addon.addonid, 'uninstallfailed');335						}336					} else {337						this.setFlag(addon.addonid, 'uninstallfailed');338						logger.error(`[Addons] Addon uninstall failed`);339						logger.error(err);340					}341					res(null);342				});343			})344		}345	}346	isSomethingInstalling() {347		for(let i = 0; i < this.availableAddons.length; i++) {348			if(this.hasFlag(this.availableAddons[i], 'installing')) {349				return true;350			}351		}352		return false;353	}354	async onInstall(event: Electron.IpcMainEvent, addons: Array<IAddon>) {355		let installingRows: string[] = [];356		let addonFileNames: Array<string[]> = [];357		if(this.isSomethingInstalling()) {358			return;359		}360		let tempPath = app.getPath('temp');361		for(let i = 0; i < addons.length; i++) {362			let addon = addons[i];363			if(typeof(addon.download) !== 'string' || !addon.download.startsWith('https://')) {364				this.setFlag(addon.addonid, 'installfailed');365				continue;366			}367			try {368				this.setFlag(addon.addonid, 'installing');369				let resp = await got(addon.download, { responseType: 'buffer', timeout: 20000 })370				if(resp.statusCode === 200) {371					let sanitizedAddonName = addon.addonid.replace(/[^a-z0-9\.\-]/ig, '');372					await new Promise((res, rej) => {373						let addonDownload = Path.join(tempPath, sanitizedAddonName + '.asar');374						originalFs.writeFile(addonDownload, resp.body, (err) => {375							if(err === null) {376								installingRows.push('move "' + addonDownload + '" "resources\\' + sanitizedAddonName + '.asar"');377								addonFileNames.push([addon.addonid, sanitizedAddonName]);378								res(null);379							} else {380								rej(err);381							}382						});383					});384				} else {385					this.setFlag(addon.addonid, 'installfailed');386					logger.error(`[Addons] Addon download failed. Server responded with status code ${resp.statusCode}`);387				}388			} catch(e) {389				this.setFlag(addon.addonid, 'installfailed');390				logger.error(`[Addons] Addon install failed`);391				logger.error(e);392			}393		}394		let batch = '@echo off\r\n' + installingRows.join('\r\n');395		let batchPath = Path.join(tempPath, 'addons.bat');396		try {397			fs.writeFileSync(batchPath, batch);398			399			spawnSync('resources\\elevate -w -c "'+batchPath+'"', { cwd: process.cwd(), env: process.env, shell: true, windowsHide: true });400			for(let i = 0; i < addonFileNames.length; i++) {401				try {402					originalFs.accessSync(`resources\\${addonFileNames[i][1]}.asar`, fs.constants.R_OK);403					await this.checkAddon(`resources\\${addonFileNames[i][1]}.asar`);404				} catch(e) {405					this.setFlag(addonFileNames[i][0], 'installfailed');406					logger.error(`[Addons] Addon install failed`);407					logger.error(e);408				}409			}410		} catch(e) {}411		this.loadAddons();412	}413	onRestart() {414		let execArgv = process.execArgv.map(a => a.replace(/"/g, '""'));415		let batchLines: Array<string> = [];416		for(let addonid of Object.keys(Addons.batchLines)) {417			batchLines = batchLines.concat(Addons.batchLines[addonid]);418		}419		let batchPath = Path.join(app.getPath('temp'), 'addons.bat');420		let batch = '@echo off\r\n' + batchLines.join('\r\n') + '\r\nstart "" "' + process.execPath + '"' + (execArgv.length > 0 ? ' "' + execArgv.join('" "') + '"' : '') + '\r\nexit'421		fs.writeFile(batchPath, batch, (err: NodeJS.ErrnoException) => {422			if(err === null) {423				spawn('resources\\elevate -c "'+batchPath+'"', { cwd: process.cwd(), env: process.env, shell: true, detached: true, windowsHide: false });424				app.quit();425			} else {426				TTVST.mainWindow.ipcSend('Addons.batchFailed');427				logger.error(`[Addons] Addon batch creation failed`);428				logger.error(err);429			}430		});431	}432	setFlag(addonid: string, flag: AddonFlag, skipupdate?: boolean) {433		switch(flag) {434			case 'installing': this.removeFlag(addonid, 'installfailed', true); break;435			case 'installfailed': this.removeFlag(addonid, 'installing', true); break;436			437			case 'updating': this.removeFlag(addonid, ['updateready','updatefailed','uninstallready','uninstallfailed'], true); break;438			case 'updateready': this.removeFlag(addonid, ['updating','updatefailed','uninstallready','uninstallfailed'], true); break;439			case 'updatefailed': this.removeFlag(addonid, ['updateready','updating','uninstallready','uninstallfailed'], true); break;440			441			case 'uninstallready': this.removeFlag(addonid, ['uninstallfailed','updateready','updatefailed'], true); break;442			case 'uninstallfailed': this.removeFlag(addonid, ['uninstallready','updateready','updatefailed'], true); break;443			case 'loaded': this.removeFlag(addonid, ['installing','installfailed','updating','updateready','updatefailed','uninstallready','uninstallfailed'], true); break;444		}445		for(let i = 0; i < this.installedAddons.length; i++) {446			if(this.installedAddons[i].addonid === addonid) {447				if(typeof(this.installedAddons[i].flags) === 'undefined') {448					this.installedAddons[i].flags = [];449				}450				if(!this.hasFlag(this.installedAddons[i], flag)) {451					this.installedAddons[i].flags.push(flag);452				}453				break;454			}455		}456		for(let i = 0; i < this.availableAddons.length; i++) {457			if(this.availableAddons[i].addonid === addonid) {458				if(typeof(this.availableAddons[i].flags) === 'undefined') {459					this.availableAddons[i].flags = [];460				}461				if(!this.hasFlag(this.availableAddons[i], flag)) {462					this.availableAddons[i].flags.push(flag);463				}464				break;465			}466		}467		if(typeof(skipupdate) !== 'boolean' || !skipupdate) {468			this.sendAddonUpdate();469		}470	}471	removeFlag(addonid: string, flags: AddonFlag | Array<AddonFlag>, skipupdate?: boolean) {472		if(!Array.isArray(flags)) {473			flags = [flags];474		}475		for(let i = 0; i < this.installedAddons.length; i++) {476			if(this.installedAddons[i].addonid === addonid) {477				if(typeof(this.installedAddons[i].flags) === 'undefined') {478					break;479				}480				this.installedAddons[i].flags = this.installedAddons[i].flags.filter(f => flags.indexOf(f) < 0);481				break;482			}483		}484		for(let i = 0; i < this.availableAddons.length; i++) {485			if(this.availableAddons[i].addonid === addonid) {486				if(typeof(this.availableAddons[i].flags) === 'undefined') {487					break;488				}489				this.availableAddons[i].flags = this.availableAddons[i].flags.filter(f => flags.indexOf(f) < 0);490				break;491			}492		}493		if(typeof(skipupdate) !== 'boolean' || !skipupdate) {494			this.sendAddonUpdate();495		}496	}497	hasFlag(addon: IAddon, flag: AddonFlag) {498		if(typeof(addon.flags) === 'undefined') return false;499		if(addon.flags.indexOf(flag) >= 0) {500			return true;501		}502		return false;503	}...elementor.js
Source:elementor.js  
1import { setButtonAtts } from '../modules/getButtonURL';2import { lazyImages } from '../modules/lazyImages';3import loadItems from '../modules/loadItems';4/**5 * Set up the instance on Elementor6 *7 * @param {object} alm8 * @since 5.3.09 */10export function elementorInit(alm) {11	if (!alm.addons.elementor || !alm.addons.elementor_type || !alm.addons.elementor_type === 'posts') {12		return false;13	}14	let target = alm.addons.elementor_element;15	if (target) {16		// Set button data attributes17		alm.button.dataset.page = alm.addons.elementor_paged;18		// Set button URL19		let nextPage = alm.addons.elementor_next_page_url;20		alm.button.dataset.url = nextPage ? nextPage : '';21		// Set a11y attributes22		target.setAttribute('aria-live', 'polite');23		target.setAttribute('aria-atomic', 'true');24		alm.listing.removeAttribute('aria-live');25		alm.listing.removeAttribute('aria-atomic');26		// Set data atts on 1st grid item27		let item = target.querySelector(`.${alm.addons.elementor_item_class}`); // Get first `.product` item28		if (item) {29			item.classList.add('alm-elementor');30			item.dataset.url = window.location;31			item.dataset.page = alm.addons.elementor_paged;32			item.dataset.pageTitle = document.title;33		}34		if (alm.addons.elementor_paged > 1) {35			// maybe soon36			//almElementorResultsTextInit(alm);37		}38		// Masonry Window Resize. Delay for masonry to be added via Elementor.39		if (alm.addons.elementor_masonry) {40			let resizeTimeout;41			setTimeout(function () {42				window.addEventListener('resize', function () {43					clearTimeout(resizeTimeout);44					resizeTimeout = setTimeout(function () {45						positionMasonryItems(alm, `.${alm.addons.elementor_container_class}`, `.${alm.addons.elementor_item_class}`);46					}, 100);47				});48			}, 250);49		}50	}51}52/**53 * Core ALM Elementor loader.54 *55 * @param {HTMLElement} content56 * @param {object} alm57 * @param {string} pageTitle58 * @since 5.3.059 */60export function elementor(content, alm, pageTitle = document.title) {61	if (!content || !alm) {62		return false;63	}64	return new Promise((resolve) => {65		let container = alm.addons.elementor_element.querySelector(`.${alm.addons.elementor_container_class}`); // Get post container66		let items = content.querySelectorAll(`.${alm.addons.elementor_item_class}`); // Get all items in container67		let url = alm.addons.elementor_current_url; // Current Page URL68		if (container && items && url) {69			// Convert NodeList to Array70			items = Array.prototype.slice.call(items);71			// Trigger almElementorLoaded callback.72			if (typeof almElementorLoaded === 'function') {73				window.almElementorLoaded(items);74			}75			// Load the items76			(async function () {77				await loadItems(container, items, alm, pageTitle, url, 'alm-elementor');78				if (alm.addons.elementor_masonry) {79					setTimeout(function () {80						positionMasonryItems(alm, `.${alm.addons.elementor_container_class}`, `.${alm.addons.elementor_item_class}`);81					}, 125);82				}83				resolve(true);84			})().catch((e) => {85				console.log(e, 'There was an error with Elementor');86			});87		} else {88			resolve(false);89		}90	});91}92/**93 * Handle Elementor loaded functionality and dispatch actions.94 *95 * @param {object} alm96 * @since 5.5.097 */98export function elementorLoaded(alm) {99	let nextPageNum = alm.page + 1;100	let nextPage = alm.addons.elementor_next_page_url; // Get URL.101	// Set button data attributes.102	setButtonAtts(alm.button, nextPageNum, nextPage);103	// Lazy load images if necessary.104	lazyImages(alm);105	// Trigger almComplete.106	if (typeof almComplete === 'function' && alm.transition !== 'masonry') {107		window.almComplete(alm);108	}109	// End transitions.110	alm.AjaxLoadMore.transitionEnd();111	// ALM Done112	if (!nextPage) {113		alm.AjaxLoadMore.triggerDone();114	}115}116/**117 * Get the content, title and results text from the Ajax response.118 *119 * @param {*} response120 * @param {object} alm121 * @since 5.4.0122 */123export function elementorGetContent(response, alm) {124	let data = {125		html: '',126		meta: {127			postcount: 1,128			totalposts: alm.localize.total_posts,129			debug: false,130		},131	};132	if (response.status === 200 && response.data) {133		let div = document.createElement('div');134		div.innerHTML = response.data;135		// Get Page Title136		let title = div.querySelector('title').innerHTML;137		data.pageTitle = title;138		// Get Elementor Items HTML139		let items = div.querySelector(`${alm.addons.elementor_target} .${alm.addons.elementor_container_class}`);140		data.html = items ? items.innerHTML : '';141		// Set Page URL Params142		alm.addons.elementor_current_url = alm.addons.elementor_next_page_url; // Set current to previous page URL143		alm.addons.elementor_next_page_url = elementorGetNextPage(div, alm.addons.elementor_pagination_class);144		// Results Text145		//almElementorResultsText(div, alm);146	}147	return data;148}149/**150 * Create Elementor Params for ALM.151 *152 * @param Object alm153 * @return alm154 */155export function elementorCreateParams(alm) {156	// Get Settings157	alm.addons.elementor_type = 'posts';158	alm.addons.elementor_settings = JSON.parse(alm.listing.dataset.elementorSettings);159	// Parse Container Settings160	alm.addons.elementor_target = alm.addons.elementor_settings.target;161	alm.addons.elementor_element = alm.addons.elementor_settings.target162		? document.querySelector(`.elementor-widget-wrap ${alm.addons.elementor_settings.target}`)163		: '';164	alm.addons.elementor_widget = elementorGetWidgetType(alm.addons.elementor_element);165	// Masonry166	alm = setElementorClasses(alm, alm.addons.elementor_widget);167	// Pagination Element168	alm.addons.elementor_pagination =169		alm.addons.elementor_element.querySelector(alm.addons.elementor_pagination_class) ||170		alm.addons.elementor_element.querySelector(`.${alm.addons.elementor_settings.pagination_class}`);171	alm.addons.elementor_pagination = alm.addons.elementor_pagination ? alm.addons.elementor_pagination : false;172	alm.addons.elementor_controls = alm.addons.elementor_settings.controls;173	alm.addons.elementor_controls = alm.addons.elementor_controls === 'true' ? true : false;174	alm.addons.elementor_scrolltop = parseInt(alm.addons.elementor_settings.scrolltop);175	// Set Page & URL params176	alm.addons.elementor_current_url = window.location.href;177	alm.addons.elementor_next_page_url = elementorGetNextUrl(alm.addons.elementor_pagination);178	alm.addons.elementor_paged = alm.addons.elementor_settings.paged ? parseInt(alm.addons.elementor_settings.paged) : 1;179	alm.page = parseInt(alm.page) + alm.addons.elementor_paged;180	// Masonry181	alm = parseMasonryConfig(alm);182	if (!alm.addons.elementor_element) {183		console.warn("Ajax Load More: Unable to locate Elementor Widget. Are you sure you've set up your target parameter correctly?");184	}185	if (!alm.addons.elementor_pagination) {186		console.warn(187			'Ajax Load More: Unable to locate Elementor pagination. There are either no results or p Ajax Load More is unable to locate the pagination widget?'188		);189	}190	return alm;191}192/**193 * Set the required classnames for parsing data and injecting content into the Elementor listing194 *195 * @param {*} alm196 * @param {*} type197 */198function setElementorClasses(alm, type = 'posts') {199	// Container Class200	alm.addons.elementor_container_class =201		type === 'woocommerce' ? alm.addons.elementor_settings.woo_container_class : alm.addons.elementor_settings.posts_container_class;202	// Item Class203	alm.addons.elementor_item_class = type === 'woocommerce' ? alm.addons.elementor_settings.woo_item_class : alm.addons.elementor_settings.posts_item_class;204	// Pagination Class205	alm.addons.elementor_pagination_class =206		type === 'woocommerce' ? `.${alm.addons.elementor_settings.woo_pagination_class}` : `.${alm.addons.elementor_settings.posts_pagination_class}`;207	return alm;208}209/**210 * Parse Masonry Settings from Elementor Data atts211 *212 * @param {*} alm213 */214function parseMasonryConfig(alm) {215	if (!alm.addons.elementor_element) {216		return alm; // Exit if not found.217	}218	const target = alm.addons.elementor_element;219	const settings = target.dataset.settings ? JSON.parse(target.dataset.settings) : '';220	if (!settings) {221		return alm; // Exit if not found.222	}223	alm.addons.elementor_masonry = settings.hasOwnProperty('cards_masonry') || settings.hasOwnProperty('classic_masonry');224	if (alm.addons.elementor_masonry) {225		alm.addons.elementor_masonry_columns = parseInt(settings.cards_columns) || parseInt(settings.classic_columns);226		alm.addons.elementor_masonry_columns_mobile = parseInt(settings.cards_columns_mobile) || parseInt(settings.classic_columns_mobile);227		alm.addons.elementor_masonry_columns_tablet = parseInt(settings.cards_columns_tablet) || parseInt(settings.classic_columns_tablet);228		alm.addons.elementor_masonry_gap = parseInt(settings.cards_row_gap.size);229	}230	return alm;231}232/**233 * Position Elementor Masonry Items234 *235 * @param {*} alm236 * @param {*} container_class237 * @param {*} item_class238 */239function positionMasonryItems(alm, container_class, item_class) {240	let heights = [];241	// Get Elementor Settings242	const columnsCount = alm.addons.elementor_masonry_columns;243	const columnsCountTablet = alm.addons.elementor_masonry_columns_tablet;244	const columnsCountMobile = alm.addons.elementor_masonry_columns_mobile;245	const verticalSpaceBetween = alm.addons.elementor_masonry_gap;246	let columns = columnsCount;247	// Get Elementor Breakpoints248	const breakpoints = window.elementorFrontendConfig && window.elementorFrontendConfig.breakpoints ? window.elementorFrontendConfig.breakpoints : 0;249	const windowW = window.innerWidth;250	// Set Columns251	if (windowW > breakpoints.lg) {252		columns = columnsCount;253	} else if (windowW > breakpoints.md) {254		columns = columnsCountTablet;255	} else {256		columns = columnsCountMobile;257	}258	// Get Containers259	const container = document.querySelector(container_class);260	if (!container) {261		return false;262	}263	const items = container.querySelectorAll(item_class);264	if (!items) {265		return false;266	}267	// Loop items268	items.forEach((item, index) => {269		let row = Math.floor(index / columns);270		let itemHeight = item.getBoundingClientRect().height + verticalSpaceBetween;271		if (row) {272			let itemPosition = jQuery(item).position();273			let indexAtRow = index % columns;274			let pullHeight = Math.round(itemPosition.top) - heights[indexAtRow];275			pullHeight *= -1;276			item.style.marginTop = `${Math.round(pullHeight)}px`;277			heights[indexAtRow] += itemHeight;278		} else {279			heights.push(itemHeight);280		}281	});282}283/**284 * Determine the type of elementor widget (woocommerce || posts)285 *286 * @param {*} target287 * @param {*} classname288 */289function elementorGetWidgetType(target) {290	if (!target) {291		return false;292	}293	// If container contains the woocommerce elementor class294	const type = target.classList.contains('elementor-wc-products') ? 'woocommerce' : 'posts';295	return type;296}297/**298 * Get the upcoming URL from the a.next link from the HTML299 *300 * @param {HTMLElement} element301 * @param {String} classname302 * @return {string} href303 */304function elementorGetNextPage(element, classname) {305	const pagination = element.querySelector(classname);306	const href = pagination ? elementorGetNextUrl(pagination) : '';307	return href;308}309/**310 * Get the URL of the next page to load from the a.next href311 *312 * @param {HTMLElement} element313 * @return {String} url314 */315function elementorGetNextUrl(element) {316	if (!element) {317		return '';318	}319	return element.querySelector('a.next') ? element.querySelector('a.next').href : '';...useSelectableInputs.js
Source:useSelectableInputs.js  
1// Copyright (C) 2017-2022 Smart code 2033585072const React = require('react');3const mapSelectableInputs = (installedAddons, remoteAddons) => {4    const catalogSelect = {5        title: 'Select catalog',6        options: remoteAddons.selectable.catalogs7            .concat(installedAddons.selectable.catalogs)8            .map(({ name, deepLinks }) => ({9                value: deepLinks.addons,10                label: name,11                title: name12            })),13        selected: remoteAddons.selectable.catalogs14            .concat(installedAddons.selectable.catalogs)15            .filter(({ selected }) => selected)16            .map(({ deepLinks }) => deepLinks.addons),17        renderLabelText: remoteAddons.selected !== null ?18            () => {19                const selectableCatalog = remoteAddons.selectable.catalogs20                    .find(({ id }) => id === remoteAddons.selected.request.path.id);21                return selectableCatalog ? selectableCatalog.name : remoteAddons.selected.request.path.id;22            }23            :24            null,25        onSelect: (event) => {26            window.location = event.value;27        }28    };29    const typeSelect = {30        title: 'Select type',31        options: installedAddons.selected !== null ?32            installedAddons.selectable.types.map(({ type, deepLinks }) => ({33                value: deepLinks.addons,34                label: type !== null ? type : 'All'35            }))36            :37            remoteAddons.selectable.types.map(({ type, deepLinks }) => ({38                value: deepLinks.addons,39                label: type40            })),41        selected: installedAddons.selected !== null ?42            installedAddons.selectable.types43                .filter(({ selected }) => selected)44                .map(({ deepLinks }) => deepLinks.addons)45            :46            remoteAddons.selectable.types47                .filter(({ selected }) => selected)48                .map(({ deepLinks }) => deepLinks.addons),49        renderLabelText: () => {50            return installedAddons.selected !== null ?51                installedAddons.selected.request.type === null ?52                    'All'53                    :54                    installedAddons.selected.request.type55                :56                remoteAddons.selected !== null ?57                    remoteAddons.selected.request.path.type58                    :59                    typeSelect.title;60        },61        onSelect: (event) => {62            window.location = event.value;63        }64    };65    return [catalogSelect, typeSelect];66};67const useSelectableInputs = (installedAddons, remoteAddons) => {68    const selectableInputs = React.useMemo(() => {69        return mapSelectableInputs(installedAddons, remoteAddons);70    }, [installedAddons, remoteAddons]);71    return selectableInputs;72};...Using AI Code Generation
1import React from 'react';2import { Button } from '@storybook/react/demo';3import { withKnobs, text, boolean, number } from "@storybook/addon-knobs";4export default {5};6export const Text = () => <Button>{text("Label", "Hello Storybook")}</Button>;7export const Emoji = () => (8);9export const WithSomeEmojiAndAction = () => (10  <Button onClick={action('clicked')}>11);12export const WithSomeEmojiAndAction = () => (13  <Button onClick={action('clicked')}>14);15export const WithSomeEmojiAndAction = () => (16  <Button onClick={action('clicked')}>17);18export const WithSomeEmojiAndAction = () => (19  <Button onClick={action('clicked')}>20);21export const WithSomeEmojiAndAction = () => (22  <Button onClick={action('clicked')}>23);24export const WithSomeEmojiAndAction = () => (25  <Button onClick={action('clicked')}>26);27export const WithSomeEmojiAndAction = () => (28  <Button onClick={action('clicked')}>29);30export const WithSomeEmojiAndAction = () => (31  <Button onClick={action('Using AI Code Generation
1import { configure } from '@storybook/react'2const req = require.context('../src', true, /\.stories\.js$/)3function loadStories() {4  req.keys().forEach(filename => req(filename))5}6configure(loadStories, module)7import { configure } from '@storybook/react'8const req = require.context('../', true, /\.stories\.js$/)9function loadStories() {10  req.keys().forEach(filename => req(filename))11}12configure(loadStories, module)Using AI Code Generation
1import { addons } from '@storybook/addons';2import { create } from '@storybook/theming/create';3import { themes } from '@storybook/theming';4addons.setConfig({5  theme: create({6  }),7});8addons.setConfig({9});10addons.setConfig({11});12addons.setConfig({13});Using AI Code Generation
1module.exports = require('storybook-root-config').addons;2module.exports = {3    {4      options: {5      },6    },7};8import { addParameters } from '@storybook/react';9import { DocsPage, DocsContainer } from '@storybook/addon-docs/blocks';10addParameters({11  docs: {12  },13});14module.exports = ({ config }) => {15  config.module.rules.push({16    test: /\.(js|jsx)$/,17    include: path.resolve(__dirname, 'src'),18      {19        loader: require.resolve('babel-loader'),20        options: {21        },22      },23  });24  config.resolve.extensions.push('.js', '.jsx');25  return config;26};27import { addons } from '@storybook/addons';28import { themes } from '@storybook/theming';29addons.setConfig({30});31  window.STORYBOOK_REACT_CLASSES = {};32  window.STORYBOOK_REACT_CLASSES = {};33import { addParameters } from '@storybook/react';34import { DocsPage, DocsContainer } from '@storybook/addon-docs/blocks';35addParameters({36  docs: {37  },38});39import { addDecorator } from '@storybook/react';40import { withInfo } from '@storybook/addon-info';41addDecorator(withInfo);42import { addDecorator } from '@storybook/react';43import { withProvider } from 'storybook-addon-redux-decorator';44addDecorator(withProvider);45import { addDecorator } from '@storybook/react';46import { withRedux } from 'storybook-addon-redux-decorator';47addDecorator(withRedux);48import { addDecorator } from '@Using AI Code Generation
1import addons from '@storybook/addons';2import { withInfo } from '@storybook/addon-info';3import { withKnobs } from '@storybook/addon-knobs';4import { configure } from '@storybook/react';5addons.setConfig({6  theme: {},7  sidebar: {8  },9});10function loadStories() {11  require('../src/stories');12}13configure(loadStories, module);14addons.register('storybookjs/knobs', () => {15  addons.addPanel('storybookjs/knobs/panel', {16    render: () => <div>Knobs</div>,17  });18});19addons.register('storybookjs/info', () => {20  addons.addPanel('storybookjs/info/panel', {21    render: () => <div>Info</div>,22  });23});24addons.register('storybookjs/actions', () => {25  addons.addPanel('storybookjs/actions/panel', {26    render: () => <div>Actions</div>,27  });28});29addons.register('storybookjs/viewport', () => {30  addons.addPanel('storybookjs/viewport/panel', {31    render: () => <div>Viewport</div>,32  });33});34addons.register('storybookjs/source', () => {35  addons.addPanel('storybookjs/source/panel', {36    render: () => <div>Source</div>,37  });38});39addons.register('storybookjs/links', () => {Using AI Code Generation
1import addons from '@storybook/addons';2import { ADDON_ID, PANEL_ID } from './';3import { ADDON_ID as ADDON_ID_KNOBS } from '@storybook/addon-knobs';4addons.register(ADDON_ID, api => {5  addons.addPanel(PANEL_ID, {6    render: ({ active, key }) => (7      <MyPanel key={key} api={api} active={active} />8  });9});10import addons from '@storybook/addons';11import { ADDON_ID, PANEL_ID } from './';12import { ADDON_ID as ADDON_ID_KNOBS } from '@storybook/addon-knobs';13addons.register(ADDON_ID, api => {14  addons.addPanel(PANEL_ID, {15    render: ({ active, key }) => (16      <MyPanel key={key} api={api} active={active} />17  });18});19import React from 'react';20import { useParameter } from '@storybook/api';21import { PARAM_KEY } from './';22export const MyPanel = () => {23  const value = useParameter(PARAM_KEY, null);24  return <div>{value}</div>;25};Using AI Code Generation
1import addons from '@storybook/addons';2import { EVENT_ID } from './constants';3addons.getChannel().addListener(EVENT_ID, data => {4  console.log(`Received ${EVENT_ID} with data: ${data}`);5});6export const EVENT_ID = 'my-event';7import { EVENT_ID } from './constants';8addons.getChannel().emit(EVENT_ID, 'Hello from the preview');9import { EVENT_ID } from './constants';10addons.getChannel().emit(EVENT_ID, 'Hello from the manager');11import { EVENT_ID } from './constants';12addons.getChannel().emit(EVENT_ID, 'Hello from the preview');13import { EVENT_ID } from './constants';14addons.getChannel().emit(EVENT_ID, 'Hello from the manager');15import { EVENT_ID } from './constants';16addons.getChannel().emit(EVENT_ID, 'Hello from the preview');17import { EVENT_ID } from './constants';18addons.getChannel().emit(EVENT_ID, 'Hello from the manager');19import { EVENT_ID } from './constants';20addons.getChannel().emit(EVENT_ID, 'Hello from the preview');21import { EVENT_ID } from './constants';22addons.getChannel().emit(EVENT_ID, 'Hello from the manager');23import { EVENT_ID } from './constants';24addons.getChannel().emit(EVENT_ID, 'Hello from the preview');25import { EVENT_ID } from './constants';Using AI Code Generation
1import { addons } from '@storybook/addons';2import { withRootDecorator } from 'storybook-root-decorator';3addons.setConfig({4  decorator: withRootDecorator({5    style: {6    },7    bodyStyle: {8    },9  }),10});11import { withRootDecorator } from 'storybook-root-decorator';12  withRootDecorator({13    style: {14    },15    bodyStyle: {16    },17  }),18];19import React from 'react';20import { storiesOf } from '@storybook/react';21import MyComponent from './MyComponent';22storiesOf('MyComponent', module).add('default', () => <MyComponent />);23Default: {}24Default: {}Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
