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