PageSourceSearch

https://www.alliedelectronics.com/mm5/json.mvc?Store_Code=Allied04…=mmx-category-carousel&T=9fc2de2b

js alliedelectronics.com collected 2026-09-26 17:42:48 UTC 11,403 bytes, 443 lines download raw bytes

1/**
2 * MMX / CATEGORY CAROUSEL
3 */
4class MMX_CategoryCarousel extends MMX_Element {
5
6	static get props() {
7		let props = MMX.assign(MMX_CategoryCarousel.carouselProps, MMX_HeroSlider.props);
8		props['gap'].default = 32;
9		props['per-page'].default = '1,3,5';
10		props['arrow-style'].default = 'button';
11		props['nav-position'].default = 'none';
12		props['wrap'].default = false;
13		props['autoplay'].default = false;
14		return props;
15	}
16
17	static carouselProps = {
18		'fallback-image': {
19			allowAny: true
20		},
21		'image-fit': {
22			allowAny: true,
23			options: [
24				'cover',
25				'contain',
26				'fill',
27				'none',
28				'scale-down'
29			],
30			default: 'contain'
31		}
32	};
33
34	styleResourceCodes = ['mmx-base', 'mmx-button', 'mmx-hero', 'mmx-hero-slider'];
35	loadedCategories = {};
36	categories = [];
37
38	constructor() {
39		super();
40		this.makeComponent();
41		this.bindRevealElement();
42	}
43
44	render() {
45		return /*html*/`
46			<div part="wrapper" class="mmx-category-carousel">
47				<div part="title" class="mmx-category-carousel__title">
48					<slot name="title"></slot>
49				</div>
50				${this.renderCategories()}
51			</div>
52		`;
53	}
54
55	styles() {
56		return /*css*/`
57			slot[name="title"]::slotted(*) {
58				margin: 0 auto 3%;
59			}
60		`;
61	}
62
63	onDataChange() {
64		MMX.setElementAttributes(this, {
65			'data-per-page': this.data?.advanced?.slide_controls?.per_page?.value,
66			'data-per-move': this.data?.advanced?.slide_controls?.per_move?.value,
67			'data-peek': this.data?.advanced?.slide_controls?.peek?.value,
68			'data-size': this.data?.category_group?.image_size?.value,
69			'data-image-fit': this.data?.category_group?.image_fit?.value
70		});
71
72		this.displayCategories();
73	}
74
75	displayCategories() {
76		if (this.data?.category_group?.source?.value === 'manual')		this.loadCategories();
77		else if (this.data?.category_group?.source?.value === 'ids')	this.loadCategoriesByIds();
78		else															this.loadChildCategories();
79	}
80
81	loadCategoriesByIds() {
82		const categoryIds = this.data?.category_group?.categories?.ids ?? [];
83
84		if (MMX.arrayIsEmpty(categoryIds)) {
85			return;
86		}
87
88		this.categories = [];
89		this.setLifecycleReady(false);
90
91		const imageEnabled = this.data?.category_group?.category_image?.settings?.enabled;
92		const filters = [
93			{
94				name: 'search',
95				value: [
96					{
97						field: 'id',
98						operator: 'IN',
99						value: categoryIds
100					}
101				]
102			}
103		];
104
105		if (imageEnabled) {
106			filters.push({
107				name: 'ondemandcolumns',
108				value: [
109					'CustomField_Values:cmp-cssui-cattitle:category_title_image',
110					'CustomField_Values:cmp-cssui-cattree:category_tree_image'
111				]
112			});
113		}
114
115		MMX.Runtime_JSON_API_Call({
116			params: {
117				Function: 'Runtime_CategoryList_Load_Query',
118				Filter: filters
119			}
120		})
121		.then(response => this.#onCategoriesLoaded(response?.data?.data, categoryIds))
122		.catch(response => {});
123	}
124
125	#getCategoriesToLoad() {
126		const children = this?.data?.category_group?.categories?.children;
127
128		if (!children?.length) {
129			return [];
130		}
131
132		return children.reduce((categories, child) => {
133			const category = child?.category?.category;
134			const code = category?.code;
135
136			if (!MMX.valueIsEmpty(code) && categories.findIndex(item => item.code === code) === -1 && MMX.isTruthy(child?.image?.category_image?.settings?.enabled)) {
137				categories.push(category);
138			}
139
140			return categories;
141		}, []);
142	}
143
144	getCategoryCodesToLoad() {
145		const categories = this.#getCategoriesToLoad();
146
147		if (!categories?.length) {
148			return undefined;
149		}
150
151		return categories.map(category => category.code);
152	}
153
154	loadCategories() {
155		const categoryCodes = this.getCategoryCodesToLoad();
156
157		if (!categoryCodes?.length) {
158			return;
159		}
160
161		this.setLifecycleReady(false);
162
163		MMX.Runtime_JSON_API_Call({
164			params: {
165				Function: 'Runtime_CategoryList_Load_Query',
166				Filter: [
167					{
168						name: 'search',
169						value: [
170							{
171								field: 'code',
172								operator: 'IN',
173								value: categoryCodes
174							}
175						]
176					},
177					{
178						name: 'ondemandcolumns',
179						value: [
180							'CustomField_Values:cmp-cssui-cattitle:category_title_image',
181							'CustomField_Values:cmp-cssui-cattree:category_tree_image'
182						]
183					},
184					...MMX.cacheKeysFilters(this.#getCategoriesToLoad())
185				]
186			}
187		})
188		.then(response => {
189			if(!response?.data?.data?.length) {
190				return;
191			}
192
193			response.data.data.forEach(category => {
194				this.loadedCategories[category.id] = category;
195			});
196
197			this.forceUpdate();
198		})
199		.catch(response => {});
200	}
201
202	loadChildCategories() {
203		if (MMX.valueIsEmpty(this?.data?.category_id)) {
204			return;
205		}
206
207		var filters = [];
208
209		if (this.data?.category_group?.category_image?.settings?.enabled) {
210			filters = [
211				{
212					name: 'ondemandcolumns',
213					value: [
214						'CustomField_Values:cmp-cssui-cattitle:category_title_image',
215						'CustomField_Values:cmp-cssui-cattree:category_tree_image'
216					]
217				}
218			];
219		}
220
221		filters.push(...MMX.cacheKeysFilters(this.data?.category));
222
223		this.categories = [];
224		this.setLifecycleReady(false);
225
226		MMX.Runtime_JSON_API_Call({
227			params: {
228				Function: 'Runtime_CategoryList_Load_Query',
229				Parent_ID: this.data.category_id,
230				Filter: filters
231			}
232		})
233		.then(response => this.#onCategoriesLoaded(response?.data?.data))
234		.catch(response => {});
235	}
236
237	#onCategoriesLoaded(categories = [], orderedIds = null) {
238		if (!categories.length) {
239			return;
240		}
241
242		categories.forEach(category => {
243			this.loadedCategories[category.id] = category;
244		});
245
246		const ordered = orderedIds
247			? orderedIds.map(id => this.loadedCategories[id]).filter(Boolean)
248			: categories;
249
250		ordered.forEach(category => {
251			this.categories.push(this.#buildCategoryItem(category));
252		});
253
254		this.forceUpdate();
255	}
256
257	#buildCategoryItem(category) {
258		return {
259			category: {
260				category: {
261					link: category.url,
262					...category,
263				},
264				category_code: category.code
265			},
266			image: {
267				category_image: {
268					image: {
269						value: this.data?.category_group?.category_image?.image?.value
270					},
271					settings: {
272						enabled: this.data?.category_group?.category_image?.settings?.enabled
273					}
274				}
275			}
276		};
277	}
278
279	renderCategories() {
280		var children;
281
282		if (this.data?.category_group?.source?.value === 'auto' || this.data?.category_group?.source?.value === 'ids')
283		{
284			children = this.categories;
285		}
286		else
287		{
288			children = MMX.copy(this?.data?.category_group?.categories?.children || []);
289		}
290
291		if (!children?.length) {
292			return '';
293		}
294
295		return /*html*/`
296			<mmx-hero-slider
297				part="slider"
298				data-per-page="${this.getPropValue('per-page')}"
299				data-per-move="${this.getPropValue('per-move')}"
300				data-peek="${this.getPropValue('peek')}"
301				data-gap="${this.getPropValue('gap')}"
302				data-size="${this.getPropValue('size')}"
303				data-autoplay="${this.getPropValue('autoplay')}"
304				data-delay="${this.getPropValue('delay')}"
305				data-pause-on-hover="${this.getPropValue('pause-on-hover')}"
306				data-arrow-style="${this.getPropValue('arrow-style')}"
307				data-nav-position="${this.getPropValue('nav-position')}"
308				data-nav-button-size="${this.getPropValue('nav-button-size')}"
309				data-wrap="${this.getPropValue('wrap')}"
310			>
311				${children.map(child => this.renderCategory(child)).join('')}
312			</mmx-hero-slider>
313		`;
314	}
315
316	renderCategory(child) {
317		// Skip unavailable/inactive categories
318		if(!child?.category?.category?.id) {
319			return '';
320		}
321
322		const theme_available = this.data?.text_styles?.category_name?.typography_theme?.theme_available;
323
324		return /*html*/`
325			<mmx-hero
326				slot="hero_slide"
327				part="hero_slide"
328				data-fit="${MMX.encodeEntities(this.getPropValue('image-fit'))}"
329				data-href="${MMX.encodeEntities(child.category.category.link)}"
330			>
331				${this.renderCategoryImage(child)}
332				<mmx-text
333					slot="heading"
334					part="hero_slide__heading"
335					data-theme="${MMX.encodeEntities(theme_available)}"
336					data-theme-class="${MMX.encodeEntities(this.data?.text_styles?.category_name?.typography_theme?.classname ?? '')}"
337					data-style="${this.data?.text_styles?.category_name?.style?.value ?? ''}"
338					data-align="${this.data?.text_styles?.align?.value ?? ''}"
339				>
340					${this.renderLegacyStylesTemplate(theme_available, this.getStylesFromGroup(this.data?.text_styles?.category_name))}
341					${this.renderThemeStylesheetTemplate(theme_available)}
342					${child.category.category.name}
343				</mmx-text>
344			</mmx-hero>
345		`;
346	}
347
348	renderCategoryImage(child) {
349		let mobileSource = '';
350		let tabletSource = '';
351
352		child.image.url = this.getPropValue('fallback-image');
353
354		// Custom Images
355		if (MMX.isTruthy(child?.image?.custom_image?.settings?.enabled) && child?.image?.custom_image?.image?.image?.length ) {
356			child.image.url = child.image.custom_image.image.image;
357
358			const mobileImage = this.#getResponsiveImageData('mobile', child?.image?.custom_image?.image);
359
360			if (mobileImage) {
361				mobileSource = /*html*/`<source
362					class="source__mobile"
363					media="(max-width: 39.999em)"
364					srcset="${MMX.encodeEntitiesURI(mobileImage.image)}"
365					width="${MMX.encodeEntities(mobileImage.width)}"
366					height="${MMX.encodeEntities(mobileImage.height)}"
367				>`;
368			}
369
370			const tabletImage = this.#getResponsiveImageData('tablet', child?.image?.custom_image?.image);
371
372			if (tabletImage) {
373				tabletSource = /*html*/`<source
374					class="source__tablet"
375					media="(max-width: 59.999em)"
376					srcset="${MMX.encodeEntitiesURI(tabletImage.image)}"
377					width="${MMX.encodeEntities(tabletImage.width)}"
378					height="${MMX.encodeEntities(tabletImage.height)}"
379				>`;
380			}
381		}
382		// Category Image (tree or title)
383		else if (MMX.isTruthy(child?.image?.category_image?.settings?.enabled)) {
384			const loadedCategory = this.loadedCategories[child.category.category.id];
385			if (child?.image?.category_image?.image?.value === 'cattitle' && loadedCategory?.CustomField_Values?.['cmp-cssui-cattitle']?.category_title_image?.length) {
386				child.image.url = loadedCategory.CustomField_Values['cmp-cssui-cattitle'].category_title_image;
387			}
388			else if (child?.image?.category_image?.image?.value === 'cattree' && loadedCategory?.CustomField_Values?.['cmp-cssui-cattree']?.category_tree_image?.length) {
389				child.image.url = loadedCategory.CustomField_Values['cmp-cssui-cattree'].category_tree_image;
390			}
391		}
392
393		if(!child.image.url?.length) {
394			return '';
395		}
396
397		return /*html*/`
398			<picture
399				slot="image"
400				part="hero_slide__image"
401			>
402				${mobileSource}
403				${tabletSource}
404				<img
405					src="${MMX.encodeEntitiesURI(child.image.url)}"
406					alt="${MMX.encodeEntities(child.image.custom_image?.image?.alt)}"
407					width="${MMX.encodeEntities(child.image.custom_image?.image?.width)}"
408					height="${MMX.encodeEntities(child.image.custom_image?.image?.height)}"
409					${this.getLoadingAttributeString()}
410				>
411			</picture>
412		`;
413	}
414
415	#getResponsiveImageData(device, image) {
416		const responsiveImageData = image?.responsive_image_data?.[device];
417		const responsiveImage = image?.responsive_images?.[device];
418
419		if (!MMX.valueIsEmpty(responsiveImageData?.image)) {
420			return responsiveImageData;
421		}
422		else if (!MMX.valueIsEmpty(responsiveImage)) {
423			return {
424				image: responsiveImage
425			};
426		}
427		else {
428			return undefined;
429		}
430	}
431
432	slider() {
433		return this.shadowRoot.querySelector('[part~="slider"]');
434	}
435
436	revealElement(element) {
437		this.slider()?.revealElement(element);
438	}
439}
440
441if (!customElements.get('mmx-category-carousel')) {
442	customElements.define('mmx-category-carousel', MMX_CategoryCarousel);
443}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.