PluginProbe
Elementor Website Builder – more than just a page builder / 3.4.0
Elementor Website Builder – more than just a page builder v3.4.0
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 / includes / elements / column.php

column.php in Elementor Website Builder – more than just a page builder 3.4.0, at includes/elements/column.php

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