PluginProbe
Elementor Website Builder – more than just a page builder / 3.2.4
Elementor Website Builder – more than just a page builder v3.2.4
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 / section.php

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

1,604 lines 37.1 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 if ( ! defined( 'ABSPATH' ) ) {
5 exit; // Exit if accessed directly.
6 }
7
8 /**
9 * Elementor section element.
10 *
11 * Elementor section handler class is responsible for initializing the section
12 * element.
13 *
14 * @since 1.0.0
15 */
16 class Element_Section extends Element_Base {
17
18 /**
19 * Section predefined columns presets.
20 *
21 * Holds the predefined columns width for each columns count available by
22 * default by Elementor. Default is an empty array.
23 *
24 * Note that when the user creates a section he can define custom sizes for
25 * the columns. But Elementor sets default values for predefined columns.
26 *
27 * For example two columns 50% width each one, or three columns 33.33% each
28 * one. This property hold the data for those preset values.
29 *
30 * @since 1.0.0
31 * @access private
32 * @static
33 *
34 * @var array Section presets.
35 */
36 private static $presets = [];
37
38 /**
39 * Get element type.
40 *
41 * Retrieve the element type, in this case `section`.
42 *
43 * @since 2.1.0
44 * @access public
45 * @static
46 *
47 * @return string The type.
48 */
49 public static function get_type() {
50 return 'section';
51 }
52
53 /**
54 * Get section name.
55 *
56 * Retrieve the section name.
57 *
58 * @since 1.0.0
59 * @access public
60 *
61 * @return string Section name.
62 */
63 public function get_name() {
64 return 'section';
65 }
66
67 /**
68 * Get section title.
69 *
70 * Retrieve the section title.
71 *
72 * @since 1.0.0
73 * @access public
74 *
75 * @return string Section title.
76 */
77 public function get_title() {
78 return __( 'Section', 'elementor' );
79 }
80
81 /**
82 * Get section icon.
83 *
84 * Retrieve the section icon.
85 *
86 * @since 1.0.0
87 * @access public
88 *
89 * @return string Section icon.
90 */
91 public function get_icon() {
92 return 'eicon-columns';
93 }
94
95 /**
96 * Get presets.
97 *
98 * Retrieve a specific preset columns for a given columns count, or a list
99 * of all the preset if no parameters passed.
100 *
101 * @since 1.0.0
102 * @access public
103 * @static
104 *
105 * @param int $columns_count Optional. Columns count. Default is null.
106 * @param int $preset_index Optional. Preset index. Default is null.
107 *
108 * @return array Section presets.
109 */
110 public static function get_presets( $columns_count = null, $preset_index = null ) {
111 if ( ! self::$presets ) {
112 self::init_presets();
113 }
114
115 $presets = self::$presets;
116
117 if ( null !== $columns_count ) {
118 $presets = $presets[ $columns_count ];
119 }
120
121 if ( null !== $preset_index ) {
122 $presets = $presets[ $preset_index ];
123 }
124
125 return $presets;
126 }
127
128 /**
129 * Initialize presets.
130 *
131 * Initializing the section presets and set the number of columns the
132 * section can have by default. For example a column can have two columns
133 * 50% width each one, or three columns 33.33% each one.
134 *
135 * Note that Elementor sections have default section presets but the user
136 * can set custom number of columns and define custom sizes for each column.
137
138 * @since 1.0.0
139 * @access public
140 * @static
141 */
142 public static function init_presets() {
143 $additional_presets = [
144 2 => [
145 [
146 'preset' => [ 33, 66 ],
147 ],
148 [
149 'preset' => [ 66, 33 ],
150 ],
151 ],
152 3 => [
153 [
154 'preset' => [ 25, 25, 50 ],
155 ],
156 [
157 'preset' => [ 50, 25, 25 ],
158 ],
159 [
160 'preset' => [ 25, 50, 25 ],
161 ],
162 [
163 'preset' => [ 16, 66, 16 ],
164 ],
165 ],
166 ];
167
168 foreach ( range( 1, 10 ) as $columns_count ) {
169 self::$presets[ $columns_count ] = [
170 [
171 'preset' => [],
172 ],
173 ];
174
175 $preset_unit = floor( 1 / $columns_count * 100 );
176
177 for ( $i = 0; $i < $columns_count; $i++ ) {
178 self::$presets[ $columns_count ][0]['preset'][] = $preset_unit;
179 }
180
181 if ( ! empty( $additional_presets[ $columns_count ] ) ) {
182 self::$presets[ $columns_count ] = array_merge( self::$presets[ $columns_count ], $additional_presets[ $columns_count ] );
183 }
184
185 foreach ( self::$presets[ $columns_count ] as $preset_index => & $preset ) {
186 $preset['key'] = $columns_count . $preset_index;
187 }
188 }
189 }
190
191 /**
192 * Get initial config.
193 *
194 * Retrieve the current section initial configuration.
195 *
196 * Adds more configuration on top of the controls list, the tabs assigned to
197 * the control, element name, type, icon and more. This method also adds
198 * section presets.
199 *
200 * @since 2.9.0
201 * @access protected
202 *
203 * @return array The initial config.
204 */
205 protected function get_initial_config() {
206 $config = parent::get_initial_config();
207
208 $config['presets'] = self::get_presets();
209 $config['controls'] = $this->get_controls();
210 $config['tabs_controls'] = $this->get_tabs_controls();
211
212 return $config;
213 }
214
215 /**
216 * Register section controls.
217 *
218 * Used to add new controls to the section element.
219 *
220 * @since 3.1.0
221 * @access protected
222 */
223 protected function register_controls() {
224 $this->start_controls_section(
225 'section_layout',
226 [
227 'label' => __( 'Layout', 'elementor' ),
228 'tab' => Controls_Manager::TAB_LAYOUT,
229 ]
230 );
231
232 // Element Name for the Navigator
233 $this->add_control(
234 '_title',
235 [
236 'label' => __( 'Title', 'elementor' ),
237 'type' => Controls_Manager::HIDDEN,
238 'render_type' => 'none',
239 ]
240 );
241
242 $this->add_control(
243 'layout',
244 [
245 'label' => __( 'Content Width', 'elementor' ),
246 'type' => Controls_Manager::SELECT,
247 'default' => 'boxed',
248 'options' => [
249 'boxed' => __( 'Boxed', 'elementor' ),
250 'full_width' => __( 'Full Width', 'elementor' ),
251 ],
252 'prefix_class' => 'elementor-section-',
253 ]
254 );
255
256 $this->add_control(
257 'content_width',
258 [
259 'label' => __( 'Content Width', 'elementor' ),
260 'type' => Controls_Manager::SLIDER,
261 'range' => [
262 'px' => [
263 'min' => 500,
264 'max' => 1600,
265 ],
266 ],
267 'selectors' => [
268 '{{WRAPPER}} > .elementor-container' => 'max-width: {{SIZE}}{{UNIT}};',
269 ],
270 'condition' => [
271 'layout' => [ 'boxed' ],
272 ],
273 'show_label' => false,
274 'separator' => 'none',
275 ]
276 );
277
278 $this->add_control(
279 'gap',
280 [
281 'label' => __( 'Columns Gap', 'elementor' ),
282 'type' => Controls_Manager::SELECT,
283 'default' => 'default',
284 'options' => [
285 'default' => __( 'Default', 'elementor' ),
286 'no' => __( 'No Gap', 'elementor' ),
287 'narrow' => __( 'Narrow', 'elementor' ),
288 'extended' => __( 'Extended', 'elementor' ),
289 'wide' => __( 'Wide', 'elementor' ),
290 'wider' => __( 'Wider', 'elementor' ),
291 'custom' => __( 'Custom', 'elementor' ),
292 ],
293 ]
294 );
295
296 $this->add_responsive_control(
297 'gap_columns_custom',
298 [
299 'label' => __( 'Custom Columns Gap', 'elementor' ),
300 'type' => Controls_Manager::SLIDER,
301 'range' => [
302 'px' => [
303 'min' => 0,
304 'max' => 500,
305 ],
306 '%' => [
307 'min' => 0,
308 'max' => 100,
309 ],
310 'vh' => [
311 'min' => 0,
312 'max' => 100,
313 ],
314 'vw' => [
315 'min' => 0,
316 'max' => 100,
317 ],
318 ],
319 'size_units' => [ 'px', '%', 'vh', 'vw' ],
320 'selectors' => [
321 '{{WRAPPER}} .elementor-column-gap-custom .elementor-column > .elementor-element-populated' => 'padding: {{SIZE}}{{UNIT}};',
322 ],
323 'condition' => [
324 'gap' => 'custom',
325 ],
326 ]
327 );
328
329 $this->add_control(
330 'height',
331 [
332 'label' => __( 'Height', 'elementor' ),
333 'type' => Controls_Manager::SELECT,
334 'default' => 'default',
335 'options' => [
336 'default' => __( 'Default', 'elementor' ),
337 'full' => __( 'Fit To Screen', 'elementor' ),
338 'min-height' => __( 'Min Height', 'elementor' ),
339 ],
340 'prefix_class' => 'elementor-section-height-',
341 'hide_in_inner' => true,
342 ]
343 );
344
345 $this->add_responsive_control(
346 'custom_height',
347 [
348 'label' => __( 'Minimum Height', 'elementor' ),
349 'type' => Controls_Manager::SLIDER,
350 'default' => [
351 'size' => 400,
352 ],
353 'range' => [
354 'px' => [
355 'min' => 0,
356 'max' => 1440,
357 ],
358 'vh' => [
359 'min' => 0,
360 'max' => 100,
361 ],
362 'vw' => [
363 'min' => 0,
364 'max' => 100,
365 ],
366 ],
367 'size_units' => [ 'px', 'vh', 'vw' ],
368 'selectors' => [
369 '{{WRAPPER}} > .elementor-container' => 'min-height: {{SIZE}}{{UNIT}};',
370 ],
371 'condition' => [
372 'height' => [ 'min-height' ],
373 ],
374 'hide_in_inner' => true,
375 ]
376 );
377
378 $this->add_control(
379 'height_inner',
380 [
381 'label' => __( 'Height', 'elementor' ),
382 'type' => Controls_Manager::SELECT,
383 'default' => 'default',
384 'options' => [
385 'default' => __( 'Default', 'elementor' ),
386 'full' => __( 'Fit To Screen', 'elementor' ),
387 'min-height' => __( 'Min Height', 'elementor' ),
388 ],
389 'prefix_class' => 'elementor-section-height-',
390 'hide_in_top' => true,
391 ]
392 );
393
394 $this->add_responsive_control(
395 'custom_height_inner',
396 [
397 'label' => __( 'Minimum Height', 'elementor' ),
398 'type' => Controls_Manager::SLIDER,
399 'default' => [
400 'size' => 400,
401 ],
402 'range' => [
403 'px' => [
404 'min' => 0,
405 'max' => 1440,
406 ],
407 ],
408 'selectors' => [
409 '{{WRAPPER}} > .elementor-container' => 'min-height: {{SIZE}}{{UNIT}};',
410 ],
411 'condition' => [
412 'height_inner' => [ 'min-height' ],
413 ],
414 'size_units' => [ 'px', 'vh', 'vw' ],
415 'hide_in_top' => true,
416 ]
417 );
418
419 $this->add_control(
420 'column_position',
421 [
422 'label' => __( 'Column Position', 'elementor' ),
423 'type' => Controls_Manager::SELECT,
424 'default' => 'middle',
425 'options' => [
426 'stretch' => __( 'Stretch', 'elementor' ),
427 'top' => __( 'Top', 'elementor' ),
428 'middle' => __( 'Middle', 'elementor' ),
429 'bottom' => __( 'Bottom', 'elementor' ),
430 ],
431 'prefix_class' => 'elementor-section-items-',
432 'condition' => [
433 'height' => [ 'full', 'min-height' ],
434 ],
435 ]
436 );
437
438 $content_position_selector = Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ?
439 '{{WRAPPER}} > .elementor-container > .elementor-column > .elementor-widget-wrap' :
440 '{{WRAPPER}} > .elementor-container > .elementor-row > .elementor-column > .elementor-column-wrap > .elementor-widget-wrap';
441
442 $this->add_control(
443 'content_position',
444 [
445 'label' => __( 'Vertical Align', 'elementor' ),
446 'type' => Controls_Manager::SELECT,
447 'default' => '',
448 'options' => [
449 '' => __( 'Default', 'elementor' ),
450 'top' => __( 'Top', 'elementor' ),
451 'middle' => __( 'Middle', 'elementor' ),
452 'bottom' => __( 'Bottom', 'elementor' ),
453 'space-between' => __( 'Space Between', 'elementor' ),
454 'space-around' => __( 'Space Around', 'elementor' ),
455 'space-evenly' => __( 'Space Evenly', 'elementor' ),
456 ],
457 'selectors_dictionary' => [
458 'top' => 'flex-start',
459 'middle' => 'center',
460 'bottom' => 'flex-end',
461 ],
462 'selectors' => [
463 $content_position_selector => 'align-content: {{VALUE}}; align-items: {{VALUE}};',
464 ],
465 // TODO: The following line is for BC since 2.7.0
466 'prefix_class' => 'elementor-section-content-',
467 ]
468 );
469
470 $this->add_control(
471 'overflow',
472 [
473 'label' => __( 'Overflow', 'elementor' ),
474 'type' => Controls_Manager::SELECT,
475 'default' => '',
476 'options' => [
477 '' => __( 'Default', 'elementor' ),
478 'hidden' => __( 'Hidden', 'elementor' ),
479 ],
480 'selectors' => [
481 '{{WRAPPER}}' => 'overflow: {{VALUE}}',
482 ],
483 ]
484 );
485
486 $this->add_control(
487 'stretch_section',
488 [
489 'label' => __( 'Stretch Section', 'elementor' ),
490 'type' => Controls_Manager::SWITCHER,
491 'default' => '',
492 'return_value' => 'section-stretched',
493 'prefix_class' => 'elementor-',
494 'hide_in_inner' => true,
495 'description' => __( 'Stretch the section to the full width of the page using JS.', 'elementor' ) . sprintf( ' <a href="%1$s" target="_blank">%2$s</a>', 'https://go.elementor.com/stretch-section/', __( 'Learn more.', 'elementor' ) ),
496 'render_type' => 'none',
497 'frontend_available' => true,
498 ]
499 );
500
501 $possible_tags = [
502 'div',
503 'header',
504 'footer',
505 'main',
506 'article',
507 'section',
508 'aside',
509 'nav',
510 ];
511
512 $options = [
513 '' => __( 'Default', 'elementor' ),
514 ] + array_combine( $possible_tags, $possible_tags );
515
516 $this->add_control(
517 'html_tag',
518 [
519 'label' => __( 'HTML Tag', 'elementor' ),
520 'type' => Controls_Manager::SELECT,
521 'options' => $options,
522 'separator' => 'before',
523 ]
524 );
525
526 $this->end_controls_section();
527
528 // Section Structure
529 $this->start_controls_section(
530 'section_structure',
531 [
532 'label' => __( 'Structure', 'elementor' ),
533 'tab' => Controls_Manager::TAB_LAYOUT,
534 ]
535 );
536
537 $this->add_control(
538 'structure',
539 [
540 'label' => __( 'Structure', 'elementor' ),
541 'type' => Controls_Manager::STRUCTURE,
542 'default' => '10',
543 'render_type' => 'none',
544 'style_transfer' => false,
545 ]
546 );
547
548 $this->end_controls_section();
549
550 // Section background
551 $this->start_controls_section(
552 'section_background',
553 [
554 'label' => __( 'Background', 'elementor' ),
555 'tab' => Controls_Manager::TAB_STYLE,
556 ]
557 );
558
559 $this->start_controls_tabs( 'tabs_background' );
560
561 $this->start_controls_tab(
562 'tab_background_normal',
563 [
564 'label' => __( 'Normal', 'elementor' ),
565 ]
566 );
567
568 $this->add_group_control(
569 Group_Control_Background::get_type(),
570 [
571 'name' => 'background',
572 'types' => [ 'classic', 'gradient', 'video', 'slideshow' ],
573 'fields_options' => [
574 'background' => [
575 'frontend_available' => true,
576 ],
577 ],
578 ]
579 );
580
581 $this->end_controls_tab();
582
583 $this->start_controls_tab(
584 'tab_background_hover',
585 [
586 'label' => __( 'Hover', 'elementor' ),
587 ]
588 );
589
590 $this->add_group_control(
591 Group_Control_Background::get_type(),
592 [
593 'name' => 'background_hover',
594 'selector' => '{{WRAPPER}}:hover',
595 ]
596 );
597
598 $this->add_control(
599 'background_hover_transition',
600 [
601 'label' => __( 'Transition Duration', 'elementor' ),
602 'type' => Controls_Manager::SLIDER,
603 'default' => [
604 'size' => 0.3,
605 ],
606 'range' => [
607 'px' => [
608 'max' => 3,
609 'step' => 0.1,
610 ],
611 ],
612 'render_type' => 'ui',
613 'separator' => 'before',
614 ]
615 );
616
617 $this->end_controls_tab();
618
619 $this->end_controls_tabs();
620
621 $this->end_controls_section();
622
623 // Background Overlay
624 $this->start_controls_section(
625 'section_background_overlay',
626 [
627 'label' => __( 'Background Overlay', 'elementor' ),
628 'tab' => Controls_Manager::TAB_STYLE,
629 ]
630 );
631
632 $this->start_controls_tabs( 'tabs_background_overlay' );
633
634 $this->start_controls_tab(
635 'tab_background_overlay_normal',
636 [
637 'label' => __( 'Normal', 'elementor' ),
638 ]
639 );
640
641 $this->add_group_control(
642 Group_Control_Background::get_type(),
643 [
644 'name' => 'background_overlay',
645 'selector' => '{{WRAPPER}} > .elementor-background-overlay',
646 ]
647 );
648
649 $this->add_control(
650 'background_overlay_opacity',
651 [
652 'label' => __( 'Opacity', 'elementor' ),
653 'type' => Controls_Manager::SLIDER,
654 'default' => [
655 'size' => .5,
656 ],
657 'range' => [
658 'px' => [
659 'max' => 1,
660 'step' => 0.01,
661 ],
662 ],
663 'selectors' => [
664 '{{WRAPPER}} > .elementor-background-overlay' => 'opacity: {{SIZE}};',
665 ],
666 'condition' => [
667 'background_overlay_background' => [ 'classic', 'gradient' ],
668 ],
669 ]
670 );
671
672 $this->add_group_control(
673 Group_Control_Css_Filter::get_type(),
674 [
675 'name' => 'css_filters',
676 'selector' => '{{WRAPPER}} .elementor-background-overlay',
677 'conditions' => [
678 'relation' => 'or',
679 'terms' => [
680 [
681 'name' => 'background_overlay_image[url]',
682 'operator' => '!==',
683 'value' => '',
684 ],
685 [
686 'name' => 'background_overlay_color',
687 'operator' => '!==',
688 'value' => '',
689 ],
690 ],
691 ],
692 ]
693 );
694
695 $this->add_control(
696 'overlay_blend_mode',
697 [
698 'label' => __( 'Blend Mode', 'elementor' ),
699 'type' => Controls_Manager::SELECT,
700 'options' => [
701 '' => __( 'Normal', 'elementor' ),
702 'multiply' => 'Multiply',
703 'screen' => 'Screen',
704 'overlay' => 'Overlay',
705 'darken' => 'Darken',
706 'lighten' => 'Lighten',
707 'color-dodge' => 'Color Dodge',
708 'saturation' => 'Saturation',
709 'color' => 'Color',
710 'luminosity' => 'Luminosity',
711 ],
712 'selectors' => [
713 '{{WRAPPER}} > .elementor-background-overlay' => 'mix-blend-mode: {{VALUE}}',
714 ],
715 'conditions' => [
716 'relation' => 'or',
717 'terms' => [
718 [
719 'name' => 'background_overlay_image[url]',
720 'operator' => '!==',
721 'value' => '',
722 ],
723 [
724 'name' => 'background_overlay_color',
725 'operator' => '!==',
726 'value' => '',
727 ],
728 ],
729 ],
730 ]
731 );
732
733 $this->end_controls_tab();
734
735 $this->start_controls_tab(
736 'tab_background_overlay_hover',
737 [
738 'label' => __( 'Hover', 'elementor' ),
739 ]
740 );
741
742 $this->add_group_control(
743 Group_Control_Background::get_type(),
744 [
745 'name' => 'background_overlay_hover',
746 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
747 ]
748 );
749
750 $this->add_control(
751 'background_overlay_hover_opacity',
752 [
753 'label' => __( 'Opacity', 'elementor' ),
754 'type' => Controls_Manager::SLIDER,
755 'default' => [
756 'size' => .5,
757 ],
758 'range' => [
759 'px' => [
760 'max' => 1,
761 'step' => 0.01,
762 ],
763 ],
764 'selectors' => [
765 '{{WRAPPER}}:hover > .elementor-background-overlay' => 'opacity: {{SIZE}};',
766 ],
767 'condition' => [
768 'background_overlay_hover_background' => [ 'classic', 'gradient' ],
769 ],
770 ]
771 );
772
773 $this->add_group_control(
774 Group_Control_Css_Filter::get_type(),
775 [
776 'name' => 'css_filters_hover',
777 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
778 ]
779 );
780
781 $this->add_control(
782 'background_overlay_hover_transition',
783 [
784 'label' => __( 'Transition Duration', 'elementor' ),
785 'type' => Controls_Manager::SLIDER,
786 'default' => [
787 'size' => 0.3,
788 ],
789 'range' => [
790 'px' => [
791 'max' => 3,
792 'step' => 0.1,
793 ],
794 ],
795 'render_type' => 'ui',
796 'separator' => 'before',
797 ]
798 );
799
800 $this->end_controls_tab();
801
802 $this->end_controls_tabs();
803
804 $this->end_controls_section();
805
806 // Section border
807 $this->start_controls_section(
808 'section_border',
809 [
810 'label' => __( 'Border', 'elementor' ),
811 'tab' => Controls_Manager::TAB_STYLE,
812 ]
813 );
814
815 $this->start_controls_tabs( 'tabs_border' );
816
817 $this->start_controls_tab(
818 'tab_border_normal',
819 [
820 'label' => __( 'Normal', 'elementor' ),
821 ]
822 );
823
824 $this->add_group_control(
825 Group_Control_Border::get_type(),
826 [
827 'name' => 'border',
828 ]
829 );
830
831 $this->add_responsive_control(
832 'border_radius',
833 [
834 'label' => __( 'Border Radius', 'elementor' ),
835 'type' => Controls_Manager::DIMENSIONS,
836 'size_units' => [ 'px', '%' ],
837 'selectors' => [
838 '{{WRAPPER}}, {{WRAPPER}} > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
839 ],
840 ]
841 );
842
843 $this->add_group_control(
844 Group_Control_Box_Shadow::get_type(),
845 [
846 'name' => 'box_shadow',
847 ]
848 );
849
850 $this->end_controls_tab();
851
852 $this->start_controls_tab(
853 'tab_border_hover',
854 [
855 'label' => __( 'Hover', 'elementor' ),
856 ]
857 );
858
859 $this->add_group_control(
860 Group_Control_Border::get_type(),
861 [
862 'name' => 'border_hover',
863 'selector' => '{{WRAPPER}}:hover',
864 ]
865 );
866
867 $this->add_responsive_control(
868 'border_radius_hover',
869 [
870 'label' => __( 'Border Radius', 'elementor' ),
871 'type' => Controls_Manager::DIMENSIONS,
872 'size_units' => [ 'px', '%' ],
873 'selectors' => [
874 '{{WRAPPER}}:hover, {{WRAPPER}}:hover > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
875 ],
876 ]
877 );
878
879 $this->add_group_control(
880 Group_Control_Box_Shadow::get_type(),
881 [
882 'name' => 'box_shadow_hover',
883 'selector' => '{{WRAPPER}}:hover',
884 ]
885 );
886
887 $this->add_control(
888 'border_hover_transition',
889 [
890 'label' => __( 'Transition Duration', 'elementor' ),
891 'type' => Controls_Manager::SLIDER,
892 'separator' => 'before',
893 'default' => [
894 'size' => 0.3,
895 ],
896 'range' => [
897 'px' => [
898 'max' => 3,
899 'step' => 0.1,
900 ],
901 ],
902 'conditions' => [
903 'relation' => 'or',
904 'terms' => [
905 [
906 'name' => 'background_background',
907 'operator' => '!==',
908 'value' => '',
909 ],
910 [
911 'name' => 'border_border',
912 'operator' => '!==',
913 'value' => '',
914 ],
915 ],
916 ],
917 'selectors' => [
918 '{{WRAPPER}}' => 'transition: background {{background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s',
919 '{{WRAPPER}} > .elementor-background-overlay' => 'transition: background {{background_overlay_hover_transition.SIZE}}s, border-radius {{SIZE}}s, opacity {{background_overlay_hover_transition.SIZE}}s',
920 ],
921 ]
922 );
923
924 $this->end_controls_tab();
925
926 $this->end_controls_tabs();
927
928 $this->end_controls_section();
929
930 // Section Shape Divider
931 $this->start_controls_section(
932 'section_shape_divider',
933 [
934 'label' => __( 'Shape Divider', 'elementor' ),
935 'tab' => Controls_Manager::TAB_STYLE,
936 ]
937 );
938
939 $this->start_controls_tabs( 'tabs_shape_dividers' );
940
941 $shapes_options = [
942 '' => __( 'None', 'elementor' ),
943 ];
944
945 foreach ( Shapes::get_shapes() as $shape_name => $shape_props ) {
946 $shapes_options[ $shape_name ] = $shape_props['title'];
947 }
948
949 foreach ( [
950 'top' => __( 'Top', 'elementor' ),
951 'bottom' => __( 'Bottom', 'elementor' ),
952 ] as $side => $side_label ) {
953 $base_control_key = "shape_divider_$side";
954
955 $this->start_controls_tab(
956 "tab_$base_control_key",
957 [
958 'label' => $side_label,
959 ]
960 );
961
962 $this->add_control(
963 $base_control_key,
964 [
965 'label' => __( 'Type', 'elementor' ),
966 'type' => Controls_Manager::SELECT,
967 'options' => $shapes_options,
968 'render_type' => 'none',
969 'frontend_available' => true,
970 ]
971 );
972
973 $this->add_control(
974 $base_control_key . '_color',
975 [
976 'label' => __( 'Color', 'elementor' ),
977 'type' => Controls_Manager::COLOR,
978 'condition' => [
979 "shape_divider_$side!" => '',
980 ],
981 'selectors' => [
982 "{{WRAPPER}} > .elementor-shape-$side .elementor-shape-fill" => 'fill: {{UNIT}};',
983 ],
984 ]
985 );
986
987 $this->add_responsive_control(
988 $base_control_key . '_width',
989 [
990 'label' => __( 'Width', 'elementor' ),
991 'type' => Controls_Manager::SLIDER,
992 'default' => [
993 'unit' => '%',
994 ],
995 'tablet_default' => [
996 'unit' => '%',
997 ],
998 'mobile_default' => [
999 'unit' => '%',
1000 ],
1001 'range' => [
1002 '%' => [
1003 'min' => 100,
1004 'max' => 300,
1005 ],
1006 ],
1007 'condition' => [
1008 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'height_only', Shapes::FILTER_EXCLUDE ) ),
1009 ],
1010 'selectors' => [
1011 "{{WRAPPER}} > .elementor-shape-$side svg" => 'width: calc({{SIZE}}{{UNIT}} + 1.3px)',
1012 ],
1013 ]
1014 );
1015
1016 $this->add_responsive_control(
1017 $base_control_key . '_height',
1018 [
1019 'label' => __( 'Height', 'elementor' ),
1020 'type' => Controls_Manager::SLIDER,
1021 'range' => [
1022 'px' => [
1023 'max' => 500,
1024 ],
1025 ],
1026 'condition' => [
1027 "shape_divider_$side!" => '',
1028 ],
1029 'selectors' => [
1030 "{{WRAPPER}} > .elementor-shape-$side svg" => 'height: {{SIZE}}{{UNIT}};',
1031 ],
1032 ]
1033 );
1034
1035 $this->add_control(
1036 $base_control_key . '_flip',
1037 [
1038 'label' => __( 'Flip', 'elementor' ),
1039 'type' => Controls_Manager::SWITCHER,
1040 'condition' => [
1041 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_flip' ) ),
1042 ],
1043 'selectors' => [
1044 "{{WRAPPER}} > .elementor-shape-$side svg" => 'transform: translateX(-50%) rotateY(180deg)',
1045 ],
1046 ]
1047 );
1048
1049 $this->add_control(
1050 $base_control_key . '_negative',
1051 [
1052 'label' => __( 'Invert', 'elementor' ),
1053 'type' => Controls_Manager::SWITCHER,
1054 'frontend_available' => true,
1055 'condition' => [
1056 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_negative' ) ),
1057 ],
1058 'render_type' => 'none',
1059 ]
1060 );
1061
1062 $this->add_control(
1063 $base_control_key . '_above_content',
1064 [
1065 'label' => __( 'Bring to Front', 'elementor' ),
1066 'type' => Controls_Manager::SWITCHER,
1067 'selectors' => [
1068 "{{WRAPPER}} > .elementor-shape-$side" => 'z-index: 2; pointer-events: none',
1069 ],
1070 'condition' => [
1071 "shape_divider_$side!" => '',
1072 ],
1073 ]
1074 );
1075
1076 $this->end_controls_tab();
1077 }
1078
1079 $this->end_controls_tabs();
1080
1081 $this->end_controls_section();
1082
1083 // Section Typography
1084 $this->start_controls_section(
1085 'section_typo',
1086 [
1087 'label' => __( 'Typography', 'elementor' ),
1088 'tab' => Controls_Manager::TAB_STYLE,
1089 ]
1090 );
1091
1092 $this->add_control(
1093 'heading_color',
1094 [
1095 'label' => __( 'Heading Color', 'elementor' ),
1096 'type' => Controls_Manager::COLOR,
1097 'default' => '',
1098 'selectors' => [
1099 '{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
1100 ],
1101 'separator' => 'none',
1102 ]
1103 );
1104
1105 $this->add_control(
1106 'color_text',
1107 [
1108 'label' => __( 'Text Color', 'elementor' ),
1109 'type' => Controls_Manager::COLOR,
1110 'default' => '',
1111 'selectors' => [
1112 '{{WRAPPER}}' => 'color: {{VALUE}};',
1113 ],
1114 ]
1115 );
1116
1117 $this->add_control(
1118 'color_link',
1119 [
1120 'label' => __( 'Link Color', 'elementor' ),
1121 'type' => Controls_Manager::COLOR,
1122 'default' => '',
1123 'selectors' => [
1124 '{{WRAPPER}} a' => 'color: {{VALUE}};',
1125 ],
1126 ]
1127 );
1128
1129 $this->add_control(
1130 'color_link_hover',
1131 [
1132 'label' => __( 'Link Hover Color', 'elementor' ),
1133 'type' => Controls_Manager::COLOR,
1134 'default' => '',
1135 'selectors' => [
1136 '{{WRAPPER}} a:hover' => 'color: {{VALUE}};',
1137 ],
1138 ]
1139 );
1140
1141 $this->add_control(
1142 'text_align',
1143 [
1144 'label' => __( 'Text Align', 'elementor' ),
1145 'type' => Controls_Manager::CHOOSE,
1146 'options' => [
1147 'left' => [
1148 'title' => __( 'Left', 'elementor' ),
1149 'icon' => 'eicon-text-align-left',
1150 ],
1151 'center' => [
1152 'title' => __( 'Center', 'elementor' ),
1153 'icon' => 'eicon-text-align-center',
1154 ],
1155 'right' => [
1156 'title' => __( 'Right', 'elementor' ),
1157 'icon' => 'eicon-text-align-right',
1158 ],
1159 ],
1160 'selectors' => [
1161 '{{WRAPPER}} > .elementor-container' => 'text-align: {{VALUE}};',
1162 ],
1163 ]
1164 );
1165
1166 $this->end_controls_section();
1167
1168 // Section Advanced
1169 $this->start_controls_section(
1170 'section_advanced',
1171 [
1172 'label' => __( 'Advanced', 'elementor' ),
1173 'tab' => Controls_Manager::TAB_ADVANCED,
1174 ]
1175 );
1176
1177 $this->add_responsive_control(
1178 'margin',
1179 [
1180 'label' => __( 'Margin', 'elementor' ),
1181 'type' => Controls_Manager::DIMENSIONS,
1182 'size_units' => [ 'px', 'em', '%', 'rem' ],
1183 'allowed_dimensions' => 'vertical',
1184 'placeholder' => [
1185 'top' => '',
1186 'right' => 'auto',
1187 'bottom' => '',
1188 'left' => 'auto',
1189 ],
1190 'selectors' => [
1191 '{{WRAPPER}}' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};',
1192 ],
1193 ]
1194 );
1195
1196 $this->add_responsive_control(
1197 'padding',
1198 [
1199 'label' => __( 'Padding', 'elementor' ),
1200 'type' => Controls_Manager::DIMENSIONS,
1201 'size_units' => [ 'px', 'em', '%', 'rem' ],
1202 'selectors' => [
1203 '{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1204 ],
1205 ]
1206 );
1207
1208 $this->add_responsive_control(
1209 'z_index',
1210 [
1211 'label' => __( 'Z-Index', 'elementor' ),
1212 'type' => Controls_Manager::NUMBER,
1213 'min' => 0,
1214 'selectors' => [
1215 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
1216 ],
1217 ]
1218 );
1219
1220 $this->add_control(
1221 '_element_id',
1222 [
1223 'label' => __( 'CSS ID', 'elementor' ),
1224 'type' => Controls_Manager::TEXT,
1225 'default' => '',
1226 'dynamic' => [
1227 'active' => true,
1228 ],
1229 'title' => __( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
1230 'style_transfer' => false,
1231 'classes' => 'elementor-control-direction-ltr',
1232 ]
1233 );
1234
1235 $this->add_control(
1236 'css_classes',
1237 [
1238 'label' => __( 'CSS Classes', 'elementor' ),
1239 'type' => Controls_Manager::TEXT,
1240 'default' => '',
1241 'dynamic' => [
1242 'active' => true,
1243 ],
1244 'prefix_class' => '',
1245 'title' => __( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
1246 'classes' => 'elementor-control-direction-ltr',
1247 ]
1248 );
1249
1250 $this->end_controls_section();
1251
1252 $this->start_controls_section(
1253 'section_effects',
1254 [
1255 'label' => __( 'Motion Effects', 'elementor' ),
1256 'tab' => Controls_Manager::TAB_ADVANCED,
1257 ]
1258 );
1259
1260 $this->add_responsive_control(
1261 'animation',
1262 [
1263 'label' => __( 'Entrance Animation', 'elementor' ),
1264 'type' => Controls_Manager::ANIMATION,
1265 'frontend_available' => true,
1266 ]
1267 );
1268
1269 $this->add_control(
1270 'animation_duration',
1271 [
1272 'label' => __( 'Animation Duration', 'elementor' ),
1273 'type' => Controls_Manager::SELECT,
1274 'default' => '',
1275 'options' => [
1276 'slow' => __( 'Slow', 'elementor' ),
1277 '' => __( 'Normal', 'elementor' ),
1278 'fast' => __( 'Fast', 'elementor' ),
1279 ],
1280 'prefix_class' => 'animated-',
1281 'condition' => [
1282 'animation!' => '',
1283 ],
1284 ]
1285 );
1286
1287 $this->add_control(
1288 'animation_delay',
1289 [
1290 'label' => __( 'Animation Delay', 'elementor' ) . ' (ms)',
1291 'type' => Controls_Manager::NUMBER,
1292 'default' => '',
1293 'min' => 0,
1294 'step' => 100,
1295 'condition' => [
1296 'animation!' => '',
1297 ],
1298 'render_type' => 'none',
1299 'frontend_available' => true,
1300 ]
1301 );
1302
1303 $this->end_controls_section();
1304
1305 // Section Responsive
1306 $this->start_controls_section(
1307 '_section_responsive',
1308 [
1309 'label' => __( 'Responsive', 'elementor' ),
1310 'tab' => Controls_Manager::TAB_ADVANCED,
1311 ]
1312 );
1313
1314 $this->add_control(
1315 'reverse_order_tablet',
1316 [
1317 'label' => __( 'Reverse Columns', 'elementor' ) . ' (' . __( 'Tablet', 'elementor' ) . ')',
1318 'type' => Controls_Manager::SWITCHER,
1319 'default' => '',
1320 'prefix_class' => 'elementor-',
1321 'return_value' => 'reverse-tablet',
1322 ]
1323 );
1324
1325 $this->add_control(
1326 'reverse_order_mobile',
1327 [
1328 'label' => __( 'Reverse Columns', 'elementor' ) . ' (' . __( 'Mobile', 'elementor' ) . ')',
1329 'type' => Controls_Manager::SWITCHER,
1330 'default' => '',
1331 'prefix_class' => 'elementor-',
1332 'return_value' => 'reverse-mobile',
1333 ]
1334 );
1335
1336 $this->add_control(
1337 'heading_visibility',
1338 [
1339 'label' => __( 'Visibility', 'elementor' ),
1340 'type' => Controls_Manager::HEADING,
1341 'separator' => 'before',
1342 ]
1343 );
1344
1345 $this->add_control(
1346 'responsive_description',
1347 [
1348 'raw' => __( 'Responsive visibility will take effect only on preview or live page, and not while editing in Elementor.', 'elementor' ),
1349 'type' => Controls_Manager::RAW_HTML,
1350 'content_classes' => 'elementor-descriptor',
1351 ]
1352 );
1353
1354 $this->add_control(
1355 'hide_desktop',
1356 [
1357 'label' => __( 'Hide On Desktop', 'elementor' ),
1358 'type' => Controls_Manager::SWITCHER,
1359 'default' => '',
1360 'prefix_class' => 'elementor-',
1361 'label_on' => __( 'Hide', 'elementor' ),
1362 'label_off' => __( 'Show', 'elementor' ),
1363 'return_value' => 'hidden-desktop',
1364 ]
1365 );
1366
1367 $this->add_control(
1368 'hide_tablet',
1369 [
1370 'label' => __( 'Hide On Tablet', 'elementor' ),
1371 'type' => Controls_Manager::SWITCHER,
1372 'default' => '',
1373 'prefix_class' => 'elementor-',
1374 'label_on' => __( 'Hide', 'elementor' ),
1375 'label_off' => __( 'Show', 'elementor' ),
1376 'return_value' => 'hidden-tablet',
1377 ]
1378 );
1379
1380 $this->add_control(
1381 'hide_mobile',
1382 [
1383 'label' => __( 'Hide On Mobile', 'elementor' ),
1384 'type' => Controls_Manager::SWITCHER,
1385 'default' => '',
1386 'prefix_class' => 'elementor-',
1387 'label_on' => __( 'Hide', 'elementor' ),
1388 'label_off' => __( 'Show', 'elementor' ),
1389 'return_value' => 'hidden-phone',
1390 ]
1391 );
1392
1393 $this->end_controls_section();
1394
1395 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1396
1397 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1398 }
1399
1400 /**
1401 * Render section output in the editor.
1402 *
1403 * Used to generate the live preview, using a Backbone JavaScript template.
1404 *
1405 * @since 2.9.0
1406 * @access protected
1407 */
1408 protected function content_template() {
1409 ?>
1410 <#
1411 if ( settings.background_video_link ) {
1412 let videoAttributes = 'autoplay muted playsinline';
1413
1414 if ( ! settings.background_play_once ) {
1415 videoAttributes += ' loop';
1416 }
1417
1418 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-background-video-container' );
1419
1420 if ( ! settings.background_play_on_mobile ) {
1421 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-hidden-phone' );
1422 }
1423 #>
1424 <div {{{ view.getRenderAttributeString( 'background-video-container' ) }}}>
1425 <div class="elementor-background-video-embed"></div>
1426 <video class="elementor-background-video-hosted elementor-html5-video" {{ videoAttributes }}></video>
1427 </div>
1428 <# } #>
1429 <div class="elementor-background-overlay"></div>
1430 <div class="elementor-shape elementor-shape-top"></div>
1431 <div class="elementor-shape elementor-shape-bottom"></div>
1432 <div class="elementor-container elementor-column-gap-{{ settings.gap }}">
1433 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
1434 <div class="elementor-row"></div>
1435 <?php } ?>
1436 </div>
1437 <?php
1438 }
1439
1440 /**
1441 * Before section rendering.
1442 *
1443 * Used to add stuff before the section element.
1444 *
1445 * @since 1.0.0
1446 * @access public
1447 */
1448 public function before_render() {
1449 $settings = $this->get_settings_for_display();
1450 ?>
1451 <<?php echo $this->get_html_tag(); ?> <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
1452 <?php
1453 if ( 'video' === $settings['background_background'] ) :
1454 if ( $settings['background_video_link'] ) :
1455 $video_properties = Embed::get_video_properties( $settings['background_video_link'] );
1456
1457 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-background-video-container' );
1458
1459 if ( ! $settings['background_play_on_mobile'] ) {
1460 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-hidden-phone' );
1461 }
1462 ?>
1463 <div <?php echo $this->get_render_attribute_string( 'background-video-container' ); ?>>
1464 <?php if ( $video_properties ) : ?>
1465 <div class="elementor-background-video-embed"></div>
1466 <?php
1467 else :
1468 $video_tag_attributes = 'autoplay muted playsinline';
1469 if ( 'yes' !== $settings['background_play_once'] ) :
1470 $video_tag_attributes .= ' loop';
1471 endif;
1472 ?>
1473 <video class="elementor-background-video-hosted elementor-html5-video" <?php echo $video_tag_attributes; ?>></video>
1474 <?php endif; ?>
1475 </div>
1476 <?php
1477 endif;
1478 endif;
1479
1480 $has_background_overlay = in_array( $settings['background_overlay_background'], [ 'classic', 'gradient' ], true ) ||
1481 in_array( $settings['background_overlay_hover_background'], [ 'classic', 'gradient' ], true );
1482
1483 if ( $has_background_overlay ) :
1484 ?>
1485 <div class="elementor-background-overlay"></div>
1486 <?php
1487 endif;
1488
1489 if ( $settings['shape_divider_top'] ) {
1490 $this->print_shape_divider( 'top' );
1491 }
1492
1493 if ( $settings['shape_divider_bottom'] ) {
1494 $this->print_shape_divider( 'bottom' );
1495 }
1496 ?>
1497 <div class="elementor-container elementor-column-gap-<?php echo esc_attr( $settings['gap'] ); ?>">
1498 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
1499 <div class="elementor-row">
1500 <?php }
1501 }
1502
1503 /**
1504 * After section rendering.
1505 *
1506 * Used to add stuff after the section element.
1507 *
1508 * @since 1.0.0
1509 * @access public
1510 */
1511 public function after_render() {
1512 ?>
1513 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
1514 </div>
1515 <?php } ?>
1516 </div>
1517 </<?php echo $this->get_html_tag(); ?>>
1518 <?php
1519 }
1520
1521 /**
1522 * Add section render attributes.
1523 *
1524 * Used to add attributes to the current section wrapper HTML tag.
1525 *
1526 * @since 1.3.0
1527 * @access protected
1528 */
1529 protected function add_render_attributes() {
1530
1531 $section_type = $this->get_data( 'isInner' ) ? 'inner' : 'top';
1532
1533 $this->add_render_attribute(
1534 '_wrapper', 'class', [
1535 'elementor-section',
1536 'elementor-' . $section_type . '-section',
1537 ]
1538 );
1539
1540 parent::add_render_attributes();
1541 }
1542
1543 /**
1544 * Get default child type.
1545 *
1546 * Retrieve the section child type based on element data.
1547 *
1548 * @since 1.0.0
1549 * @access protected
1550 *
1551 * @param array $element_data Element ID.
1552 *
1553 * @return Element_Base Section default child type.
1554 */
1555 protected function _get_default_child_type( array $element_data ) {
1556 return Plugin::$instance->elements_manager->get_element_types( 'column' );
1557 }
1558
1559 /**
1560 * Get HTML tag.
1561 *
1562 * Retrieve the section element HTML tag.
1563 *
1564 * @since 1.5.3
1565 * @access private
1566 *
1567 * @return string Section HTML tag.
1568 */
1569 private function get_html_tag() {
1570 $html_tag = $this->get_settings( 'html_tag' );
1571
1572 if ( empty( $html_tag ) ) {
1573 $html_tag = 'section';
1574 }
1575
1576 return Utils::validate_html_tag( $html_tag );
1577 }
1578
1579 /**
1580 * Print section shape divider.
1581 *
1582 * Used to generate the shape dividers HTML.
1583 *
1584 * @since 1.3.0
1585 * @access private
1586 *
1587 * @param string $side Shape divider side, used to set the shape key.
1588 */
1589 private function print_shape_divider( $side ) {
1590 $settings = $this->get_active_settings();
1591 $base_setting_key = "shape_divider_$side";
1592 $negative = ! empty( $settings[ $base_setting_key . '_negative' ] );
1593 $shape_path = Shapes::get_shape_path( $settings[ $base_setting_key ], $negative );
1594 if ( ! is_file( $shape_path ) || ! is_readable( $shape_path ) ) {
1595 return;
1596 }
1597 ?>
1598 <div class="elementor-shape elementor-shape-<?php echo esc_attr( $side ); ?>" data-negative="<?php echo var_export( $negative ); ?>">
1599 <?php echo file_get_contents( $shape_path ); ?>
1600 </div>
1601 <?php
1602 }
1603 }
1604