PluginProbe
Elementor Website Builder – more than just a page builder / 3.26.1
Elementor Website Builder – more than just a page builder v3.26.1
4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 All 457 releases
elementor / assets / js / container.7bbfb10dea9b7c487356.bundle.js

container.7bbfb10dea9b7c487356.bundle.js in Elementor Website Builder – more than just a page builder 3.26.1, at assets/js/container.7bbfb10dea9b7c487356.bundle.js

505 lines 18.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*! elementor - v3.26.0 - 19-12-2024 */
2 "use strict";
3 (self["webpackChunkelementor"] = self["webpackChunkelementor"] || []).push([["container"],{
4
5 /***/ "../assets/dev/js/frontend/handlers/container/grid-container.js":
6 /*!**********************************************************************!*\
7 !*** ../assets/dev/js/frontend/handlers/container/grid-container.js ***!
8 \**********************************************************************/
9 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
10
11
12
13 Object.defineProperty(exports, "__esModule", ({
14 value: true
15 }));
16 exports["default"] = void 0;
17 __webpack_require__(/*! core-js/modules/es.array.includes.js */ "../node_modules/core-js/modules/es.array.includes.js");
18 __webpack_require__(/*! core-js/modules/es.array.push.js */ "../node_modules/core-js/modules/es.array.push.js");
19 class GridContainer extends elementorModules.frontend.handlers.Base {
20 __construct(settings) {
21 super.__construct(settings);
22 this.onDeviceModeChange = this.onDeviceModeChange.bind(this);
23 this.updateEmptyViewHeight = this.updateEmptyViewHeight.bind(this);
24 }
25 isActive() {
26 return elementorFrontend.isEditMode();
27 }
28 getDefaultSettings() {
29 return {
30 selectors: {
31 gridOutline: '.e-grid-outline',
32 directGridOverlay: ':scope > .e-grid-outline',
33 boxedContainer: ':scope > .e-con-inner',
34 emptyView: '.elementor-empty-view'
35 },
36 classes: {
37 outline: 'e-grid-outline',
38 outlineItem: 'e-grid-outline-item'
39 }
40 };
41 }
42 getDefaultElements() {
43 const selectors = this.getSettings('selectors');
44 return {
45 outlineParentContainer: null,
46 gridOutline: this.findElement(selectors.gridOutline),
47 directChildGridOverlay: this.findElement(selectors.directGridOverlay),
48 emptyView: this.findElement(selectors.emptyView)[0],
49 container: this.$element[0]
50 };
51 }
52 onInit() {
53 super.onInit();
54 this.initLayoutOverlay();
55 this.updateEmptyViewHeight();
56 elementor.hooks.addAction('panel/open_editor/container', this.onPanelShow);
57 }
58 onPanelShow(panel, model) {
59 const settingsModel = model.get('settings'),
60 containerType = settingsModel.get('container_type'),
61 $linkElement = panel.$el.find('#elementor-panel__editor__help__link'),
62 href = 'grid' === containerType ? 'https://go.elementor.com/widget-container-grid' : 'https://go.elementor.com/widget-container';
63 if ($linkElement) {
64 $linkElement.attr('href', href);
65 }
66 }
67 bindEvents() {
68 elementorFrontend.elements.$window.on('resize', this.onDeviceModeChange);
69 elementorFrontend.elements.$window.on('resize', this.updateEmptyViewHeight);
70 this.addChildLifeCycleEventListeners();
71 }
72 unbindEvents() {
73 this.removeChildLifeCycleEventListeners();
74 elementorFrontend.elements.$window.off('resize', this.onDeviceModeChange);
75 elementorFrontend.elements.$window.off('resize', this.updateEmptyViewHeight);
76 }
77 initLayoutOverlay() {
78 this.getCorrectContainer();
79 // Re-init empty view element after container layout change
80 const selectors = this.getSettings('selectors'),
81 isGridContainer = 'grid' === this.getElementSettings('container_type');
82 this.elements.emptyView = this.findElement(selectors.emptyView)[0];
83 if (isGridContainer && this.elements?.emptyView) {
84 this.elements.emptyView.style.display = this.shouldRemoveEmptyView() ? 'none' : 'block';
85 }
86 if (!this.shouldDrawOutline()) {
87 return;
88 }
89 this.removeExistingOverlay();
90 this.createOverlayContainer();
91 this.createOverlayItems();
92 }
93 shouldDrawOutline() {
94 const {
95 grid_outline: gridOutline
96 } = this.getElementSettings();
97 return gridOutline;
98 }
99 getCorrectContainer() {
100 const container = this.elements.container,
101 getDefaultSettings = this.getDefaultSettings(),
102 {
103 selectors: {
104 boxedContainer
105 }
106 } = getDefaultSettings;
107 this.elements.outlineParentContainer = container.querySelector(boxedContainer) || container;
108 }
109 removeExistingOverlay() {
110 this.elements.gridOutline?.remove();
111 }
112 createOverlayContainer() {
113 const {
114 outlineParentContainer
115 } = this.elements,
116 {
117 classes: {
118 outline
119 }
120 } = this.getDefaultSettings(),
121 gridOutline = document.createElement('div');
122 gridOutline.classList.add(outline);
123 outlineParentContainer.appendChild(gridOutline);
124 this.elements.gridOutline = gridOutline;
125 this.setGridOutlineDimensions();
126 }
127 createOverlayItems() {
128 const {
129 gridOutline
130 } = this.elements,
131 {
132 classes: {
133 outlineItem
134 }
135 } = this.getDefaultSettings(),
136 numberOfItems = this.getMaxOutlineElementsNumber();
137 for (let i = 0; i < numberOfItems; i++) {
138 const gridOutlineItem = document.createElement('div');
139 gridOutlineItem.classList.add(outlineItem);
140 gridOutline.appendChild(gridOutlineItem);
141 }
142 }
143
144 /**
145 * Get the grid dimensions for the current device.
146 *
147 * @return { { columns: { value, length }, rows: { value, length } } }
148 */
149 getDeviceGridDimensions() {
150 const currentDevice = elementor.channels.deviceMode.request('currentMode');
151 return {
152 rows: this.getControlValues('grid_rows_grid', currentDevice, 'grid-template-rows') || 1,
153 columns: this.getControlValues('grid_columns_grid', currentDevice, 'grid-template-columns') || 1
154 };
155 }
156 setGridOutlineDimensions() {
157 const {
158 gridOutline
159 } = this.elements,
160 {
161 rows,
162 columns
163 } = this.getDeviceGridDimensions();
164 gridOutline.style.gridTemplateColumns = columns.value;
165 gridOutline.style.gridTemplateRows = rows.value;
166 }
167
168 /**
169 * Set the control value for the current device.
170 * Distinguish between grid custom values and slider controls.
171 *
172 * @param {string} control - The control name.
173 * @param {string} device - The device mode.
174 * @param {string} property - The CSS property name we need to copy from the parent container.
175 *
176 * @return {Object} - E,g. {value: repeat(2, 1fr), length: 2}.
177 */
178 getControlValues(control, device, property) {
179 const elementSettings = this.getElementSettings(),
180 {
181 unit,
182 size
183 } = elementSettings[control],
184 {
185 outlineParentContainer
186 } = this.elements,
187 controlValueForCurrentDevice = elementorFrontend.utils.controls.getResponsiveControlValue(elementSettings, control, 'size', device),
188 controlValue = this.getComputedStyle(outlineParentContainer, property),
189 computedStyleLength = controlValue.split(' ').length;
190 let controlData;
191 if ('custom' === unit && 'string' === typeof controlValueForCurrentDevice || size < computedStyleLength) {
192 controlData = {
193 value: controlValue
194 };
195 } else {
196 // In this case the data is taken from the getComputedStyle and not from the control, in order to handle cases when the user has more elements than grid cells.
197 controlData = {
198 value: `repeat(${computedStyleLength}, 1fr)`
199 };
200 }
201 controlData = {
202 ...controlData,
203 length: computedStyleLength
204 };
205 return controlData;
206 }
207 getComputedStyle(container, property) {
208 return window?.getComputedStyle(container, null).getPropertyValue(property);
209 }
210 onElementChange(propertyName) {
211 if (this.isControlThatMayAffectEmptyViewHeight(propertyName)) {
212 this.updateEmptyViewHeight();
213 }
214 let propsThatTriggerGridLayoutRender = ['grid_rows_grid', 'grid_columns_grid', 'grid_gaps', 'container_type', 'boxed_width', 'content_width', 'width', 'height', 'min_height', 'padding', 'grid_auto_flow'];
215
216 // Add responsive control names to the list of controls that trigger re-rendering.
217 propsThatTriggerGridLayoutRender = this.getResponsiveControlNames(propsThatTriggerGridLayoutRender);
218 if (propsThatTriggerGridLayoutRender.includes(propertyName)) {
219 this.initLayoutOverlay();
220 }
221 }
222 isControlThatMayAffectEmptyViewHeight(propertyName) {
223 return 0 === propertyName.indexOf('grid_rows_grid') || 0 === propertyName.indexOf('grid_columns_grid') || 0 === propertyName.indexOf('grid_auto_flow');
224 }
225
226 /**
227 * GetResponsiveControlNames
228 * Add responsive control names to the list of controls that trigger re-rendering.
229 *
230 * @param {Array} propsThatTriggerGridLayoutRender - array of control names.
231 *
232 * @return {Array}
233 */
234 getResponsiveControlNames(propsThatTriggerGridLayoutRender) {
235 const activeBreakpoints = elementorFrontend.breakpoints.getActiveBreakpointsList();
236 const responsiveControlNames = [];
237 for (const prop of propsThatTriggerGridLayoutRender) {
238 for (const breakpoint of activeBreakpoints) {
239 responsiveControlNames.push(`${prop}_${breakpoint}`);
240 }
241 }
242 responsiveControlNames.push(...propsThatTriggerGridLayoutRender);
243 return responsiveControlNames;
244 }
245 onDeviceModeChange() {
246 this.initLayoutOverlay();
247 }
248
249 /**
250 * Rerender Grid Overlay when child element is added or removed from its parent.
251 *
252 * @return {void}
253 */
254 addChildLifeCycleEventListeners() {
255 this.lifecycleChangeListener = this.initLayoutOverlay.bind(this);
256 window.addEventListener('elementor/editor/element-rendered', this.lifecycleChangeListener);
257 window.addEventListener('elementor/editor/element-destroyed', this.lifecycleChangeListener);
258 }
259 removeChildLifeCycleEventListeners() {
260 window.removeEventListener('elementor/editor/element-rendered', this.lifecycleChangeListener);
261 window.removeEventListener('elementor/editor/element-destroyed', this.lifecycleChangeListener);
262 }
263 updateEmptyViewHeight() {
264 if (this.shouldUpdateEmptyViewHeight()) {
265 const {
266 emptyView
267 } = this.elements,
268 currentDevice = elementor.channels.deviceMode.request('currentMode'),
269 elementSettings = this.getElementSettings(),
270 gridRows = 'desktop' === currentDevice ? elementSettings.grid_rows_grid : elementSettings.grid_rows_grid + '_' + currentDevice;
271 emptyView?.style.removeProperty('min-height');
272 if (this.hasCustomUnit(gridRows) && this.isNotOnlyANumber(gridRows) && this.sizeNotEmpty(gridRows)) {
273 emptyView.style.minHeight = 'auto';
274 }
275
276 // This is to handle cases where `minHeight: auto` computes to `0`.
277 if (emptyView?.offsetHeight <= 0) {
278 emptyView.style.minHeight = '100px';
279 }
280 }
281 }
282 shouldUpdateEmptyViewHeight() {
283 return !!this.elements.container.querySelector('.elementor-empty-view');
284 }
285 hasCustomUnit(gridRows) {
286 return 'custom' === gridRows?.unit;
287 }
288 sizeNotEmpty(gridRows) {
289 return '' !== gridRows?.size?.trim();
290 }
291 isNotOnlyANumber(gridRows) {
292 const numberPattern = /^\d+$/;
293 return !numberPattern.test(gridRows?.size);
294 }
295 shouldRemoveEmptyView() {
296 const childrenLength = this.elements.outlineParentContainer.querySelectorAll(':scope > .elementor-element').length;
297 if (0 === childrenLength) {
298 return false;
299 }
300 const maxElements = this.getMaxElementsNumber();
301 return maxElements <= childrenLength && this.isFullFilled(childrenLength);
302 }
303 isFullFilled(numberOfElements) {
304 const gridDimensions = this.getDeviceGridDimensions(),
305 {
306 grid_auto_flow: gridAutoFlow
307 } = this.getElementSettings();
308 const flowTypeField = 'row' === gridAutoFlow ? 'columns' : 'rows';
309 return 0 === numberOfElements % gridDimensions[flowTypeField].length;
310 }
311 getMaxOutlineElementsNumber() {
312 const childrenLength = this.elements.outlineParentContainer.querySelectorAll(':scope > .elementor-element').length,
313 gridDimensions = this.getDeviceGridDimensions(),
314 maxElementsBySettings = this.getMaxElementsNumber(),
315 {
316 grid_auto_flow: gridAutoFlow
317 } = this.getElementSettings();
318 const flowTypeField = 'row' === gridAutoFlow ? 'columns' : 'rows';
319 const maxElementsByItems = Math.ceil(childrenLength / gridDimensions[flowTypeField].length) * gridDimensions[flowTypeField].length;
320 return maxElementsBySettings > maxElementsByItems ? maxElementsBySettings : maxElementsByItems;
321 }
322 getMaxElementsNumber() {
323 const elementSettings = this.getElementSettings(),
324 device = elementor.channels.deviceMode.request('currentMode'),
325 {
326 grid_auto_flow: gridAutoFlow
327 } = this.getElementSettings(),
328 gridDimensions = this.getDeviceGridDimensions();
329 if ('row' === gridAutoFlow) {
330 const rows = elementorFrontend.utils.controls.getResponsiveControlValue(elementSettings, 'grid_rows_grid', 'size', device);
331 const rowsLength = isNaN(rows) ? rows.split(' ').length : rows;
332 return gridDimensions.columns.length * rowsLength;
333 }
334 const columns = elementorFrontend.utils.controls.getResponsiveControlValue(elementSettings, 'grid_columns_grid', 'size', device);
335 const columnsLength = isNaN(columns) ? rows.split(' ').length : columns;
336 return gridDimensions.rows.length * columnsLength;
337 }
338 }
339 exports["default"] = GridContainer;
340
341 /***/ }),
342
343 /***/ "../assets/dev/js/frontend/handlers/container/handles-position.js":
344 /*!************************************************************************!*\
345 !*** ../assets/dev/js/frontend/handlers/container/handles-position.js ***!
346 \************************************************************************/
347 /***/ ((__unused_webpack_module, exports) => {
348
349
350
351 Object.defineProperty(exports, "__esModule", ({
352 value: true
353 }));
354 exports["default"] = void 0;
355 /**
356 * TODO: Try to merge with `section/handles-position.js` and create a generic solution using `.elementor-element`.
357 */
358 class HandlesPosition extends elementorModules.frontend.handlers.Base {
359 isActive() {
360 return elementorFrontend.isEditMode();
361 }
362 isFirstContainer() {
363 return this.$element[0] === document.querySelector('.elementor-edit-mode .e-con:first-child');
364 }
365 isOverflowHidden() {
366 return 'hidden' === this.$element.css('overflow');
367 }
368 getOffset() {
369 if ('body' === elementor.config.document.container) {
370 return this.$element.offset().top;
371 }
372 const $container = jQuery(elementor.config.document.container);
373 return this.$element.offset().top - $container.offset().top;
374 }
375 setHandlesPosition() {
376 const document = elementor.documents.getCurrent();
377 if (!document || !document.container.isEditable()) {
378 return;
379 }
380 const isOverflowHidden = this.isOverflowHidden();
381 if (!isOverflowHidden && !this.isFirstContainer()) {
382 return;
383 }
384 const offset = isOverflowHidden ? 0 : this.getOffset(),
385 $handlesElement = this.$element.find('> .elementor-element-overlay > .elementor-editor-section-settings'),
386 insideHandleClass = 'e-handles-inside';
387 if (offset < 25) {
388 this.$element.addClass(insideHandleClass);
389 if (offset < -5) {
390 $handlesElement.css('top', -offset);
391 } else {
392 $handlesElement.css('top', '');
393 }
394 } else {
395 this.$element.removeClass(insideHandleClass);
396 }
397 }
398 onInit() {
399 if (!this.isActive()) {
400 return;
401 }
402 this.setHandlesPosition();
403 this.$element.on('mouseenter', this.setHandlesPosition.bind(this));
404 }
405 }
406 exports["default"] = HandlesPosition;
407
408 /***/ }),
409
410 /***/ "../assets/dev/js/frontend/handlers/container/shapes.js":
411 /*!**************************************************************!*\
412 !*** ../assets/dev/js/frontend/handlers/container/shapes.js ***!
413 \**************************************************************/
414 /***/ ((__unused_webpack_module, exports) => {
415
416
417
418 Object.defineProperty(exports, "__esModule", ({
419 value: true
420 }));
421 exports["default"] = void 0;
422 // TODO: Copied from `section/shapes.js`.
423 class Shapes extends elementorModules.frontend.handlers.Base {
424 getDefaultSettings() {
425 const contentWidth = this.getElementSettings('content_width'),
426 container = 'boxed' === contentWidth ? '> .e-con-inner > .elementor-shape-%s' : '> .elementor-shape-%s';
427 return {
428 selectors: {
429 container
430 },
431 svgURL: elementorFrontend.config.urls.assets + 'shapes/'
432 };
433 }
434 getDefaultElements() {
435 const elements = {},
436 selectors = this.getSettings('selectors');
437 elements.$topContainer = this.$element.find(selectors.container.replace('%s', 'top'));
438 elements.$bottomContainer = this.$element.find(selectors.container.replace('%s', 'bottom'));
439 return elements;
440 }
441 isActive() {
442 return elementorFrontend.isEditMode();
443 }
444 getSvgURL(shapeType, fileName) {
445 let svgURL = this.getSettings('svgURL') + fileName + '.svg';
446 if (elementor.config.additional_shapes && shapeType in elementor.config.additional_shapes) {
447 svgURL = elementor.config.additional_shapes[shapeType];
448 if (-1 < fileName.indexOf('-negative')) {
449 svgURL = svgURL.replace('.svg', '-negative.svg');
450 }
451 }
452 return svgURL;
453 }
454 buildSVG(side) {
455 const baseSettingKey = 'shape_divider_' + side,
456 shapeType = this.getElementSettings(baseSettingKey),
457 $svgContainer = this.elements['$' + side + 'Container'];
458 $svgContainer.attr('data-shape', shapeType);
459 if (!shapeType) {
460 $svgContainer.empty(); // Shape-divider set to 'none'
461 return;
462 }
463 let fileName = shapeType;
464 if (this.getElementSettings(baseSettingKey + '_negative')) {
465 fileName += '-negative';
466 }
467 const svgURL = this.getSvgURL(shapeType, fileName);
468 jQuery.get(svgURL, data => {
469 $svgContainer.empty().append(data.childNodes[0]);
470 });
471 this.setNegative(side);
472 }
473 setNegative(side) {
474 this.elements['$' + side + 'Container'].attr('data-negative', !!this.getElementSettings('shape_divider_' + side + '_negative'));
475 }
476 onInit() {
477 if (!this.isActive(this.getSettings())) {
478 return;
479 }
480 super.onInit(...arguments);
481 ['top', 'bottom'].forEach(side => {
482 if (this.getElementSettings('shape_divider_' + side)) {
483 this.buildSVG(side);
484 }
485 });
486 }
487 onElementChange(propertyName) {
488 const shapeChange = propertyName.match(/^shape_divider_(top|bottom)$/);
489 if (shapeChange) {
490 this.buildSVG(shapeChange[1]);
491 return;
492 }
493 const negativeChange = propertyName.match(/^shape_divider_(top|bottom)_negative$/);
494 if (negativeChange) {
495 this.buildSVG(negativeChange[1]);
496 this.setNegative(negativeChange[1]);
497 }
498 }
499 }
500 exports["default"] = Shapes;
501
502 /***/ })
503
504 }]);
505 //# sourceMappingURL=container.7bbfb10dea9b7c487356.bundle.js.map