PluginProbe
Elementor Website Builder – more than just a page builder / 3.8.1
Elementor Website Builder – more than just a page builder v3.8.1
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 / container.php

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

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