PluginProbe
Elementor Website Builder – more than just a page builder / 3.28.0-dev2
Elementor Website Builder – more than just a page builder v3.28.0-dev2
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 / widgets / common-base.php

common-base.php in Elementor Website Builder – more than just a page builder 3.28.0-dev2, at includes/widgets/common-base.php

1,280 lines 30.7 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 common widget.
10 *
11 * Elementor base widget that gives you all the advanced options of the basic
12 * widget.
13 *
14 * @since 1.0.0
15 */
16 class Widget_Common_Base extends Widget_Base {
17
18 const WRAPPER_SELECTOR = '{{WRAPPER}} .elementor-widget-container';
19 const WRAPPER_SELECTOR_CHILD = '{{WRAPPER}} > .elementor-widget-container';
20 const WRAPPER_SELECTOR_HOVER = '{{WRAPPER}}:hover .elementor-widget-container';
21 const WRAPPER_SELECTOR_HOVER_CHILD = '{{WRAPPER}}:hover > .elementor-widget-container';
22 const MASK_SELECTOR_DEFAULT = '{{WRAPPER}}:not( .elementor-widget-image ) .elementor-widget-container';
23 const MASK_SELECTOR_IMG = '{{WRAPPER}}.elementor-widget-image .elementor-widget-container img';
24 const TRANSFORM_SELECTOR_CLASS = ' > .elementor-widget-container';
25 const MARGIN = 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};';
26
27 /**
28 * Get widget name.
29 *
30 * Retrieve common widget name.
31 *
32 * @since 1.0.0
33 * @access public
34 *
35 * @return string Widget name.
36 */
37 public function get_name() {
38 return 'common-base';
39 }
40
41 /**
42 * Show in panel.
43 *
44 * Whether to show the common widget in the panel or not.
45 *
46 * @since 1.0.0
47 * @access public
48 *
49 * @return bool Whether to show the widget in the panel.
50 */
51 public function show_in_panel() {
52 return false;
53 }
54
55 /**
56 * Get Responsive Device Args
57 *
58 * Receives an array of device args, and duplicates it for each active breakpoint.
59 * Returns an array of device args.
60 *
61 * @since 3.4.7
62 * @deprecated 3.7.0 Not needed anymore because responsive conditioning in the Editor was fixed in v3.7.0.
63 * @access protected
64 *
65 * @param array $args arguments to duplicate per breakpoint.
66 * @param array $devices_to_exclude
67 *
68 * @return array responsive device args
69 */
70 protected function get_responsive_device_args( array $args, array $devices_to_exclude = [] ) {
71 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.7.0' );
72
73 $device_args = [];
74 $breakpoints = Plugin::$instance->breakpoints->get_active_breakpoints();
75
76 foreach ( $breakpoints as $breakpoint_key => $breakpoint ) {
77 // If the device is not excluded, add it to the device args array.
78 if ( ! in_array( $breakpoint_key, $devices_to_exclude, true ) ) {
79 $parsed_device_args = $this->parse_device_args_placeholders( $args, $breakpoint_key );
80
81 $device_args[ $breakpoint_key ] = $parsed_device_args;
82 }
83 }
84
85 return $device_args;
86 }
87
88 /**
89 * Parse Device Args Placeholders
90 *
91 * Receives an array of args. Iterates over the args, and replaces the {{DEVICE}} placeholder, if exists, with the
92 * passed breakpoint key.
93 *
94 * @since 3.4.7
95 * @access private
96 *
97 * @param array $args
98 * @param string $breakpoint_key
99 * @return array parsed device args
100 */
101 private function parse_device_args_placeholders( array $args, $breakpoint_key ) {
102 $parsed_args = [];
103
104 foreach ( $args as $arg_key => $arg_value ) {
105 $arg_key = str_replace( '{{DEVICE}}', $breakpoint_key, $arg_key );
106
107 if ( is_array( $arg_value ) ) {
108 $arg_value = $this->parse_device_args_placeholders( $arg_value, $breakpoint_key );
109 }
110
111 $parsed_args[ $arg_key ] = $arg_value;
112 }
113
114 return $parsed_args;
115 }
116
117 /**
118 * @param String $shape Shape name.
119 *
120 * @return string The shape path in the assets folder.
121 */
122 private function get_shape_url( $shape ) {
123 return ELEMENTOR_ASSETS_URL . 'mask-shapes/' . $shape . '.svg';
124 }
125
126 /**
127 * Return a translated user-friendly list of the available masking shapes.
128 *
129 * @param bool $add_custom Determine if the output should contain `Custom` options.
130 *
131 * @return array Array of shapes with their URL as key.
132 */
133 private function get_shapes( $add_custom = true ) {
134 $shapes = [
135 'circle' => esc_html__( 'Circle', 'elementor' ),
136 'flower' => esc_html__( 'Flower', 'elementor' ),
137 'sketch' => esc_html__( 'Sketch', 'elementor' ),
138 'triangle' => esc_html__( 'Triangle', 'elementor' ),
139 'blob' => esc_html__( 'Blob', 'elementor' ),
140 'hexagon' => esc_html__( 'Hexagon', 'elementor' ),
141 ];
142
143 if ( $add_custom ) {
144 $shapes['custom'] = esc_html__( 'Custom', 'elementor' );
145 }
146
147 return $shapes;
148 }
149
150 /**
151 * Gets a string of CSS rules to apply, and returns an array of selectors with those rules.
152 * This function has been created in order to deal with masking for image widget.
153 * For most of the widgets the mask is being applied to the wrapper itself, but in the case of an image widget,
154 * the `img` tag should be masked directly. So instead of writing a lot of selectors every time,
155 * this function builds both of those selectors easily.
156 *
157 * @param string $rules The CSS rules to apply.
158 *
159 * @return array Selectors with the rules applied.
160 */
161 private function get_mask_selectors( $rules ) {
162 $mask_selectors = [
163 'default' => static::MASK_SELECTOR_DEFAULT,
164 'image' => static::MASK_SELECTOR_IMG,
165 ];
166
167 return [
168 $mask_selectors['default'] => $rules,
169 $mask_selectors['image'] => $rules,
170 ];
171 }
172
173 /**
174 * Register the Layout section.
175 *
176 * @return void
177 */
178 private function register_layout_section() {
179 $this->start_controls_section(
180 '_section_style',
181 [
182 'label' => esc_html__( 'Layout', 'elementor' ),
183 'tab' => Controls_Manager::TAB_ADVANCED,
184 ]
185 );
186
187 // Element Name for the Navigator
188 $this->add_control(
189 '_title',
190 [
191 'label' => esc_html__( 'Title', 'elementor' ),
192 'type' => Controls_Manager::HIDDEN,
193 'render_type' => 'none',
194 ]
195 );
196
197 $this->add_responsive_control(
198 '_margin',
199 [
200 'label' => esc_html__( 'Margin', 'elementor' ),
201 'type' => Controls_Manager::DIMENSIONS,
202 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
203 'selectors' => [
204 static::WRAPPER_SELECTOR_CHILD => static::MARGIN,
205 ],
206 ]
207 );
208
209 $this->add_responsive_control(
210 '_padding',
211 [
212 'label' => esc_html__( 'Padding', 'elementor' ),
213 'type' => Controls_Manager::DIMENSIONS,
214 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
215 'selectors' => [
216 static::WRAPPER_SELECTOR_CHILD => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
217 ],
218 ]
219 );
220
221 $experiments_manager = Plugin::$instance->experiments;
222 $is_container_active = $experiments_manager->is_feature_active( 'container' );
223
224 $this->add_responsive_control(
225 '_element_width',
226 [
227 'label' => esc_html__( 'Width', 'elementor' ),
228 'type' => Controls_Manager::SELECT,
229 'default' => '',
230 'options' => [
231 '' => esc_html__( 'Default', 'elementor' ),
232 'inherit' => esc_html__( 'Full Width', 'elementor' ) . ' (100%)',
233 'auto' => esc_html__( 'Inline', 'elementor' ) . ' (auto)',
234 'initial' => esc_html__( 'Custom', 'elementor' ),
235 ],
236 'selectors_dictionary' => [
237 'inherit' => '100%',
238 ],
239 'prefix_class' => 'elementor-widget%s__width-',
240 'selectors' => [
241 '{{WRAPPER}}' => 'width: {{VALUE}}; max-width: {{VALUE}}',
242 ],
243 ]
244 );
245
246 $this->add_responsive_control(
247 '_element_custom_width',
248 [
249 'label' => esc_html__( 'Custom Width', 'elementor' ),
250 'type' => Controls_Manager::SLIDER,
251 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
252 'default' => [
253 'unit' => '%',
254 ],
255 'range' => [
256 'px' => [
257 'max' => 1000,
258 ],
259 ],
260 'selectors' => [
261 '{{WRAPPER}}' => '--container-widget-width: {{SIZE}}{{UNIT}}; --container-widget-flex-grow: 0; width: var( --container-widget-width, {{SIZE}}{{UNIT}} ); max-width: {{SIZE}}{{UNIT}}',
262 ],
263 'condition' => [ '_element_width' => 'initial' ],
264 ]
265 );
266
267 $this->add_control(
268 '_heading_grid_item',
269 [
270 'type' => Controls_Manager::HEADING,
271 'label' => esc_html__( 'Grid Item', 'elementor' ),
272 'separator' => 'before',
273 ]
274 );
275
276 $this->add_responsive_control(
277 '_grid_column',
278 [
279 'label' => esc_html__( 'Column Span', 'elementor' ),
280 'type' => Controls_Manager::SELECT,
281 'options' => [
282 '' => ' Default',
283 '1' => '1',
284 '2' => '2',
285 '3' => '3',
286 '4' => '4',
287 '5' => '5',
288 '6' => '6',
289 '7' => '7',
290 '8' => '8',
291 '9' => '9',
292 '10' => '10',
293 '11' => '11',
294 '12' => '12',
295 'custom' => 'Custom',
296 ],
297 'selectors' => [
298 '{{WRAPPER}}' => 'grid-column: span {{VALUE}};',
299 ],
300 ]
301 );
302
303 $this->add_responsive_control(
304 '_grid_column_custom',
305 [
306 'label' => esc_html__( 'Custom', 'elementor' ),
307 'type' => Controls_Manager::TEXT,
308 'ai' => [
309 'active' => false,
310 ],
311 'selectors' => [
312 '{{WRAPPER}}' => 'grid-column: {{VALUE}}',
313 ],
314 'condition' => [
315 '_grid_column' => 'custom',
316 ],
317 ]
318 );
319
320 $this->add_responsive_control(
321 '_grid_row',
322 [
323 'label' => esc_html__( 'Row Span', 'elementor' ),
324 'type' => Controls_Manager::SELECT,
325 'options' => [
326 '' => ' Default',
327 '1' => '1',
328 '2' => '2',
329 '3' => '3',
330 '4' => '4',
331 '5' => '5',
332 '6' => '6',
333 '7' => '7',
334 '8' => '8',
335 '9' => '9',
336 '10' => '10',
337 '11' => '11',
338 '12' => '12',
339 'custom' => 'Custom',
340 ],
341 'selectors' => [
342 '{{WRAPPER}}' => 'grid-row: span {{VALUE}};',
343 ],
344 ]
345 );
346
347 $this->add_responsive_control(
348 '_grid_row_custom',
349 [
350 'label' => esc_html__( 'Custom', 'elementor' ),
351 'type' => Controls_Manager::TEXT,
352 'separator' => 'after',
353 'ai' => [
354 'active' => false,
355 ],
356 'selectors' => [
357 '{{WRAPPER}}' => 'grid-row: {{VALUE}}',
358 ],
359 'condition' => [
360 '_grid_row' => 'custom',
361 ],
362 ]
363 );
364
365 // Register Flex controls only if the Container experiment is active.
366 if ( $is_container_active ) {
367 $this->add_group_control(
368 Group_Control_Flex_Item::get_type(),
369 [
370 'name' => '_flex',
371 // Hack to increase specificity and make sure that the current widget overrides the
372 // parent flex settings.
373 'selector' => '{{WRAPPER}}.elementor-element',
374 'include' => [
375 'align_self',
376 'order',
377 'order_custom',
378 'size',
379 'grow',
380 'shrink',
381 ],
382 'fields_options' => [
383 'align_self' => [
384 'separator' => 'before',
385 ],
386 ],
387 ]
388 );
389 }
390
391 $vertical_align_conditions = [
392 '_element_width!' => '',
393 '_position' => '',
394 ];
395
396 if ( $is_container_active ) {
397 $vertical_align_conditions['_element_vertical_align!'] = ''; // TODO: For BC.
398 }
399
400 // TODO: For BC - Remove in the future.
401 $this->add_responsive_control(
402 '_element_vertical_align',
403 [
404 'label' => esc_html__( 'Vertical Align', 'elementor' ),
405 'type' => Controls_Manager::CHOOSE,
406 'options' => [
407 'flex-start' => [
408 'title' => esc_html__( 'Start', 'elementor' ),
409 'icon' => 'eicon-v-align-top',
410 ],
411 'center' => [
412 'title' => esc_html__( 'Center', 'elementor' ),
413 'icon' => 'eicon-v-align-middle',
414 ],
415 'flex-end' => [
416 'title' => esc_html__( 'End', 'elementor' ),
417 'icon' => 'eicon-v-align-bottom',
418 ],
419 ],
420 'condition' => $vertical_align_conditions,
421 'selectors' => [
422 '{{WRAPPER}}' => 'align-self: {{VALUE}}',
423 ],
424 ]
425 );
426
427 $this->add_control(
428 '_position_description',
429 [
430 'type' => Controls_Manager::ALERT,
431 'alert_type' => 'warning',
432 'heading' => esc_html__( 'Please note!', 'elementor' ),
433 'content' => esc_html__( 'Custom positioning is not considered best practice for responsive web design and should not be used too frequently.', 'elementor' ),
434 'render_type' => 'ui',
435 'condition' => [
436 '_position!' => '',
437 ],
438 ]
439 );
440
441 $this->add_control(
442 '_position',
443 [
444 'label' => esc_html__( 'Position', 'elementor' ),
445 'type' => Controls_Manager::SELECT,
446 'default' => '',
447 'options' => [
448 '' => esc_html__( 'Default', 'elementor' ),
449 'absolute' => esc_html__( 'Absolute', 'elementor' ),
450 'fixed' => esc_html__( 'Fixed', 'elementor' ),
451 ],
452 'prefix_class' => 'elementor-',
453 'frontend_available' => true,
454 'separator' => 'before',
455 ]
456 );
457
458 $start = is_rtl() ? esc_html__( 'Right', 'elementor' ) : esc_html__( 'Left', 'elementor' );
459 $end = ! is_rtl() ? esc_html__( 'Right', 'elementor' ) : esc_html__( 'Left', 'elementor' );
460
461 $this->add_control(
462 '_offset_orientation_h',
463 [
464 'label' => esc_html__( 'Horizontal Orientation', 'elementor' ),
465 'type' => Controls_Manager::CHOOSE,
466 'toggle' => false,
467 'default' => 'start',
468 'options' => [
469 'start' => [
470 'title' => $start,
471 'icon' => 'eicon-h-align-left',
472 ],
473 'end' => [
474 'title' => $end,
475 'icon' => 'eicon-h-align-right',
476 ],
477 ],
478 'classes' => 'elementor-control-start-end',
479 'render_type' => 'ui',
480 'condition' => [
481 '_position!' => '',
482 ],
483 ]
484 );
485
486 $this->add_responsive_control(
487 '_offset_x',
488 [
489 'label' => esc_html__( 'Offset', 'elementor' ),
490 'type' => Controls_Manager::SLIDER,
491 'range' => [
492 'px' => [
493 'min' => -1000,
494 'max' => 1000,
495 ],
496 '%' => [
497 'min' => -200,
498 'max' => 200,
499 ],
500 'vw' => [
501 'min' => -200,
502 'max' => 200,
503 ],
504 'vh' => [
505 'min' => -200,
506 'max' => 200,
507 ],
508 ],
509 'default' => [
510 'size' => 0,
511 ],
512 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'vh', 'custom' ],
513 'selectors' => [
514 'body:not(.rtl) {{WRAPPER}}' => 'left: {{SIZE}}{{UNIT}}',
515 'body.rtl {{WRAPPER}}' => 'right: {{SIZE}}{{UNIT}}',
516 ],
517 'condition' => [
518 '_offset_orientation_h!' => 'end',
519 '_position!' => '',
520 ],
521 ]
522 );
523
524 $this->add_responsive_control(
525 '_offset_x_end',
526 [
527 'label' => esc_html__( 'Offset', 'elementor' ),
528 'type' => Controls_Manager::SLIDER,
529 'range' => [
530 'px' => [
531 'min' => -1000,
532 'max' => 1000,
533 ],
534 '%' => [
535 'min' => -200,
536 'max' => 200,
537 ],
538 'vw' => [
539 'min' => -200,
540 'max' => 200,
541 ],
542 'vh' => [
543 'min' => -200,
544 'max' => 200,
545 ],
546 ],
547 'default' => [
548 'size' => 0,
549 ],
550 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'vh', 'custom' ],
551 'selectors' => [
552 'body:not(.rtl) {{WRAPPER}}' => 'right: {{SIZE}}{{UNIT}}',
553 'body.rtl {{WRAPPER}}' => 'left: {{SIZE}}{{UNIT}}',
554 ],
555 'condition' => [
556 '_offset_orientation_h' => 'end',
557 '_position!' => '',
558 ],
559 ]
560 );
561
562 $this->add_control(
563 '_offset_orientation_v',
564 [
565 'label' => esc_html__( 'Vertical Orientation', 'elementor' ),
566 'type' => Controls_Manager::CHOOSE,
567 'toggle' => false,
568 'default' => 'start',
569 'options' => [
570 'start' => [
571 'title' => esc_html__( 'Top', 'elementor' ),
572 'icon' => 'eicon-v-align-top',
573 ],
574 'end' => [
575 'title' => esc_html__( 'Bottom', 'elementor' ),
576 'icon' => 'eicon-v-align-bottom',
577 ],
578 ],
579 'render_type' => 'ui',
580 'condition' => [
581 '_position!' => '',
582 ],
583 ]
584 );
585
586 $this->add_responsive_control(
587 '_offset_y',
588 [
589 'label' => esc_html__( 'Offset', 'elementor' ),
590 'type' => Controls_Manager::SLIDER,
591 'range' => [
592 'px' => [
593 'min' => -1000,
594 'max' => 1000,
595 ],
596 '%' => [
597 'min' => -200,
598 'max' => 200,
599 ],
600 'vh' => [
601 'min' => -200,
602 'max' => 200,
603 ],
604 'vw' => [
605 'min' => -200,
606 'max' => 200,
607 ],
608 ],
609 'size_units' => [ 'px', '%', 'em', 'rem', 'vh', 'vw', 'custom' ],
610 'default' => [
611 'size' => 0,
612 ],
613 'selectors' => [
614 '{{WRAPPER}}' => 'top: {{SIZE}}{{UNIT}}',
615 ],
616 'condition' => [
617 '_offset_orientation_v!' => 'end',
618 '_position!' => '',
619 ],
620 ]
621 );
622
623 $this->add_responsive_control(
624 '_offset_y_end',
625 [
626 'label' => esc_html__( 'Offset', 'elementor' ),
627 'type' => Controls_Manager::SLIDER,
628 'range' => [
629 'px' => [
630 'min' => -1000,
631 'max' => 1000,
632 ],
633 '%' => [
634 'min' => -200,
635 'max' => 200,
636 ],
637 'vh' => [
638 'min' => -200,
639 'max' => 200,
640 ],
641 'vw' => [
642 'min' => -200,
643 'max' => 200,
644 ],
645 ],
646 'size_units' => [ 'px', '%', 'em', 'rem', 'vh', 'vw', 'custom' ],
647 'default' => [
648 'size' => 0,
649 ],
650 'selectors' => [
651 '{{WRAPPER}}' => 'bottom: {{SIZE}}{{UNIT}}',
652 ],
653 'condition' => [
654 '_offset_orientation_v' => 'end',
655 '_position!' => '',
656 ],
657 ]
658 );
659
660 $this->add_responsive_control(
661 '_z_index',
662 [
663 'label' => esc_html__( 'Z-Index', 'elementor' ),
664 'type' => Controls_Manager::NUMBER,
665 'selectors' => [
666 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
667 ],
668 ]
669 );
670
671 $this->add_control(
672 '_element_id',
673 [
674 'label' => esc_html__( 'CSS ID', 'elementor' ),
675 'type' => Controls_Manager::TEXT,
676 'dynamic' => [
677 'active' => true,
678 ],
679 'ai' => [
680 'active' => false,
681 ],
682 'default' => '',
683 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
684 'style_transfer' => false,
685 'classes' => 'elementor-control-direction-ltr',
686 ]
687 );
688
689 $this->add_control(
690 '_css_classes',
691 [
692 'label' => esc_html__( 'CSS Classes', 'elementor' ),
693 'type' => Controls_Manager::TEXT,
694 'ai' => [
695 'active' => false,
696 ],
697 'dynamic' => [
698 'active' => true,
699 ],
700 'prefix_class' => '',
701 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
702 'classes' => 'elementor-control-direction-ltr',
703 ]
704 );
705
706 Plugin::$instance->controls_manager->add_display_conditions_controls( $this );
707
708 $this->end_controls_section();
709 }
710
711 /**
712 * Register the Motion Effects section.
713 *
714 * @return void
715 */
716 private function register_effects_section() {
717 $this->start_controls_section(
718 'section_effects',
719 [
720 'label' => esc_html__( 'Motion Effects', 'elementor' ),
721 'tab' => Controls_Manager::TAB_ADVANCED,
722 ]
723 );
724
725 Plugin::$instance->controls_manager->add_motion_effects_promotion_control( $this );
726
727 $this->add_responsive_control(
728 '_animation',
729 [
730 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
731 'type' => Controls_Manager::ANIMATION,
732 'frontend_available' => true,
733 ]
734 );
735
736 $this->add_control(
737 'animation_duration',
738 [
739 'label' => esc_html__( 'Animation Duration', 'elementor' ),
740 'type' => Controls_Manager::SELECT,
741 'default' => '',
742 'options' => [
743 'slow' => esc_html__( 'Slow', 'elementor' ),
744 '' => esc_html__( 'Normal', 'elementor' ),
745 'fast' => esc_html__( 'Fast', 'elementor' ),
746 ],
747 'prefix_class' => 'animated-',
748 'condition' => [
749 '_animation!' => '',
750 ],
751 ]
752 );
753
754 $this->add_control(
755 '_animation_delay',
756 [
757 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
758 'type' => Controls_Manager::NUMBER,
759 'default' => '',
760 'min' => 0,
761 'step' => 100,
762 'condition' => [
763 '_animation!' => '',
764 ],
765 'render_type' => 'none',
766 'frontend_available' => true,
767 ]
768 );
769
770 $this->end_controls_section();
771 }
772
773 /** Register the Background section.
774 *
775 * @return void
776 */
777 private function register_background_section() {
778 $this->start_controls_section(
779 '_section_background',
780 [
781 'label' => esc_html__( 'Background', 'elementor' ),
782 'tab' => Controls_Manager::TAB_ADVANCED,
783 ]
784 );
785
786 $this->start_controls_tabs( '_tabs_background' );
787
788 $this->start_controls_tab(
789 '_tab_background_normal',
790 [
791 'label' => esc_html__( 'Normal', 'elementor' ),
792 ]
793 );
794
795 $this->add_group_control(
796 Group_Control_Background::get_type(),
797 [
798 'name' => '_background',
799 'selector' => static::WRAPPER_SELECTOR_CHILD,
800 ]
801 );
802
803 $this->end_controls_tab();
804
805 $this->start_controls_tab(
806 '_tab_background_hover',
807 [
808 'label' => esc_html__( 'Hover', 'elementor' ),
809 ]
810 );
811
812 $this->add_group_control(
813 Group_Control_Background::get_type(),
814 [
815 'name' => '_background_hover',
816 'selector' => static::WRAPPER_SELECTOR_HOVER,
817 ]
818 );
819
820 $this->add_control(
821 '_background_hover_transition',
822 [
823 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
824 'type' => Controls_Manager::SLIDER,
825 'range' => [
826 'px' => [
827 'min' => 0,
828 'max' => 3,
829 'step' => 0.1,
830 ],
831 ],
832 'render_type' => 'ui',
833 'separator' => 'before',
834 'selectors' => [
835 static::WRAPPER_SELECTOR_CHILD => 'transition: background {{SIZE}}s',
836 ],
837 ]
838 );
839
840 $this->end_controls_tab();
841
842 $this->end_controls_tabs();
843
844 $this->end_controls_section();
845 }
846
847 /**
848 * Register the Border section.
849 *
850 * @return void
851 */
852 private function register_border_section() {
853 $this->start_controls_section(
854 '_section_border',
855 [
856 'label' => esc_html__( 'Border', 'elementor' ),
857 'tab' => Controls_Manager::TAB_ADVANCED,
858 ]
859 );
860
861 $this->start_controls_tabs( '_tabs_border' );
862
863 $this->start_controls_tab(
864 '_tab_border_normal',
865 [
866 'label' => esc_html__( 'Normal', 'elementor' ),
867 ]
868 );
869
870 $this->add_group_control(
871 Group_Control_Border::get_type(),
872 [
873 'name' => '_border',
874 'selector' => static::WRAPPER_SELECTOR_CHILD,
875 ]
876 );
877
878 $this->add_responsive_control(
879 '_border_radius',
880 [
881 'label' => esc_html__( 'Border Radius', 'elementor' ),
882 'type' => Controls_Manager::DIMENSIONS,
883 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
884 'selectors' => [
885 static::WRAPPER_SELECTOR_CHILD => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
886 ],
887 ]
888 );
889
890 $this->add_group_control(
891 Group_Control_Box_Shadow::get_type(),
892 [
893 'name' => '_box_shadow',
894 'selector' => static::WRAPPER_SELECTOR_CHILD,
895 ]
896 );
897
898 $this->end_controls_tab();
899
900 $this->start_controls_tab(
901 '_tab_border_hover',
902 [
903 'label' => esc_html__( 'Hover', 'elementor' ),
904 ]
905 );
906
907 $this->add_group_control(
908 Group_Control_Border::get_type(),
909 [
910 'name' => '_border_hover',
911 'selector' => static::WRAPPER_SELECTOR_HOVER,
912 ]
913 );
914
915 $this->add_responsive_control(
916 '_border_radius_hover',
917 [
918 'label' => esc_html__( 'Border Radius', 'elementor' ),
919 'type' => Controls_Manager::DIMENSIONS,
920 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
921 'selectors' => [
922 static::WRAPPER_SELECTOR_HOVER_CHILD => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
923 ],
924 ]
925 );
926
927 $this->add_group_control(
928 Group_Control_Box_Shadow::get_type(),
929 [
930 'name' => '_box_shadow_hover',
931 'selector' => static::WRAPPER_SELECTOR_HOVER,
932 ]
933 );
934
935 $this->add_control(
936 '_border_hover_transition',
937 [
938 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
939 'type' => Controls_Manager::SLIDER,
940 'separator' => 'before',
941 'range' => [
942 'px' => [
943 'min' => 0,
944 'max' => 3,
945 'step' => 0.1,
946 ],
947 ],
948 'selectors' => [
949 static::WRAPPER_SELECTOR => 'transition: background {{_background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s',
950 ],
951 ]
952 );
953
954 $this->end_controls_tab();
955
956 $this->end_controls_tabs();
957
958 $this->end_controls_section();
959 }
960
961
962 /**
963 * Register the Mask section.
964 *
965 * @return void
966 */
967 private function register_masking_section() {
968 $this->start_controls_section(
969 '_section_masking',
970 [
971 'label' => esc_html__( 'Mask', 'elementor' ),
972 'tab' => Controls_Manager::TAB_ADVANCED,
973 ]
974 );
975
976 $this->add_control(
977 '_mask_switch',
978 [
979 'label' => esc_html__( 'Mask', 'elementor' ),
980 'type' => Controls_Manager::SWITCHER,
981 'label_on' => esc_html__( 'On', 'elementor' ),
982 'label_off' => esc_html__( 'Off', 'elementor' ),
983 'default' => '',
984 ]
985 );
986
987 $this->add_control(
988 '_mask_shape',
989 [
990 'label' => esc_html__( 'Shape', 'elementor' ),
991 'type' => Controls_Manager::SELECT,
992 'options' => $this->get_shapes(),
993 'default' => 'circle',
994 'selectors' => $this->get_mask_selectors( '-webkit-mask-image: url( ' . ELEMENTOR_ASSETS_URL . '/mask-shapes/{{VALUE}}.svg );' ),
995 'condition' => [
996 '_mask_switch!' => '',
997 ],
998 ]
999 );
1000
1001 $this->add_control(
1002 '_mask_image',
1003 [
1004 'label' => esc_html__( 'Image', 'elementor' ),
1005 'type' => Controls_Manager::MEDIA,
1006 'media_types' => [ 'image' ],
1007 'should_include_svg_inline_option' => true,
1008 'library_type' => 'image/svg+xml',
1009 'dynamic' => [
1010 'active' => true,
1011 ],
1012 'selectors' => $this->get_mask_selectors( '-webkit-mask-image: url( {{URL}} );' ),
1013 'condition' => [
1014 '_mask_switch!' => '',
1015 '_mask_shape' => 'custom',
1016 ],
1017 ]
1018 );
1019
1020 $this->add_control(
1021 '_mask_notice',
1022 [
1023 'type' => Controls_Manager::HIDDEN,
1024 'raw' => esc_html__( 'Need More Shapes?', 'elementor' ) .
1025 '<br>' .
1026 sprintf(
1027 '%1$s <a target="_blank" href="https://go.elementor.com/mask-control">%2$s</a>',
1028 esc_html__( 'Explore additional Premium Shape packs and use them in your site.', 'elementor' ),
1029 esc_html__( 'Learn more', 'elementor' ),
1030 ),
1031 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
1032 'condition' => [
1033 '_mask_switch!' => '',
1034 ],
1035 ]
1036 );
1037
1038 $this->add_responsive_control(
1039 '_mask_size',
1040 [
1041 'label' => esc_html__( 'Size', 'elementor' ),
1042 'type' => Controls_Manager::SELECT,
1043 'options' => [
1044 'contain' => esc_html__( 'Fit', 'elementor' ),
1045 'cover' => esc_html__( 'Fill', 'elementor' ),
1046 'custom' => esc_html__( 'Custom', 'elementor' ),
1047 ],
1048 'default' => 'contain',
1049 'selectors' => $this->get_mask_selectors( '-webkit-mask-size: {{VALUE}};' ),
1050 'condition' => [
1051 '_mask_switch!' => '',
1052 ],
1053 ]
1054 );
1055
1056 $this->add_responsive_control(
1057 '_mask_size_scale',
1058 [
1059 'label' => esc_html__( 'Scale', 'elementor' ),
1060 'type' => Controls_Manager::SLIDER,
1061 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1062 'range' => [
1063 'px' => [
1064 'min' => 0,
1065 'max' => 500,
1066 ],
1067 'em' => [
1068 'min' => 0,
1069 'max' => 100,
1070 ],
1071 '%' => [
1072 'min' => 0,
1073 'max' => 200,
1074 ],
1075 ],
1076 'default' => [
1077 'unit' => '%',
1078 'size' => 100,
1079 ],
1080 'selectors' => $this->get_mask_selectors( '-webkit-mask-size: {{SIZE}}{{UNIT}};' ),
1081 'condition' => [
1082 '_mask_switch!' => '',
1083 '_mask_size' => 'custom',
1084 ],
1085 ]
1086 );
1087
1088 $this->add_responsive_control(
1089 '_mask_position',
1090 [
1091 'label' => esc_html__( 'Position', 'elementor' ),
1092 'type' => Controls_Manager::SELECT,
1093 'options' => [
1094 'center center' => esc_html__( 'Center Center', 'elementor' ),
1095 'center left' => esc_html__( 'Center Left', 'elementor' ),
1096 'center right' => esc_html__( 'Center Right', 'elementor' ),
1097 'top center' => esc_html__( 'Top Center', 'elementor' ),
1098 'top left' => esc_html__( 'Top Left', 'elementor' ),
1099 'top right' => esc_html__( 'Top Right', 'elementor' ),
1100 'bottom center' => esc_html__( 'Bottom Center', 'elementor' ),
1101 'bottom left' => esc_html__( 'Bottom Left', 'elementor' ),
1102 'bottom right' => esc_html__( 'Bottom Right', 'elementor' ),
1103 'custom' => esc_html__( 'Custom', 'elementor' ),
1104 ],
1105 'default' => 'center center',
1106 'selectors' => $this->get_mask_selectors( '-webkit-mask-position: {{VALUE}};' ),
1107 'condition' => [
1108 '_mask_switch!' => '',
1109 ],
1110 ]
1111 );
1112
1113 $this->add_responsive_control(
1114 '_mask_position_x',
1115 [
1116 'label' => esc_html__( 'X Position', 'elementor' ),
1117 'type' => Controls_Manager::SLIDER,
1118 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1119 'range' => [
1120 'px' => [
1121 'min' => -500,
1122 'max' => 500,
1123 ],
1124 'em' => [
1125 'min' => -100,
1126 'max' => 100,
1127 ],
1128 '%' => [
1129 'min' => -100,
1130 'max' => 100,
1131 ],
1132 'vw' => [
1133 'min' => -100,
1134 'max' => 100,
1135 ],
1136 ],
1137 'default' => [
1138 'unit' => '%',
1139 'size' => 0,
1140 ],
1141 'selectors' => $this->get_mask_selectors( '-webkit-mask-position-x: {{SIZE}}{{UNIT}};' ),
1142 'condition' => [
1143 '_mask_switch!' => '',
1144 '_mask_position' => 'custom',
1145 ],
1146 ]
1147 );
1148
1149 $this->add_responsive_control(
1150 '_mask_position_y',
1151 [
1152 'label' => esc_html__( 'Y Position', 'elementor' ),
1153 'type' => Controls_Manager::SLIDER,
1154 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1155 'range' => [
1156 'px' => [
1157 'min' => -500,
1158 'max' => 500,
1159 ],
1160 'em' => [
1161 'min' => -100,
1162 'max' => 100,
1163 ],
1164 '%' => [
1165 'min' => -100,
1166 'max' => 100,
1167 ],
1168 'vw' => [
1169 'min' => -100,
1170 'max' => 100,
1171 ],
1172 ],
1173 'default' => [
1174 'unit' => '%',
1175 'size' => 0,
1176 ],
1177 'selectors' => $this->get_mask_selectors( '-webkit-mask-position-y: {{SIZE}}{{UNIT}};' ),
1178 'condition' => [
1179 '_mask_switch!' => '',
1180 '_mask_position' => 'custom',
1181 ],
1182 ]
1183 );
1184
1185 $this->add_responsive_control(
1186 '_mask_repeat',
1187 [
1188 'label' => esc_html__( 'Repeat', 'elementor' ),
1189 'type' => Controls_Manager::SELECT,
1190 'options' => [
1191 'no-repeat' => esc_html__( 'No-repeat', 'elementor' ),
1192 'repeat' => esc_html__( 'Repeat', 'elementor' ),
1193 'repeat-x' => esc_html__( 'Repeat-x', 'elementor' ),
1194 'repeat-Y' => esc_html__( 'Repeat-y', 'elementor' ),
1195 'round' => esc_html__( 'Round', 'elementor' ),
1196 'space' => esc_html__( 'Space', 'elementor' ),
1197 ],
1198 'default' => 'no-repeat',
1199 'selectors' => $this->get_mask_selectors( '-webkit-mask-repeat: {{VALUE}};' ),
1200 'condition' => [
1201 '_mask_switch!' => '',
1202 '_mask_size!' => 'cover',
1203 ],
1204 ]
1205 );
1206
1207 $this->end_controls_section();
1208 }
1209
1210
1211 /**
1212 * Register the Responsive section.
1213 *
1214 * @return void
1215 */
1216 private function register_responsive_section() {
1217 $this->start_controls_section(
1218 '_section_responsive',
1219 [
1220 'label' => esc_html__( 'Responsive', 'elementor' ),
1221 'tab' => Controls_Manager::TAB_ADVANCED,
1222 ]
1223 );
1224
1225 $this->add_control(
1226 'responsive_description',
1227 [
1228 'raw' => sprintf(
1229 /* translators: 1: Link open tag, 2: Link close tag. */
1230 esc_html__( 'Responsive visibility will take effect only on %1$s preview mode %2$s or live page, and not while editing in Elementor.', 'elementor' ),
1231 '<a href="javascript: $e.run( \'panel/close\' )">',
1232 '</a>'
1233 ),
1234 'type' => Controls_Manager::RAW_HTML,
1235 'content_classes' => 'elementor-descriptor',
1236 ]
1237 );
1238
1239 $this->add_hidden_device_controls();
1240
1241 $this->end_controls_section();
1242 }
1243
1244 /**
1245 * Register common widget controls.
1246 *
1247 * Adds different input fields to allow the user to change and customize the widget settings.
1248 *
1249 * @since 3.1.0
1250 * @access protected
1251 */
1252 protected function register_controls() {
1253 $this->register_layout_section();
1254
1255 $this->register_effects_section();
1256
1257 $this->register_transform_section( '', static::TRANSFORM_SELECTOR_CLASS );
1258
1259 $this->register_background_section();
1260
1261 $this->register_border_section();
1262
1263 $this->register_masking_section();
1264
1265 $this->register_responsive_section();
1266
1267 $register_common_controls = apply_filters(
1268 'elementor/widget/common/register_css_attributes_control',
1269 true,
1270 $this
1271 );
1272
1273 if ( $register_common_controls ) {
1274 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1275
1276 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1277 }
1278 }
1279 }
1280