PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.0-dev1
Elementor Website Builder – more than just a page builder v3.6.0-dev1
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 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / trunk / includes / elements / column.php

column.php in Elementor Website Builder – more than just a page builder 3.6.0-dev1, at trunk/includes/elements/column.php

1,067 lines 27.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 use Elementor\Core\Breakpoints\Manager as Breakpoints_Manager;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit; // Exit if accessed directly.
8 }
9
10 /**
11 * Elementor column element.
12 *
13 * Elementor column handler class is responsible for initializing the column
14 * element.
15 *
16 * @since 1.0.0
17 */
18 class Element_Column extends Element_Base {
19
20 /**
21 * Get column name.
22 *
23 * Retrieve the column name.
24 *
25 * @since 1.0.0
26 * @access public
27 *
28 * @return string Column name.
29 */
30 public function get_name() {
31 return 'column';
32 }
33
34 /**
35 * Get element type.
36 *
37 * Retrieve the element type, in this case `column`.
38 *
39 * @since 2.1.0
40 * @access public
41 * @static
42 *
43 * @return string The type.
44 */
45 public static function get_type() {
46 return 'column';
47 }
48
49 /**
50 * Get column title.
51 *
52 * Retrieve the column title.
53 *
54 * @since 1.0.0
55 * @access public
56 *
57 * @return string Column title.
58 */
59 public function get_title() {
60 return esc_html__( 'Column', 'elementor' );
61 }
62
63 /**
64 * Get column icon.
65 *
66 * Retrieve the column icon.
67 *
68 * @since 1.0.0
69 * @access public
70 *
71 * @return string Column icon.
72 */
73 public function get_icon() {
74 return 'eicon-column';
75 }
76
77 /**
78 * Get initial config.
79 *
80 * Retrieve the current section initial configuration.
81 *
82 * Adds more configuration on top of the controls list, the tabs assigned to
83 * the control, element name, type, icon and more. This method also adds
84 * section presets.
85 *
86 * @since 2.9.0
87 * @access protected
88 *
89 * @return array The initial config.
90 */
91 protected function get_initial_config() {
92 $config = parent::get_initial_config();
93
94 $config['controls'] = $this->get_controls();
95 $config['tabs_controls'] = $this->get_tabs_controls();
96
97 return $config;
98 }
99
100 /**
101 * Register column controls.
102 *
103 * Used to add new controls to the column element.
104 *
105 * @since 3.1.0
106 * @access protected
107 */
108 protected function register_controls() {
109 // Section Layout.
110 $this->start_controls_section(
111 'layout',
112 [
113 'label' => esc_html__( 'Layout', 'elementor' ),
114 'tab' => Controls_Manager::TAB_LAYOUT,
115 ]
116 );
117
118 // Element Name for the Navigator
119 $this->add_control(
120 '_title',
121 [
122 'label' => esc_html__( 'Title', 'elementor' ),
123 'type' => Controls_Manager::HIDDEN,
124 'render_type' => 'none',
125 ]
126 );
127
128 $active_breakpoint_keys = array_reverse( array_keys( Plugin::$instance->breakpoints->get_active_breakpoints() ) );
129 $inline_size_device_args = [
130 Breakpoints_Manager::BREAKPOINT_KEY_MOBILE => [ 'placeholder' => 100 ],
131 ];
132
133 foreach ( $active_breakpoint_keys as $breakpoint_key ) {
134 if ( ! isset( $inline_size_device_args[ $breakpoint_key ] ) ) {
135 $inline_size_device_args[ $breakpoint_key ] = [];
136 }
137
138 $inline_size_device_args[ $breakpoint_key ] = array_merge_recursive(
139 $inline_size_device_args[ $breakpoint_key ],
140 [
141 'max' => 100,
142 'required' => false,
143 ]
144 );
145 }
146
147 if ( in_array( Breakpoints_Manager::BREAKPOINT_KEY_MOBILE_EXTRA, $active_breakpoint_keys, true ) ) {
148 $min_affected_device_value = Breakpoints_Manager::BREAKPOINT_KEY_MOBILE_EXTRA;
149 } else {
150 $min_affected_device_value = Breakpoints_Manager::BREAKPOINT_KEY_TABLET;
151 }
152
153 $this->add_responsive_control(
154 '_inline_size',
155 [
156 'label' => esc_html__( 'Column Width', 'elementor' ) . ' (%)',
157 'type' => Controls_Manager::NUMBER,
158 'min' => 2,
159 'max' => 98,
160 'required' => true,
161 'device_args' => $inline_size_device_args,
162 'min_affected_device' => [
163 Breakpoints_Manager::BREAKPOINT_KEY_DESKTOP => $min_affected_device_value,
164 Breakpoints_Manager::BREAKPOINT_KEY_LAPTOP => $min_affected_device_value,
165 Breakpoints_Manager::BREAKPOINT_KEY_TABLET_EXTRA => $min_affected_device_value,
166 Breakpoints_Manager::BREAKPOINT_KEY_TABLET => $min_affected_device_value,
167 Breakpoints_Manager::BREAKPOINT_KEY_MOBILE_EXTRA => $min_affected_device_value,
168 ],
169 'selectors' => [
170 '{{WRAPPER}}' => 'width: {{VALUE}}%',
171 ],
172 ]
173 );
174
175 $is_dome_optimization_active = Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' );
176 $main_selector_element = $is_dome_optimization_active ? 'widget' : 'column';
177 $widget_wrap_child = $is_dome_optimization_active ? '' : ' > .elementor-widget-wrap';
178 $column_wrap_child = $is_dome_optimization_active ? '' : ' > .elementor-column-wrap';
179
180 $this->add_responsive_control(
181 'content_position',
182 [
183 'label' => esc_html__( 'Vertical Align', 'elementor' ),
184 'type' => Controls_Manager::SELECT,
185 'default' => '',
186 'options' => [
187 '' => esc_html__( 'Default', 'elementor' ),
188 'top' => esc_html__( 'Top', 'elementor' ),
189 'center' => esc_html__( 'Middle', 'elementor' ),
190 'bottom' => esc_html__( 'Bottom', 'elementor' ),
191 'space-between' => esc_html__( 'Space Between', 'elementor' ),
192 'space-around' => esc_html__( 'Space Around', 'elementor' ),
193 'space-evenly' => esc_html__( 'Space Evenly', 'elementor' ),
194 ],
195 'selectors_dictionary' => [
196 'top' => 'flex-start',
197 'bottom' => 'flex-end',
198 ],
199 'selectors' => [
200 // TODO: The following line is for BC since 2.7.0
201 '.elementor-bc-flex-widget {{WRAPPER}}.elementor-column .elementor-' . $main_selector_element . '-wrap' => 'align-items: {{VALUE}}',
202 // This specificity is intended to make sure column css overwrites section css on vertical alignment (content_position)
203 '{{WRAPPER}}.elementor-column.elementor-element[data-element_type="column"] > .elementor-' . $main_selector_element . '-wrap.elementor-element-populated' . $widget_wrap_child => 'align-content: {{VALUE}}; align-items: {{VALUE}};',
204 ],
205 ]
206 );
207
208 $this->add_responsive_control(
209 'align',
210 [
211 'label' => esc_html__( 'Horizontal Align', 'elementor' ),
212 'type' => Controls_Manager::SELECT,
213 'default' => '',
214 'options' => [
215 '' => esc_html__( 'Default', 'elementor' ),
216 'flex-start' => esc_html__( 'Start', 'elementor' ),
217 'center' => esc_html__( 'Center', 'elementor' ),
218 'flex-end' => esc_html__( 'End', 'elementor' ),
219 'space-between' => esc_html__( 'Space Between', 'elementor' ),
220 'space-around' => esc_html__( 'Space Around', 'elementor' ),
221 'space-evenly' => esc_html__( 'Space Evenly', 'elementor' ),
222 ],
223 'selectors' => [
224 '{{WRAPPER}}.elementor-column' . $column_wrap_child . ' > .elementor-widget-wrap' => 'justify-content: {{VALUE}}',
225 ],
226 ]
227 );
228
229 $space_between_widgets_selector = $is_dome_optimization_active ? '' : '> .elementor-column-wrap ';
230
231 $this->add_responsive_control(
232 'space_between_widgets',
233 [
234 'label' => esc_html__( 'Widgets Space', 'elementor' ) . ' (px)',
235 'type' => Controls_Manager::NUMBER,
236 'placeholder' => 20,
237 'selectors' => [
238 '{{WRAPPER}} ' . $space_between_widgets_selector . '> .elementor-widget-wrap > .elementor-widget:not(.elementor-widget__width-auto):not(.elementor-widget__width-initial):not(:last-child):not(.elementor-absolute)' => 'margin-bottom: {{VALUE}}px', //Need the full path for exclude the inner section
239 ],
240 ]
241 );
242
243 $possible_tags = [
244 'div',
245 'header',
246 'footer',
247 'main',
248 'article',
249 'section',
250 'aside',
251 'nav',
252 ];
253
254 $options = [
255 '' => esc_html__( 'Default', 'elementor' ),
256 ] + array_combine( $possible_tags, $possible_tags );
257
258 $this->add_control(
259 'html_tag',
260 [
261 'label' => esc_html__( 'HTML Tag', 'elementor' ),
262 'type' => Controls_Manager::SELECT,
263 'options' => $options,
264 'render_type' => 'none',
265 ]
266 );
267
268 $this->end_controls_section();
269
270 $this->start_controls_section(
271 'section_style',
272 [
273 'label' => esc_html__( 'Background', 'elementor' ),
274 'tab' => Controls_Manager::TAB_STYLE,
275 ]
276 );
277
278 $this->start_controls_tabs( 'tabs_background' );
279
280 $this->start_controls_tab(
281 'tab_background_normal',
282 [
283 'label' => esc_html__( 'Normal', 'elementor' ),
284 ]
285 );
286
287 $this->add_group_control(
288 Group_Control_Background::get_type(),
289 [
290 'name' => 'background',
291 'types' => [ 'classic', 'gradient', 'slideshow' ],
292 'selector' => '{{WRAPPER}}:not(.elementor-motion-effects-element-type-background) > .elementor-' . $main_selector_element . '-wrap, {{WRAPPER}} > .elementor-' . $main_selector_element . '-wrap > .elementor-motion-effects-container > .elementor-motion-effects-layer',
293 'fields_options' => [
294 'background' => [
295 'frontend_available' => true,
296 ],
297 ],
298 ]
299 );
300
301 $this->end_controls_tab();
302
303 $this->start_controls_tab(
304 'tab_background_hover',
305 [
306 'label' => esc_html__( 'Hover', 'elementor' ),
307 ]
308 );
309
310 $this->add_group_control(
311 Group_Control_Background::get_type(),
312 [
313 'name' => 'background_hover',
314 'selector' => '{{WRAPPER}}:hover > .elementor-element-populated',
315 ]
316 );
317
318 $this->add_control(
319 'background_hover_transition',
320 [
321 'label' => esc_html__( 'Transition Duration', 'elementor' ),
322 'type' => Controls_Manager::SLIDER,
323 'default' => [
324 'size' => 0.3,
325 ],
326 'range' => [
327 'px' => [
328 'max' => 3,
329 'step' => 0.1,
330 ],
331 ],
332 'render_type' => 'ui',
333 'separator' => 'before',
334 ]
335 );
336
337 $this->end_controls_tab();
338
339 $this->end_controls_tabs();
340
341 $this->end_controls_section();
342
343 // Section Column Background Overlay.
344 $this->start_controls_section(
345 'section_background_overlay',
346 [
347 'label' => esc_html__( 'Background Overlay', 'elementor' ),
348 'tab' => Controls_Manager::TAB_STYLE,
349 'condition' => [
350 'background_background' => [ 'classic', 'gradient' ],
351 ],
352 ]
353 );
354
355 $this->start_controls_tabs( 'tabs_background_overlay' );
356
357 $this->start_controls_tab(
358 'tab_background_overlay_normal',
359 [
360 'label' => esc_html__( 'Normal', 'elementor' ),
361 ]
362 );
363
364 $this->add_group_control(
365 Group_Control_Background::get_type(),
366 [
367 'name' => 'background_overlay',
368 'selector' => '{{WRAPPER}} > .elementor-element-populated > .elementor-background-overlay',
369 ]
370 );
371
372 $this->add_control(
373 'background_overlay_opacity',
374 [
375 'label' => esc_html__( 'Opacity', 'elementor' ),
376 'type' => Controls_Manager::SLIDER,
377 'default' => [
378 'size' => .5,
379 ],
380 'range' => [
381 'px' => [
382 'max' => 1,
383 'step' => 0.01,
384 ],
385 ],
386 'selectors' => [
387 '{{WRAPPER}} > .elementor-element-populated > .elementor-background-overlay' => 'opacity: {{SIZE}};',
388 ],
389 'condition' => [
390 'background_overlay_background' => [ 'classic', 'gradient' ],
391 ],
392 ]
393 );
394
395 $this->add_group_control(
396 Group_Control_Css_Filter::get_type(),
397 [
398 'name' => 'css_filters',
399 'selector' => '{{WRAPPER}} > .elementor-element-populated > .elementor-background-overlay',
400 ]
401 );
402
403 $this->add_control(
404 'overlay_blend_mode',
405 [
406 'label' => esc_html__( 'Blend Mode', 'elementor' ),
407 'type' => Controls_Manager::SELECT,
408 'options' => [
409 '' => esc_html__( 'Normal', 'elementor' ),
410 'multiply' => esc_html__( 'Multiply', 'elementor' ),
411 'screen' => esc_html__( 'Screen', 'elementor' ),
412 'overlay' => esc_html__( 'Overlay', 'elementor' ),
413 'darken' => esc_html__( 'Darken', 'elementor' ),
414 'lighten' => esc_html__( 'Lighten', 'elementor' ),
415 'color-dodge' => esc_html__( 'Color Dodge', 'elementor' ),
416 'saturation' => esc_html__( 'Saturation', 'elementor' ),
417 'color' => esc_html__( 'Color', 'elementor' ),
418 'difference' => esc_html__( 'Difference', 'elementor' ),
419 'exclusion' => esc_html__( 'Exclusion', 'elementor' ),
420 'hue' => esc_html__( 'Hue', 'elementor' ),
421 'luminosity' => esc_html__( 'Luminosity', 'elementor' ),
422 ],
423 'selectors' => [
424 '{{WRAPPER}} > .elementor-element-populated > .elementor-background-overlay' => 'mix-blend-mode: {{VALUE}}',
425 ],
426 ]
427 );
428
429 $this->end_controls_tab();
430
431 $this->start_controls_tab(
432 'tab_background_overlay_hover',
433 [
434 'label' => esc_html__( 'Hover', 'elementor' ),
435 ]
436 );
437
438 $this->add_group_control(
439 Group_Control_Background::get_type(),
440 [
441 'name' => 'background_overlay_hover',
442 'selector' => '{{WRAPPER}}:hover > .elementor-element-populated > .elementor-background-overlay',
443 ]
444 );
445
446 $this->add_control(
447 'background_overlay_hover_opacity',
448 [
449 'label' => esc_html__( 'Opacity', 'elementor' ),
450 'type' => Controls_Manager::SLIDER,
451 'default' => [
452 'size' => .5,
453 ],
454 'range' => [
455 'px' => [
456 'max' => 1,
457 'step' => 0.01,
458 ],
459 ],
460 'selectors' => [
461 '{{WRAPPER}}:hover > .elementor-element-populated > .elementor-background-overlay' => 'opacity: {{SIZE}};',
462 ],
463 'condition' => [
464 'background_overlay_hover_background' => [ 'classic', 'gradient' ],
465 ],
466 ]
467 );
468
469 $this->add_group_control(
470 Group_Control_Css_Filter::get_type(),
471 [
472 'name' => 'css_filters_hover',
473 'selector' => '{{WRAPPER}}:hover > .elementor-element-populated > .elementor-background-overlay',
474 ]
475 );
476
477 $this->add_control(
478 'background_overlay_hover_transition',
479 [
480 'label' => esc_html__( 'Transition Duration', 'elementor' ),
481 'type' => Controls_Manager::SLIDER,
482 'default' => [
483 'size' => 0.3,
484 ],
485 'range' => [
486 'px' => [
487 'max' => 3,
488 'step' => 0.1,
489 ],
490 ],
491 'render_type' => 'ui',
492 'separator' => 'before',
493 ]
494 );
495
496 $this->end_controls_tab();
497
498 $this->end_controls_tabs();
499
500 $this->end_controls_section();
501
502 $this->start_controls_section(
503 'section_border',
504 [
505 'label' => esc_html__( 'Border', 'elementor' ),
506 'tab' => Controls_Manager::TAB_STYLE,
507 ]
508 );
509
510 $this->start_controls_tabs( 'tabs_border' );
511
512 $this->start_controls_tab(
513 'tab_border_normal',
514 [
515 'label' => esc_html__( 'Normal', 'elementor' ),
516 ]
517 );
518
519 $this->add_group_control(
520 Group_Control_Border::get_type(),
521 [
522 'name' => 'border',
523 'selector' => '{{WRAPPER}} > .elementor-element-populated',
524 ]
525 );
526
527 $this->add_responsive_control(
528 'border_radius',
529 [
530 'label' => esc_html__( 'Border Radius', 'elementor' ),
531 'type' => Controls_Manager::DIMENSIONS,
532 'size_units' => [ 'px', '%' ],
533 'selectors' => [
534 '{{WRAPPER}} > .elementor-element-populated, {{WRAPPER}} > .elementor-element-populated > .elementor-background-overlay, {{WRAPPER}} > .elementor-background-slideshow' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
535 ],
536 ]
537 );
538
539 $this->add_group_control(
540 Group_Control_Box_Shadow::get_type(),
541 [
542 'name' => 'box_shadow',
543 'selector' => '{{WRAPPER}} > .elementor-element-populated',
544 ]
545 );
546
547 $this->end_controls_tab();
548
549 $this->start_controls_tab(
550 'tab_border_hover',
551 [
552 'label' => esc_html__( 'Hover', 'elementor' ),
553 ]
554 );
555
556 $this->add_group_control(
557 Group_Control_Border::get_type(),
558 [
559 'name' => 'border_hover',
560 'selector' => '{{WRAPPER}}:hover > .elementor-element-populated',
561 ]
562 );
563
564 $this->add_responsive_control(
565 'border_radius_hover',
566 [
567 'label' => esc_html__( 'Border Radius', 'elementor' ),
568 'type' => Controls_Manager::DIMENSIONS,
569 'size_units' => [ 'px', '%' ],
570 'selectors' => [
571 '{{WRAPPER}}:hover > .elementor-element-populated, {{WRAPPER}}:hover > .elementor-element-populated > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
572 ],
573 ]
574 );
575
576 $this->add_group_control(
577 Group_Control_Box_Shadow::get_type(),
578 [
579 'name' => 'box_shadow_hover',
580 'selector' => '{{WRAPPER}}:hover > .elementor-element-populated',
581 ]
582 );
583
584 $this->add_control(
585 'border_hover_transition',
586 [
587 'label' => esc_html__( 'Transition Duration', 'elementor' ),
588 'type' => Controls_Manager::SLIDER,
589 'separator' => 'before',
590 'default' => [
591 'size' => 0.3,
592 ],
593 'range' => [
594 'px' => [
595 'max' => 3,
596 'step' => 0.1,
597 ],
598 ],
599 'conditions' => [
600 'relation' => 'or',
601 'terms' => [
602 [
603 'name' => 'background_background',
604 'operator' => '!==',
605 'value' => '',
606 ],
607 [
608 'name' => 'border_border',
609 'operator' => '!==',
610 'value' => '',
611 ],
612 ],
613 ],
614 'selectors' => [
615 '{{WRAPPER}} > .elementor-element-populated' => 'transition: background {{background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s',
616 '{{WRAPPER}} > .elementor-element-populated > .elementor-background-overlay' => 'transition: background {{background_overlay_hover_transition.SIZE}}s, border-radius {{SIZE}}s, opacity {{background_overlay_hover_transition.SIZE}}s',
617 ],
618 ]
619 );
620
621 $this->end_controls_tab();
622
623 $this->end_controls_tabs();
624
625 $this->end_controls_section();
626
627 // Section Typography.
628 $this->start_controls_section(
629 'section_typo',
630 [
631 'label' => esc_html__( 'Typography', 'elementor' ),
632 'type' => Controls_Manager::SECTION,
633 'tab' => Controls_Manager::TAB_STYLE,
634 ]
635 );
636
637 $this->add_control(
638 'heading_color',
639 [
640 'label' => esc_html__( 'Heading Color', 'elementor' ),
641 'type' => Controls_Manager::COLOR,
642 'default' => '',
643 'selectors' => [
644 '{{WRAPPER}} .elementor-element-populated .elementor-heading-title' => 'color: {{VALUE}};',
645 ],
646 'separator' => 'none',
647 ]
648 );
649
650 $this->add_control(
651 'color_text',
652 [
653 'label' => esc_html__( 'Text Color', 'elementor' ),
654 'type' => Controls_Manager::COLOR,
655 'default' => '',
656 'selectors' => [
657 '{{WRAPPER}} > .elementor-element-populated' => 'color: {{VALUE}};',
658 ],
659 ]
660 );
661
662 $this->add_control(
663 'color_link',
664 [
665 'label' => esc_html__( 'Link Color', 'elementor' ),
666 'type' => Controls_Manager::COLOR,
667 'default' => '',
668 'selectors' => [
669 '{{WRAPPER}} .elementor-element-populated a' => 'color: {{VALUE}};',
670 ],
671 ]
672 );
673
674 $this->add_control(
675 'color_link_hover',
676 [
677 'label' => esc_html__( 'Link Hover Color', 'elementor' ),
678 'type' => Controls_Manager::COLOR,
679 'default' => '',
680 'selectors' => [
681 '{{WRAPPER}} .elementor-element-populated a:hover' => 'color: {{VALUE}};',
682 ],
683 ]
684 );
685
686 $this->add_control(
687 'text_align',
688 [
689 'label' => esc_html__( 'Text Align', 'elementor' ),
690 'type' => Controls_Manager::CHOOSE,
691 'options' => [
692 'left' => [
693 'title' => esc_html__( 'Left', 'elementor' ),
694 'icon' => 'eicon-text-align-left',
695 ],
696 'center' => [
697 'title' => esc_html__( 'Center', 'elementor' ),
698 'icon' => 'eicon-text-align-center',
699 ],
700 'right' => [
701 'title' => esc_html__( 'Right', 'elementor' ),
702 'icon' => 'eicon-text-align-right',
703 ],
704 'justify' => [
705 'title' => __( 'Justified', 'elementor' ),
706 'icon' => 'eicon-text-align-justify',
707 ],
708 ],
709 'selectors' => [
710 '{{WRAPPER}} > .elementor-element-populated' => 'text-align: {{VALUE}};',
711 ],
712 ]
713 );
714
715 $this->end_controls_section();
716
717 // Section Advanced.
718 $this->start_controls_section(
719 'section_advanced',
720 [
721 'label' => esc_html__( 'Advanced', 'elementor' ),
722 'type' => Controls_Manager::SECTION,
723 'tab' => Controls_Manager::TAB_ADVANCED,
724 ]
725 );
726
727 $this->add_responsive_control(
728 'margin',
729 [
730 'label' => esc_html__( 'Margin', 'elementor' ),
731 'type' => Controls_Manager::DIMENSIONS,
732 'size_units' => [ 'px', 'em', '%', 'rem' ],
733 'selectors' => [
734 '{{WRAPPER}} > .elementor-element-populated' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};
735 --e-column-margin-right: {{RIGHT}}{{UNIT}}; --e-column-margin-left: {{LEFT}}{{UNIT}};',
736 ],
737 ]
738 );
739
740 $padding_selector = '{{WRAPPER}} > .elementor-element-populated';
741
742 if ( ! $is_dome_optimization_active ) {
743 $padding_selector .= ' > .elementor-widget-wrap';
744 }
745
746 $this->add_responsive_control(
747 'padding',
748 [
749 'label' => esc_html__( 'Padding', 'elementor' ),
750 'type' => Controls_Manager::DIMENSIONS,
751 'size_units' => [ 'px', 'em', '%', 'rem' ],
752 'selectors' => [
753 $padding_selector => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
754 ],
755 ]
756 );
757
758 $this->add_responsive_control(
759 'z_index',
760 [
761 'label' => esc_html__( 'Z-Index', 'elementor' ),
762 'type' => Controls_Manager::NUMBER,
763 'min' => 0,
764 'selectors' => [
765 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
766 ],
767 ]
768 );
769
770 $this->add_control(
771 '_element_id',
772 [
773 'label' => esc_html__( 'CSS ID', 'elementor' ),
774 'type' => Controls_Manager::TEXT,
775 'default' => '',
776 'dynamic' => [
777 'active' => true,
778 ],
779 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
780 'style_transfer' => false,
781 'classes' => 'elementor-control-direction-ltr',
782 ]
783 );
784
785 $this->add_control(
786 'css_classes',
787 [
788 'label' => esc_html__( 'CSS Classes', 'elementor' ),
789 'type' => Controls_Manager::TEXT,
790 'default' => '',
791 'dynamic' => [
792 'active' => true,
793 ],
794 'prefix_class' => '',
795 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
796 'classes' => 'elementor-control-direction-ltr',
797 ]
798 );
799
800 // TODO: Backward comparability for deprecated controls
801 $this->add_control(
802 'screen_sm',
803 [
804 'type' => Controls_Manager::HIDDEN,
805 ]
806 );
807
808 $this->add_control(
809 'screen_sm_width',
810 [
811 'type' => Controls_Manager::HIDDEN,
812 'condition' => [
813 'screen_sm' => [ 'custom' ],
814 ],
815 'prefix_class' => 'elementor-sm-',
816 ]
817 );
818 // END Backward comparability
819
820 $this->end_controls_section();
821
822 $this->start_controls_section(
823 'section_effects',
824 [
825 'label' => esc_html__( 'Motion Effects', 'elementor' ),
826 'tab' => Controls_Manager::TAB_ADVANCED,
827 ]
828 );
829
830 $this->add_responsive_control(
831 'animation',
832 [
833 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
834 'type' => Controls_Manager::ANIMATION,
835 'frontend_available' => true,
836 ]
837 );
838
839 $this->add_control(
840 'animation_duration',
841 [
842 'label' => esc_html__( 'Animation Duration', 'elementor' ),
843 'type' => Controls_Manager::SELECT,
844 'default' => '',
845 'options' => [
846 'slow' => esc_html__( 'Slow', 'elementor' ),
847 '' => esc_html__( 'Normal', 'elementor' ),
848 'fast' => esc_html__( 'Fast', 'elementor' ),
849 ],
850 'prefix_class' => 'animated-',
851 'condition' => [
852 'animation!' => '',
853 ],
854 ]
855 );
856
857 $this->add_control(
858 'animation_delay',
859 [
860 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
861 'type' => Controls_Manager::NUMBER,
862 'default' => '',
863 'min' => 0,
864 'step' => 100,
865 'condition' => [
866 'animation!' => '',
867 ],
868 'render_type' => 'none',
869 'frontend_available' => true,
870 ]
871 );
872
873 $this->end_controls_section();
874
875 $this->start_controls_section(
876 '_section_responsive',
877 [
878 'label' => esc_html__( 'Responsive', 'elementor' ),
879 'tab' => Controls_Manager::TAB_ADVANCED,
880 ]
881 );
882
883 $this->add_control(
884 'responsive_description',
885 [
886 'raw' => esc_html__( 'Responsive visibility will take effect only on preview or live page, and not while editing in Elementor.', 'elementor' ),
887 'type' => Controls_Manager::RAW_HTML,
888 'content_classes' => 'elementor-descriptor',
889 ]
890 );
891
892 $this->add_hidden_device_controls();
893
894 $this->end_controls_section();
895
896 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
897
898 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
899 }
900
901 /**
902 * Render column output in the editor.
903 *
904 * Used to generate the live preview, using a Backbone JavaScript template.
905 *
906 * @since 2.9.0
907 * @access protected
908 */
909 protected function content_template() {
910 $is_dom_optimization_active = Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' );
911 $wrapper_element = $is_dom_optimization_active ? 'widget' : 'column';
912
913 ?>
914 <div class="elementor-<?php echo esc_attr( $wrapper_element ); ?>-wrap">
915 <div class="elementor-background-overlay"></div>
916 <?php if ( ! $is_dom_optimization_active ) { ?>
917 <div class="elementor-widget-wrap"></div>
918 <?php } ?>
919 </div>
920 <?php
921 }
922
923 /**
924 * Before column rendering.
925 *
926 * Used to add stuff before the column element.
927 *
928 * @since 1.0.0
929 * @access public
930 */
931 public function before_render() {
932 $settings = $this->get_settings_for_display();
933
934 $has_background_overlay = in_array( $settings['background_overlay_background'], [ 'classic', 'gradient' ], true ) ||
935 in_array( $settings['background_overlay_hover_background'], [ 'classic', 'gradient' ], true );
936
937 $is_dom_optimization_active = Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' );
938 $wrapper_attribute_string = $is_dom_optimization_active ? '_widget_wrapper' : '_inner_wrapper';
939
940 $column_wrap_classes = $is_dom_optimization_active ? [ 'elementor-widget-wrap' ] : [ 'elementor-column-wrap' ];
941
942 if ( $this->get_children() ) {
943 $column_wrap_classes[] = 'elementor-element-populated';
944 }
945
946 $this->add_render_attribute( [
947 '_inner_wrapper' => [
948 'class' => $column_wrap_classes,
949 ],
950 '_widget_wrapper' => [
951 'class' => $is_dom_optimization_active ? $column_wrap_classes : 'elementor-widget-wrap',
952 ],
953 '_background_overlay' => [
954 'class' => [ 'elementor-background-overlay' ],
955 ],
956 ] );
957 ?>
958 <<?php
959 // PHPCS - the method get_html_tag is safe.
960 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
961 ?> <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
962 <div <?php $this->print_render_attribute_string( $wrapper_attribute_string ); ?>>
963 <?php if ( $has_background_overlay ) : ?>
964 <div <?php $this->print_render_attribute_string( '_background_overlay' ); ?>></div>
965 <?php endif; ?>
966 <?php if ( ! $is_dom_optimization_active ) : ?>
967 <div <?php $this->print_render_attribute_string( '_widget_wrapper' ); ?>>
968 <?php endif; ?>
969 <?php
970 }
971
972 /**
973 * After column rendering.
974 *
975 * Used to add stuff after the column element.
976 *
977 * @since 1.0.0
978 * @access public
979 */
980 public function after_render() {
981 if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
982 </div>
983 <?php } ?>
984 </div>
985 </<?php
986 // PHPCS - the method get_html_tag is safe.
987 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
988 <?php
989 }
990
991 /**
992 * Add column render attributes.
993 *
994 * Used to add attributes to the current column wrapper HTML tag.
995 *
996 * @since 1.3.0
997 * @access protected
998 */
999 protected function add_render_attributes() {
1000
1001 $is_inner = $this->get_data( 'isInner' );
1002
1003 $column_type = ! empty( $is_inner ) ? 'inner' : 'top';
1004
1005 $settings = $this->get_settings();
1006
1007 $this->add_render_attribute(
1008 '_wrapper', 'class', [
1009 'elementor-column',
1010 'elementor-col-' . $settings['_column_size'],
1011 'elementor-' . $column_type . '-column',
1012 ]
1013 );
1014
1015 parent::add_render_attributes();
1016 }
1017
1018 /**
1019 * Get default child type.
1020 *
1021 * Retrieve the column child type based on element data.
1022 *
1023 * @since 1.0.0
1024 * @access protected
1025 *
1026 * @param array $element_data Element ID.
1027 *
1028 * @return Element_Base|false Column default child type.
1029 */
1030 protected function _get_default_child_type( array $element_data ) {
1031 if ( 'section' === $element_data['elType'] ) {
1032 return Plugin::$instance->elements_manager->get_element_types( 'section' );
1033 }
1034
1035 if ( 'container' === $element_data['elType'] ) {
1036 return Plugin::$instance->elements_manager->get_element_types( 'container' );
1037 }
1038
1039 // If the element doesn't exists (disabled element, experiment, etc.), return false to prevent errors.
1040 if ( empty( $element_data['widgetType'] ) ) {
1041 return false;
1042 }
1043
1044 return Plugin::$instance->widgets_manager->get_widget_types( $element_data['widgetType'] );
1045 }
1046
1047 /**
1048 * Get HTML tag.
1049 *
1050 * Retrieve the column element HTML tag.
1051 *
1052 * @since 1.5.3
1053 * @access private
1054 *
1055 * @return string Column HTML tag.
1056 */
1057 private function get_html_tag() {
1058 $html_tag = $this->get_settings( 'html_tag' );
1059
1060 if ( empty( $html_tag ) ) {
1061 $html_tag = 'div';
1062 }
1063
1064 return Utils::validate_html_tag( $html_tag );
1065 }
1066 }
1067