PluginProbe
Elementor Website Builder – more than just a page builder / 3.0.8
Elementor Website Builder – more than just a page builder v3.0.8
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.0.8, at includes/elements/section.php

1,568 lines 36.4 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 1.0.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 ],
292 ]
293 );
294
295 $this->add_control(
296 'height',
297 [
298 'label' => __( 'Height', 'elementor' ),
299 'type' => Controls_Manager::SELECT,
300 'default' => 'default',
301 'options' => [
302 'default' => __( 'Default', 'elementor' ),
303 'full' => __( 'Fit To Screen', 'elementor' ),
304 'min-height' => __( 'Min Height', 'elementor' ),
305 ],
306 'prefix_class' => 'elementor-section-height-',
307 'hide_in_inner' => true,
308 ]
309 );
310
311 $this->add_responsive_control(
312 'custom_height',
313 [
314 'label' => __( 'Minimum Height', 'elementor' ),
315 'type' => Controls_Manager::SLIDER,
316 'default' => [
317 'size' => 400,
318 ],
319 'range' => [
320 'px' => [
321 'min' => 0,
322 'max' => 1440,
323 ],
324 'vh' => [
325 'min' => 0,
326 'max' => 100,
327 ],
328 'vw' => [
329 'min' => 0,
330 'max' => 100,
331 ],
332 ],
333 'size_units' => [ 'px', 'vh', 'vw' ],
334 'selectors' => [
335 '{{WRAPPER}} > .elementor-container' => 'min-height: {{SIZE}}{{UNIT}};',
336 '{{WRAPPER}} > .elementor-container:after' => 'content: ""; min-height: inherit;', // Hack for IE11
337 ],
338 'condition' => [
339 'height' => [ 'min-height' ],
340 ],
341 'hide_in_inner' => true,
342 ]
343 );
344
345 $this->add_control(
346 'height_inner',
347 [
348 'label' => __( 'Height', 'elementor' ),
349 'type' => Controls_Manager::SELECT,
350 'default' => 'default',
351 'options' => [
352 'default' => __( 'Default', 'elementor' ),
353 'min-height' => __( 'Min Height', 'elementor' ),
354 ],
355 'prefix_class' => 'elementor-section-height-',
356 'hide_in_top' => true,
357 ]
358 );
359
360 $this->add_responsive_control(
361 'custom_height_inner',
362 [
363 'label' => __( 'Minimum Height', 'elementor' ),
364 'type' => Controls_Manager::SLIDER,
365 'default' => [
366 'size' => 400,
367 ],
368 'range' => [
369 'px' => [
370 'min' => 0,
371 'max' => 1440,
372 ],
373 ],
374 'selectors' => [
375 '{{WRAPPER}} > .elementor-container' => 'min-height: {{SIZE}}{{UNIT}};',
376 ],
377 'condition' => [
378 'height_inner' => [ 'min-height' ],
379 ],
380 'hide_in_top' => true,
381 ]
382 );
383
384 $this->add_control(
385 'column_position',
386 [
387 'label' => __( 'Column Position', 'elementor' ),
388 'type' => Controls_Manager::SELECT,
389 'default' => 'middle',
390 'options' => [
391 'stretch' => __( 'Stretch', 'elementor' ),
392 'top' => __( 'Top', 'elementor' ),
393 'middle' => __( 'Middle', 'elementor' ),
394 'bottom' => __( 'Bottom', 'elementor' ),
395 ],
396 'prefix_class' => 'elementor-section-items-',
397 'condition' => [
398 'height' => [ 'full', 'min-height' ],
399 ],
400 ]
401 );
402
403 $is_legacy_mode_active = Plugin::instance()->get_legacy_mode( 'elementWrappers' );
404 $content_position_selector = $is_legacy_mode_active ? '{{WRAPPER}} > .elementor-container > .elementor-row > .elementor-column > .elementor-column-wrap > .elementor-widget-wrap' : '{{WRAPPER}} > .elementor-container > .elementor-column > .elementor-widget-wrap';
405
406 $this->add_control(
407 'content_position',
408 [
409 'label' => __( 'Vertical Align', 'elementor' ),
410 'type' => Controls_Manager::SELECT,
411 'default' => '',
412 'options' => [
413 '' => __( 'Default', 'elementor' ),
414 'top' => __( 'Top', 'elementor' ),
415 'middle' => __( 'Middle', 'elementor' ),
416 'bottom' => __( 'Bottom', 'elementor' ),
417 'space-between' => __( 'Space Between', 'elementor' ),
418 'space-around' => __( 'Space Around', 'elementor' ),
419 'space-evenly' => __( 'Space Evenly', 'elementor' ),
420 ],
421 'selectors_dictionary' => [
422 'top' => 'flex-start',
423 'middle' => 'center',
424 'bottom' => 'flex-end',
425 ],
426 'selectors' => [
427 $content_position_selector => 'align-content: {{VALUE}}; align-items: {{VALUE}};',
428 ],
429 // TODO: The following line is for BC since 2.7.0
430 'prefix_class' => 'elementor-section-content-',
431 ]
432 );
433
434 $this->add_control(
435 'overflow',
436 [
437 'label' => __( 'Overflow', 'elementor' ),
438 'type' => Controls_Manager::SELECT,
439 'default' => '',
440 'options' => [
441 '' => __( 'Default', 'elementor' ),
442 'hidden' => __( 'Hidden', 'elementor' ),
443 ],
444 'selectors' => [
445 '{{WRAPPER}}' => 'overflow: {{VALUE}}',
446 ],
447 ]
448 );
449
450 $this->add_control(
451 'stretch_section',
452 [
453 'label' => __( 'Stretch Section', 'elementor' ),
454 'type' => Controls_Manager::SWITCHER,
455 'default' => '',
456 'return_value' => 'section-stretched',
457 'prefix_class' => 'elementor-',
458 'hide_in_inner' => true,
459 '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' ) ),
460 'render_type' => 'none',
461 'frontend_available' => true,
462 ]
463 );
464
465 $possible_tags = [
466 'div',
467 'header',
468 'footer',
469 'main',
470 'article',
471 'section',
472 'aside',
473 'nav',
474 ];
475
476 $options = [
477 '' => __( 'Default', 'elementor' ),
478 ] + array_combine( $possible_tags, $possible_tags );
479
480 $this->add_control(
481 'html_tag',
482 [
483 'label' => __( 'HTML Tag', 'elementor' ),
484 'type' => Controls_Manager::SELECT,
485 'options' => $options,
486 'separator' => 'before',
487 ]
488 );
489
490 $this->end_controls_section();
491
492 // Section Structure
493 $this->start_controls_section(
494 'section_structure',
495 [
496 'label' => __( 'Structure', 'elementor' ),
497 'tab' => Controls_Manager::TAB_LAYOUT,
498 ]
499 );
500
501 $this->add_control(
502 'structure',
503 [
504 'label' => __( 'Structure', 'elementor' ),
505 'type' => Controls_Manager::STRUCTURE,
506 'default' => '10',
507 'render_type' => 'none',
508 'style_transfer' => false,
509 ]
510 );
511
512 $this->end_controls_section();
513
514 // Section background
515 $this->start_controls_section(
516 'section_background',
517 [
518 'label' => __( 'Background', 'elementor' ),
519 'tab' => Controls_Manager::TAB_STYLE,
520 ]
521 );
522
523 $this->start_controls_tabs( 'tabs_background' );
524
525 $this->start_controls_tab(
526 'tab_background_normal',
527 [
528 'label' => __( 'Normal', 'elementor' ),
529 ]
530 );
531
532 $this->add_group_control(
533 Group_Control_Background::get_type(),
534 [
535 'name' => 'background',
536 'types' => [ 'classic', 'gradient', 'video', 'slideshow' ],
537 'fields_options' => [
538 'background' => [
539 'frontend_available' => true,
540 ],
541 ],
542 ]
543 );
544
545 $this->end_controls_tab();
546
547 $this->start_controls_tab(
548 'tab_background_hover',
549 [
550 'label' => __( 'Hover', 'elementor' ),
551 ]
552 );
553
554 $this->add_group_control(
555 Group_Control_Background::get_type(),
556 [
557 'name' => 'background_hover',
558 'selector' => '{{WRAPPER}}:hover',
559 ]
560 );
561
562 $this->add_control(
563 'background_hover_transition',
564 [
565 'label' => __( 'Transition Duration', 'elementor' ),
566 'type' => Controls_Manager::SLIDER,
567 'default' => [
568 'size' => 0.3,
569 ],
570 'range' => [
571 'px' => [
572 'max' => 3,
573 'step' => 0.1,
574 ],
575 ],
576 'render_type' => 'ui',
577 'separator' => 'before',
578 ]
579 );
580
581 $this->end_controls_tab();
582
583 $this->end_controls_tabs();
584
585 $this->end_controls_section();
586
587 // Background Overlay
588 $this->start_controls_section(
589 'section_background_overlay',
590 [
591 'label' => __( 'Background Overlay', 'elementor' ),
592 'tab' => Controls_Manager::TAB_STYLE,
593 ]
594 );
595
596 $this->start_controls_tabs( 'tabs_background_overlay' );
597
598 $this->start_controls_tab(
599 'tab_background_overlay_normal',
600 [
601 'label' => __( 'Normal', 'elementor' ),
602 ]
603 );
604
605 $this->add_group_control(
606 Group_Control_Background::get_type(),
607 [
608 'name' => 'background_overlay',
609 'selector' => '{{WRAPPER}} > .elementor-background-overlay',
610 ]
611 );
612
613 $this->add_control(
614 'background_overlay_opacity',
615 [
616 'label' => __( 'Opacity', 'elementor' ),
617 'type' => Controls_Manager::SLIDER,
618 'default' => [
619 'size' => .5,
620 ],
621 'range' => [
622 'px' => [
623 'max' => 1,
624 'step' => 0.01,
625 ],
626 ],
627 'selectors' => [
628 '{{WRAPPER}} > .elementor-background-overlay' => 'opacity: {{SIZE}};',
629 ],
630 'condition' => [
631 'background_overlay_background' => [ 'classic', 'gradient' ],
632 ],
633 ]
634 );
635
636 $this->add_group_control(
637 Group_Control_Css_Filter::get_type(),
638 [
639 'name' => 'css_filters',
640 'selector' => '{{WRAPPER}} .elementor-background-overlay',
641 'conditions' => [
642 'relation' => 'or',
643 'terms' => [
644 [
645 'name' => 'background_overlay_image[url]',
646 'operator' => '!==',
647 'value' => '',
648 ],
649 [
650 'name' => 'background_overlay_color',
651 'operator' => '!==',
652 'value' => '',
653 ],
654 ],
655 ],
656 ]
657 );
658
659 $this->add_control(
660 'overlay_blend_mode',
661 [
662 'label' => __( 'Blend Mode', 'elementor' ),
663 'type' => Controls_Manager::SELECT,
664 'options' => [
665 '' => __( 'Normal', 'elementor' ),
666 'multiply' => 'Multiply',
667 'screen' => 'Screen',
668 'overlay' => 'Overlay',
669 'darken' => 'Darken',
670 'lighten' => 'Lighten',
671 'color-dodge' => 'Color Dodge',
672 'saturation' => 'Saturation',
673 'color' => 'Color',
674 'luminosity' => 'Luminosity',
675 ],
676 'selectors' => [
677 '{{WRAPPER}} > .elementor-background-overlay' => 'mix-blend-mode: {{VALUE}}',
678 ],
679 'conditions' => [
680 'relation' => 'or',
681 'terms' => [
682 [
683 'name' => 'background_overlay_image[url]',
684 'operator' => '!==',
685 'value' => '',
686 ],
687 [
688 'name' => 'background_overlay_color',
689 'operator' => '!==',
690 'value' => '',
691 ],
692 ],
693 ],
694 ]
695 );
696
697 $this->end_controls_tab();
698
699 $this->start_controls_tab(
700 'tab_background_overlay_hover',
701 [
702 'label' => __( 'Hover', 'elementor' ),
703 ]
704 );
705
706 $this->add_group_control(
707 Group_Control_Background::get_type(),
708 [
709 'name' => 'background_overlay_hover',
710 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
711 ]
712 );
713
714 $this->add_control(
715 'background_overlay_hover_opacity',
716 [
717 'label' => __( 'Opacity', 'elementor' ),
718 'type' => Controls_Manager::SLIDER,
719 'default' => [
720 'size' => .5,
721 ],
722 'range' => [
723 'px' => [
724 'max' => 1,
725 'step' => 0.01,
726 ],
727 ],
728 'selectors' => [
729 '{{WRAPPER}}:hover > .elementor-background-overlay' => 'opacity: {{SIZE}};',
730 ],
731 'condition' => [
732 'background_overlay_hover_background' => [ 'classic', 'gradient' ],
733 ],
734 ]
735 );
736
737 $this->add_group_control(
738 Group_Control_Css_Filter::get_type(),
739 [
740 'name' => 'css_filters_hover',
741 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
742 ]
743 );
744
745 $this->add_control(
746 'background_overlay_hover_transition',
747 [
748 'label' => __( 'Transition Duration', 'elementor' ),
749 'type' => Controls_Manager::SLIDER,
750 'default' => [
751 'size' => 0.3,
752 ],
753 'range' => [
754 'px' => [
755 'max' => 3,
756 'step' => 0.1,
757 ],
758 ],
759 'render_type' => 'ui',
760 'separator' => 'before',
761 ]
762 );
763
764 $this->end_controls_tab();
765
766 $this->end_controls_tabs();
767
768 $this->end_controls_section();
769
770 // Section border
771 $this->start_controls_section(
772 'section_border',
773 [
774 'label' => __( 'Border', 'elementor' ),
775 'tab' => Controls_Manager::TAB_STYLE,
776 ]
777 );
778
779 $this->start_controls_tabs( 'tabs_border' );
780
781 $this->start_controls_tab(
782 'tab_border_normal',
783 [
784 'label' => __( 'Normal', 'elementor' ),
785 ]
786 );
787
788 $this->add_group_control(
789 Group_Control_Border::get_type(),
790 [
791 'name' => 'border',
792 ]
793 );
794
795 $this->add_responsive_control(
796 'border_radius',
797 [
798 'label' => __( 'Border Radius', 'elementor' ),
799 'type' => Controls_Manager::DIMENSIONS,
800 'size_units' => [ 'px', '%' ],
801 'selectors' => [
802 '{{WRAPPER}}, {{WRAPPER}} > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
803 ],
804 ]
805 );
806
807 $this->add_group_control(
808 Group_Control_Box_Shadow::get_type(),
809 [
810 'name' => 'box_shadow',
811 ]
812 );
813
814 $this->end_controls_tab();
815
816 $this->start_controls_tab(
817 'tab_border_hover',
818 [
819 'label' => __( 'Hover', 'elementor' ),
820 ]
821 );
822
823 $this->add_group_control(
824 Group_Control_Border::get_type(),
825 [
826 'name' => 'border_hover',
827 'selector' => '{{WRAPPER}}:hover',
828 ]
829 );
830
831 $this->add_responsive_control(
832 'border_radius_hover',
833 [
834 'label' => __( 'Border Radius', 'elementor' ),
835 'type' => Controls_Manager::DIMENSIONS,
836 'size_units' => [ 'px', '%' ],
837 'selectors' => [
838 '{{WRAPPER}}:hover, {{WRAPPER}}:hover > .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_hover',
847 'selector' => '{{WRAPPER}}:hover',
848 ]
849 );
850
851 $this->add_control(
852 'border_hover_transition',
853 [
854 'label' => __( 'Transition Duration', 'elementor' ),
855 'type' => Controls_Manager::SLIDER,
856 'separator' => 'before',
857 'default' => [
858 'size' => 0.3,
859 ],
860 'range' => [
861 'px' => [
862 'max' => 3,
863 'step' => 0.1,
864 ],
865 ],
866 'conditions' => [
867 'relation' => 'or',
868 'terms' => [
869 [
870 'name' => 'background_background',
871 'operator' => '!==',
872 'value' => '',
873 ],
874 [
875 'name' => 'border_border',
876 'operator' => '!==',
877 'value' => '',
878 ],
879 ],
880 ],
881 'selectors' => [
882 '{{WRAPPER}}' => 'transition: background {{background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s',
883 '{{WRAPPER}} > .elementor-background-overlay' => 'transition: background {{background_overlay_hover_transition.SIZE}}s, border-radius {{SIZE}}s, opacity {{background_overlay_hover_transition.SIZE}}s',
884 ],
885 ]
886 );
887
888 $this->end_controls_tab();
889
890 $this->end_controls_tabs();
891
892 $this->end_controls_section();
893
894 // Section Shape Divider
895 $this->start_controls_section(
896 'section_shape_divider',
897 [
898 'label' => __( 'Shape Divider', 'elementor' ),
899 'tab' => Controls_Manager::TAB_STYLE,
900 ]
901 );
902
903 $this->start_controls_tabs( 'tabs_shape_dividers' );
904
905 $shapes_options = [
906 '' => __( 'None', 'elementor' ),
907 ];
908
909 foreach ( Shapes::get_shapes() as $shape_name => $shape_props ) {
910 $shapes_options[ $shape_name ] = $shape_props['title'];
911 }
912
913 foreach ( [
914 'top' => __( 'Top', 'elementor' ),
915 'bottom' => __( 'Bottom', 'elementor' ),
916 ] as $side => $side_label ) {
917 $base_control_key = "shape_divider_$side";
918
919 $this->start_controls_tab(
920 "tab_$base_control_key",
921 [
922 'label' => $side_label,
923 ]
924 );
925
926 $this->add_control(
927 $base_control_key,
928 [
929 'label' => __( 'Type', 'elementor' ),
930 'type' => Controls_Manager::SELECT,
931 'options' => $shapes_options,
932 'render_type' => 'none',
933 'frontend_available' => true,
934 ]
935 );
936
937 $this->add_control(
938 $base_control_key . '_color',
939 [
940 'label' => __( 'Color', 'elementor' ),
941 'type' => Controls_Manager::COLOR,
942 'condition' => [
943 "shape_divider_$side!" => '',
944 ],
945 'selectors' => [
946 "{{WRAPPER}} > .elementor-shape-$side .elementor-shape-fill" => 'fill: {{UNIT}};',
947 ],
948 ]
949 );
950
951 $this->add_responsive_control(
952 $base_control_key . '_width',
953 [
954 'label' => __( 'Width', 'elementor' ),
955 'type' => Controls_Manager::SLIDER,
956 'default' => [
957 'unit' => '%',
958 ],
959 'tablet_default' => [
960 'unit' => '%',
961 ],
962 'mobile_default' => [
963 'unit' => '%',
964 ],
965 'range' => [
966 '%' => [
967 'min' => 100,
968 'max' => 300,
969 ],
970 ],
971 'condition' => [
972 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'height_only', Shapes::FILTER_EXCLUDE ) ),
973 ],
974 'selectors' => [
975 "{{WRAPPER}} > .elementor-shape-$side svg" => 'width: calc({{SIZE}}{{UNIT}} + 1.3px)',
976 ],
977 ]
978 );
979
980 $this->add_responsive_control(
981 $base_control_key . '_height',
982 [
983 'label' => __( 'Height', 'elementor' ),
984 'type' => Controls_Manager::SLIDER,
985 'range' => [
986 'px' => [
987 'max' => 500,
988 ],
989 ],
990 'condition' => [
991 "shape_divider_$side!" => '',
992 ],
993 'selectors' => [
994 "{{WRAPPER}} > .elementor-shape-$side svg" => 'height: {{SIZE}}{{UNIT}};',
995 ],
996 ]
997 );
998
999 $this->add_control(
1000 $base_control_key . '_flip',
1001 [
1002 'label' => __( 'Flip', 'elementor' ),
1003 'type' => Controls_Manager::SWITCHER,
1004 'condition' => [
1005 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_flip' ) ),
1006 ],
1007 'selectors' => [
1008 "{{WRAPPER}} > .elementor-shape-$side svg" => 'transform: translateX(-50%) rotateY(180deg)',
1009 ],
1010 ]
1011 );
1012
1013 $this->add_control(
1014 $base_control_key . '_negative',
1015 [
1016 'label' => __( 'Invert', 'elementor' ),
1017 'type' => Controls_Manager::SWITCHER,
1018 'frontend_available' => true,
1019 'condition' => [
1020 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_negative' ) ),
1021 ],
1022 'render_type' => 'none',
1023 ]
1024 );
1025
1026 $this->add_control(
1027 $base_control_key . '_above_content',
1028 [
1029 'label' => __( 'Bring to Front', 'elementor' ),
1030 'type' => Controls_Manager::SWITCHER,
1031 'selectors' => [
1032 "{{WRAPPER}} > .elementor-shape-$side" => 'z-index: 2; pointer-events: none',
1033 ],
1034 'condition' => [
1035 "shape_divider_$side!" => '',
1036 ],
1037 ]
1038 );
1039
1040 $this->end_controls_tab();
1041 }
1042
1043 $this->end_controls_tabs();
1044
1045 $this->end_controls_section();
1046
1047 // Section Typography
1048 $this->start_controls_section(
1049 'section_typo',
1050 [
1051 'label' => __( 'Typography', 'elementor' ),
1052 'tab' => Controls_Manager::TAB_STYLE,
1053 ]
1054 );
1055
1056 $this->add_control(
1057 'heading_color',
1058 [
1059 'label' => __( 'Heading Color', 'elementor' ),
1060 'type' => Controls_Manager::COLOR,
1061 'default' => '',
1062 'selectors' => [
1063 '{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
1064 ],
1065 'separator' => 'none',
1066 ]
1067 );
1068
1069 $this->add_control(
1070 'color_text',
1071 [
1072 'label' => __( 'Text Color', 'elementor' ),
1073 'type' => Controls_Manager::COLOR,
1074 'default' => '',
1075 'selectors' => [
1076 '{{WRAPPER}}' => 'color: {{VALUE}};',
1077 ],
1078 ]
1079 );
1080
1081 $this->add_control(
1082 'color_link',
1083 [
1084 'label' => __( 'Link Color', 'elementor' ),
1085 'type' => Controls_Manager::COLOR,
1086 'default' => '',
1087 'selectors' => [
1088 '{{WRAPPER}} a' => 'color: {{VALUE}};',
1089 ],
1090 ]
1091 );
1092
1093 $this->add_control(
1094 'color_link_hover',
1095 [
1096 'label' => __( 'Link Hover Color', 'elementor' ),
1097 'type' => Controls_Manager::COLOR,
1098 'default' => '',
1099 'selectors' => [
1100 '{{WRAPPER}} a:hover' => 'color: {{VALUE}};',
1101 ],
1102 ]
1103 );
1104
1105 $this->add_control(
1106 'text_align',
1107 [
1108 'label' => __( 'Text Align', 'elementor' ),
1109 'type' => Controls_Manager::CHOOSE,
1110 'options' => [
1111 'left' => [
1112 'title' => __( 'Left', 'elementor' ),
1113 'icon' => 'eicon-text-align-left',
1114 ],
1115 'center' => [
1116 'title' => __( 'Center', 'elementor' ),
1117 'icon' => 'eicon-text-align-center',
1118 ],
1119 'right' => [
1120 'title' => __( 'Right', 'elementor' ),
1121 'icon' => 'eicon-text-align-right',
1122 ],
1123 ],
1124 'selectors' => [
1125 '{{WRAPPER}} > .elementor-container' => 'text-align: {{VALUE}};',
1126 ],
1127 ]
1128 );
1129
1130 $this->end_controls_section();
1131
1132 // Section Advanced
1133 $this->start_controls_section(
1134 'section_advanced',
1135 [
1136 'label' => __( 'Advanced', 'elementor' ),
1137 'tab' => Controls_Manager::TAB_ADVANCED,
1138 ]
1139 );
1140
1141 $this->add_responsive_control(
1142 'margin',
1143 [
1144 'label' => __( 'Margin', 'elementor' ),
1145 'type' => Controls_Manager::DIMENSIONS,
1146 'size_units' => [ 'px', 'em', '%', 'rem' ],
1147 'allowed_dimensions' => 'vertical',
1148 'placeholder' => [
1149 'top' => '',
1150 'right' => 'auto',
1151 'bottom' => '',
1152 'left' => 'auto',
1153 ],
1154 'selectors' => [
1155 '{{WRAPPER}}' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};',
1156 ],
1157 ]
1158 );
1159
1160 $this->add_responsive_control(
1161 'padding',
1162 [
1163 'label' => __( 'Padding', 'elementor' ),
1164 'type' => Controls_Manager::DIMENSIONS,
1165 'size_units' => [ 'px', 'em', '%', 'rem' ],
1166 'selectors' => [
1167 '{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1168 ],
1169 ]
1170 );
1171
1172 $this->add_responsive_control(
1173 'z_index',
1174 [
1175 'label' => __( 'Z-Index', 'elementor' ),
1176 'type' => Controls_Manager::NUMBER,
1177 'min' => 0,
1178 'selectors' => [
1179 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
1180 ],
1181 ]
1182 );
1183
1184 $this->add_control(
1185 '_element_id',
1186 [
1187 'label' => __( 'CSS ID', 'elementor' ),
1188 'type' => Controls_Manager::TEXT,
1189 'default' => '',
1190 'dynamic' => [
1191 'active' => true,
1192 ],
1193 'title' => __( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
1194 'style_transfer' => false,
1195 'classes' => 'elementor-control-direction-ltr',
1196 ]
1197 );
1198
1199 $this->add_control(
1200 'css_classes',
1201 [
1202 'label' => __( 'CSS Classes', 'elementor' ),
1203 'type' => Controls_Manager::TEXT,
1204 'default' => '',
1205 'dynamic' => [
1206 'active' => true,
1207 ],
1208 'prefix_class' => '',
1209 'title' => __( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
1210 'classes' => 'elementor-control-direction-ltr',
1211 ]
1212 );
1213
1214 $this->end_controls_section();
1215
1216 $this->start_controls_section(
1217 'section_effects',
1218 [
1219 'label' => __( 'Motion Effects', 'elementor' ),
1220 'tab' => Controls_Manager::TAB_ADVANCED,
1221 ]
1222 );
1223
1224 $this->add_responsive_control(
1225 'animation',
1226 [
1227 'label' => __( 'Entrance Animation', 'elementor' ),
1228 'type' => Controls_Manager::ANIMATION,
1229 'frontend_available' => true,
1230 ]
1231 );
1232
1233 $this->add_control(
1234 'animation_duration',
1235 [
1236 'label' => __( 'Animation Duration', 'elementor' ),
1237 'type' => Controls_Manager::SELECT,
1238 'default' => '',
1239 'options' => [
1240 'slow' => __( 'Slow', 'elementor' ),
1241 '' => __( 'Normal', 'elementor' ),
1242 'fast' => __( 'Fast', 'elementor' ),
1243 ],
1244 'prefix_class' => 'animated-',
1245 'condition' => [
1246 'animation!' => '',
1247 ],
1248 ]
1249 );
1250
1251 $this->add_control(
1252 'animation_delay',
1253 [
1254 'label' => __( 'Animation Delay', 'elementor' ) . ' (ms)',
1255 'type' => Controls_Manager::NUMBER,
1256 'default' => '',
1257 'min' => 0,
1258 'step' => 100,
1259 'condition' => [
1260 'animation!' => '',
1261 ],
1262 'render_type' => 'none',
1263 'frontend_available' => true,
1264 ]
1265 );
1266
1267 $this->end_controls_section();
1268
1269 // Section Responsive
1270 $this->start_controls_section(
1271 '_section_responsive',
1272 [
1273 'label' => __( 'Responsive', 'elementor' ),
1274 'tab' => Controls_Manager::TAB_ADVANCED,
1275 ]
1276 );
1277
1278 $this->add_control(
1279 'reverse_order_tablet',
1280 [
1281 'label' => __( 'Reverse Columns', 'elementor' ) . ' (' . __( 'Tablet', 'elementor' ) . ')',
1282 'type' => Controls_Manager::SWITCHER,
1283 'default' => '',
1284 'prefix_class' => 'elementor-',
1285 'return_value' => 'reverse-tablet',
1286 ]
1287 );
1288
1289 $this->add_control(
1290 'reverse_order_mobile',
1291 [
1292 'label' => __( 'Reverse Columns', 'elementor' ) . ' (' . __( 'Mobile', 'elementor' ) . ')',
1293 'type' => Controls_Manager::SWITCHER,
1294 'default' => '',
1295 'prefix_class' => 'elementor-',
1296 'return_value' => 'reverse-mobile',
1297 ]
1298 );
1299
1300 $this->add_control(
1301 'heading_visibility',
1302 [
1303 'label' => __( 'Visibility', 'elementor' ),
1304 'type' => Controls_Manager::HEADING,
1305 'separator' => 'before',
1306 ]
1307 );
1308
1309 $this->add_control(
1310 'responsive_description',
1311 [
1312 'raw' => __( 'Responsive visibility will take effect only on preview or live page, and not while editing in Elementor.', 'elementor' ),
1313 'type' => Controls_Manager::RAW_HTML,
1314 'content_classes' => 'elementor-descriptor',
1315 ]
1316 );
1317
1318 $this->add_control(
1319 'hide_desktop',
1320 [
1321 'label' => __( 'Hide On Desktop', 'elementor' ),
1322 'type' => Controls_Manager::SWITCHER,
1323 'default' => '',
1324 'prefix_class' => 'elementor-',
1325 'label_on' => __( 'Hide', 'elementor' ),
1326 'label_off' => __( 'Show', 'elementor' ),
1327 'return_value' => 'hidden-desktop',
1328 ]
1329 );
1330
1331 $this->add_control(
1332 'hide_tablet',
1333 [
1334 'label' => __( 'Hide On Tablet', 'elementor' ),
1335 'type' => Controls_Manager::SWITCHER,
1336 'default' => '',
1337 'prefix_class' => 'elementor-',
1338 'label_on' => __( 'Hide', 'elementor' ),
1339 'label_off' => __( 'Show', 'elementor' ),
1340 'return_value' => 'hidden-tablet',
1341 ]
1342 );
1343
1344 $this->add_control(
1345 'hide_mobile',
1346 [
1347 'label' => __( 'Hide On Mobile', 'elementor' ),
1348 'type' => Controls_Manager::SWITCHER,
1349 'default' => '',
1350 'prefix_class' => 'elementor-',
1351 'label_on' => __( 'Hide', 'elementor' ),
1352 'label_off' => __( 'Show', 'elementor' ),
1353 'return_value' => 'hidden-phone',
1354 ]
1355 );
1356
1357 $this->end_controls_section();
1358
1359 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1360
1361 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1362 }
1363
1364 /**
1365 * Render section output in the editor.
1366 *
1367 * Used to generate the live preview, using a Backbone JavaScript template.
1368 *
1369 * @since 2.9.0
1370 * @access protected
1371 */
1372 protected function content_template() {
1373 ?>
1374 <#
1375 if ( settings.background_video_link ) {
1376 let videoAttributes = 'autoplay muted playsinline';
1377
1378 if ( ! settings.background_play_once ) {
1379 videoAttributes += ' loop';
1380 }
1381
1382 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-background-video-container' );
1383
1384 if ( ! settings.background_play_on_mobile ) {
1385 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-hidden-phone' );
1386 }
1387 #>
1388 <div {{{ view.getRenderAttributeString( 'background-video-container' ) }}}>
1389 <div class="elementor-background-video-embed"></div>
1390 <video class="elementor-background-video-hosted elementor-html5-video" {{ videoAttributes }}></video>
1391 </div>
1392 <# } #>
1393 <div class="elementor-background-overlay"></div>
1394 <div class="elementor-shape elementor-shape-top"></div>
1395 <div class="elementor-shape elementor-shape-bottom"></div>
1396 <div class="elementor-container elementor-column-gap-{{ settings.gap }}">
1397 <?php if ( Plugin::instance()->get_legacy_mode( 'elementWrappers' ) ) { ?>
1398 <div class="elementor-row"></div>
1399 <?php } ?>
1400 </div>
1401 <?php
1402 }
1403
1404 /**
1405 * Before section rendering.
1406 *
1407 * Used to add stuff before the section element.
1408 *
1409 * @since 1.0.0
1410 * @access public
1411 */
1412 public function before_render() {
1413 $settings = $this->get_settings_for_display();
1414 ?>
1415 <<?php echo esc_html( $this->get_html_tag() ); ?> <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
1416 <?php
1417 if ( 'video' === $settings['background_background'] ) :
1418 if ( $settings['background_video_link'] ) :
1419 $video_properties = Embed::get_video_properties( $settings['background_video_link'] );
1420
1421 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-background-video-container' );
1422
1423 if ( ! $settings['background_play_on_mobile'] ) {
1424 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-hidden-phone' );
1425 }
1426 ?>
1427 <div <?php echo $this->get_render_attribute_string( 'background-video-container' ); ?>>
1428 <?php if ( $video_properties ) : ?>
1429 <div class="elementor-background-video-embed"></div>
1430 <?php
1431 else :
1432 $video_tag_attributes = 'autoplay muted playsinline';
1433 if ( 'yes' !== $settings['background_play_once'] ) :
1434 $video_tag_attributes .= ' loop';
1435 endif;
1436 ?>
1437 <video class="elementor-background-video-hosted elementor-html5-video" <?php echo $video_tag_attributes; ?>></video>
1438 <?php endif; ?>
1439 </div>
1440 <?php
1441 endif;
1442 endif;
1443
1444 $has_background_overlay = in_array( $settings['background_overlay_background'], [ 'classic', 'gradient' ], true ) ||
1445 in_array( $settings['background_overlay_hover_background'], [ 'classic', 'gradient' ], true );
1446
1447 if ( $has_background_overlay ) :
1448 ?>
1449 <div class="elementor-background-overlay"></div>
1450 <?php
1451 endif;
1452
1453 if ( $settings['shape_divider_top'] ) {
1454 $this->print_shape_divider( 'top' );
1455 }
1456
1457 if ( $settings['shape_divider_bottom'] ) {
1458 $this->print_shape_divider( 'bottom' );
1459 }
1460 ?>
1461 <div class="elementor-container elementor-column-gap-<?php echo esc_attr( $settings['gap'] ); ?>">
1462 <?php if ( Plugin::instance()->get_legacy_mode( 'elementWrappers' ) ) { ?>
1463 <div class="elementor-row">
1464 <?php }
1465 }
1466
1467 /**
1468 * After section rendering.
1469 *
1470 * Used to add stuff after the section element.
1471 *
1472 * @since 1.0.0
1473 * @access public
1474 */
1475 public function after_render() {
1476 ?>
1477 <?php if ( Plugin::instance()->get_legacy_mode( 'elementWrappers' ) ) { ?>
1478 </div>
1479 <?php } ?>
1480 </div>
1481 </<?php echo esc_html( $this->get_html_tag() ); ?>>
1482 <?php
1483 }
1484
1485 /**
1486 * Add section render attributes.
1487 *
1488 * Used to add attributes to the current section wrapper HTML tag.
1489 *
1490 * @since 1.3.0
1491 * @access protected
1492 */
1493 protected function _add_render_attributes() {
1494
1495 $section_type = $this->get_data( 'isInner' ) ? 'inner' : 'top';
1496
1497 $this->add_render_attribute(
1498 '_wrapper', 'class', [
1499 'elementor-section',
1500 'elementor-' . $section_type . '-section',
1501 ]
1502 );
1503
1504 parent::_add_render_attributes();
1505 }
1506
1507 /**
1508 * Get default child type.
1509 *
1510 * Retrieve the section child type based on element data.
1511 *
1512 * @since 1.0.0
1513 * @access protected
1514 *
1515 * @param array $element_data Element ID.
1516 *
1517 * @return Element_Base Section default child type.
1518 */
1519 protected function _get_default_child_type( array $element_data ) {
1520 return Plugin::$instance->elements_manager->get_element_types( 'column' );
1521 }
1522
1523 /**
1524 * Get HTML tag.
1525 *
1526 * Retrieve the section element HTML tag.
1527 *
1528 * @since 1.5.3
1529 * @access private
1530 *
1531 * @return string Section HTML tag.
1532 */
1533 private function get_html_tag() {
1534 $html_tag = $this->get_settings( 'html_tag' );
1535
1536 if ( empty( $html_tag ) ) {
1537 $html_tag = 'section';
1538 }
1539
1540 return $html_tag;
1541 }
1542
1543 /**
1544 * Print section shape divider.
1545 *
1546 * Used to generate the shape dividers HTML.
1547 *
1548 * @since 1.3.0
1549 * @access private
1550 *
1551 * @param string $side Shape divider side, used to set the shape key.
1552 */
1553 private function print_shape_divider( $side ) {
1554 $settings = $this->get_active_settings();
1555 $base_setting_key = "shape_divider_$side";
1556 $negative = ! empty( $settings[ $base_setting_key . '_negative' ] );
1557 $shape_path = Shapes::get_shape_path( $settings[ $base_setting_key ], $negative );
1558 if ( ! is_file( $shape_path ) || ! is_readable( $shape_path ) ) {
1559 return;
1560 }
1561 ?>
1562 <div class="elementor-shape elementor-shape-<?php echo esc_attr( $side ); ?>" data-negative="<?php echo var_export( $negative ); ?>">
1563 <?php echo file_get_contents( $shape_path ); ?>
1564 </div>
1565 <?php
1566 }
1567 }
1568