icon-list.php (19083B)
1 <?php 2 namespace Elementor; 3 4 if ( ! defined( 'ABSPATH' ) ) { 5 exit; // Exit if accessed directly. 6 } 7 8 use Elementor\Core\Kits\Documents\Tabs\Global_Colors; 9 use Elementor\Core\Kits\Documents\Tabs\Global_Typography; 10 11 /** 12 * Elementor icon list widget. 13 * 14 * Elementor widget that displays a bullet list with any chosen icons and texts. 15 * 16 * @since 1.0.0 17 */ 18 class Widget_Icon_List extends Widget_Base { 19 20 /** 21 * Get widget name. 22 * 23 * Retrieve icon list widget name. 24 * 25 * @since 1.0.0 26 * @access public 27 * 28 * @return string Widget name. 29 */ 30 public function get_name() { 31 return 'icon-list'; 32 } 33 34 /** 35 * Get widget title. 36 * 37 * Retrieve icon list widget title. 38 * 39 * @since 1.0.0 40 * @access public 41 * 42 * @return string Widget title. 43 */ 44 public function get_title() { 45 return esc_html__( 'Icon List', 'elementor' ); 46 } 47 48 /** 49 * Get widget icon. 50 * 51 * Retrieve icon list widget icon. 52 * 53 * @since 1.0.0 54 * @access public 55 * 56 * @return string Widget icon. 57 */ 58 public function get_icon() { 59 return 'eicon-bullet-list'; 60 } 61 62 /** 63 * Get widget keywords. 64 * 65 * Retrieve the list of keywords the widget belongs to. 66 * 67 * @since 2.1.0 68 * @access public 69 * 70 * @return array Widget keywords. 71 */ 72 public function get_keywords() { 73 return [ 'icon list', 'icon', 'list' ]; 74 } 75 76 /** 77 * Register icon list widget controls. 78 * 79 * Adds different input fields to allow the user to change and customize the widget settings. 80 * 81 * @since 3.1.0 82 * @access protected 83 */ 84 protected function register_controls() { 85 $this->start_controls_section( 86 'section_icon', 87 [ 88 'label' => esc_html__( 'Icon List', 'elementor' ), 89 ] 90 ); 91 92 $this->add_control( 93 'view', 94 [ 95 'label' => esc_html__( 'Layout', 'elementor' ), 96 'type' => Controls_Manager::CHOOSE, 97 'default' => 'traditional', 98 'options' => [ 99 'traditional' => [ 100 'title' => esc_html__( 'Default', 'elementor' ), 101 'icon' => 'eicon-editor-list-ul', 102 ], 103 'inline' => [ 104 'title' => esc_html__( 'Inline', 'elementor' ), 105 'icon' => 'eicon-ellipsis-h', 106 ], 107 ], 108 'render_type' => 'template', 109 'classes' => 'elementor-control-start-end', 110 'style_transfer' => true, 111 'prefix_class' => 'elementor-icon-list--layout-', 112 ] 113 ); 114 115 $repeater = new Repeater(); 116 117 $repeater->add_control( 118 'text', 119 [ 120 'label' => esc_html__( 'Text', 'elementor' ), 121 'type' => Controls_Manager::TEXT, 122 'label_block' => true, 123 'placeholder' => esc_html__( 'List Item', 'elementor' ), 124 'default' => esc_html__( 'List Item', 'elementor' ), 125 'dynamic' => [ 126 'active' => true, 127 ], 128 ] 129 ); 130 131 $repeater->add_control( 132 'selected_icon', 133 [ 134 'label' => esc_html__( 'Icon', 'elementor' ), 135 'type' => Controls_Manager::ICONS, 136 'default' => [ 137 'value' => 'fas fa-check', 138 'library' => 'fa-solid', 139 ], 140 'fa4compatibility' => 'icon', 141 ] 142 ); 143 144 $repeater->add_control( 145 'link', 146 [ 147 'label' => esc_html__( 'Link', 'elementor' ), 148 'type' => Controls_Manager::URL, 149 'dynamic' => [ 150 'active' => true, 151 ], 152 'placeholder' => esc_html__( 'https://your-link.com', 'elementor' ), 153 ] 154 ); 155 156 $this->add_control( 157 'icon_list', 158 [ 159 'label' => esc_html__( 'Items', 'elementor' ), 160 'type' => Controls_Manager::REPEATER, 161 'fields' => $repeater->get_controls(), 162 'default' => [ 163 [ 164 'text' => esc_html__( 'List Item #1', 'elementor' ), 165 'selected_icon' => [ 166 'value' => 'fas fa-check', 167 'library' => 'fa-solid', 168 ], 169 ], 170 [ 171 'text' => esc_html__( 'List Item #2', 'elementor' ), 172 'selected_icon' => [ 173 'value' => 'fas fa-times', 174 'library' => 'fa-solid', 175 ], 176 ], 177 [ 178 'text' => esc_html__( 'List Item #3', 'elementor' ), 179 'selected_icon' => [ 180 'value' => 'fas fa-dot-circle', 181 'library' => 'fa-solid', 182 ], 183 ], 184 ], 185 'title_field' => '{{{ elementor.helpers.renderIcon( this, selected_icon, {}, "i", "panel" ) || \'<i class="{{ icon }}" aria-hidden="true"></i>\' }}} {{{ text }}}', 186 ] 187 ); 188 189 $this->add_control( 190 'link_click', 191 [ 192 'label' => esc_html__( 'Apply Link On', 'elementor' ), 193 'type' => Controls_Manager::SELECT, 194 'options' => [ 195 'full_width' => esc_html__( 'Full Width', 'elementor' ), 196 'inline' => esc_html__( 'Inline', 'elementor' ), 197 ], 198 'default' => 'full_width', 199 'separator' => 'before', 200 'prefix_class' => 'elementor-list-item-link-', 201 ] 202 ); 203 204 $this->end_controls_section(); 205 206 $this->start_controls_section( 207 'section_icon_list', 208 [ 209 'label' => esc_html__( 'List', 'elementor' ), 210 'tab' => Controls_Manager::TAB_STYLE, 211 ] 212 ); 213 214 $this->add_responsive_control( 215 'space_between', 216 [ 217 'label' => esc_html__( 'Space Between', 'elementor' ), 218 'type' => Controls_Manager::SLIDER, 219 'range' => [ 220 'px' => [ 221 'max' => 50, 222 ], 223 ], 224 'selectors' => [ 225 '{{WRAPPER}} .elementor-icon-list-items:not(.elementor-inline-items) .elementor-icon-list-item:not(:last-child)' => 'padding-bottom: calc({{SIZE}}{{UNIT}}/2)', 226 '{{WRAPPER}} .elementor-icon-list-items:not(.elementor-inline-items) .elementor-icon-list-item:not(:first-child)' => 'margin-top: calc({{SIZE}}{{UNIT}}/2)', 227 '{{WRAPPER}} .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item' => 'margin-right: calc({{SIZE}}{{UNIT}}/2); margin-left: calc({{SIZE}}{{UNIT}}/2)', 228 '{{WRAPPER}} .elementor-icon-list-items.elementor-inline-items' => 'margin-right: calc(-{{SIZE}}{{UNIT}}/2); margin-left: calc(-{{SIZE}}{{UNIT}}/2)', 229 'body.rtl {{WRAPPER}} .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item:after' => 'left: calc(-{{SIZE}}{{UNIT}}/2)', 230 'body:not(.rtl) {{WRAPPER}} .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item:after' => 'right: calc(-{{SIZE}}{{UNIT}}/2)', 231 ], 232 ] 233 ); 234 235 $this->add_responsive_control( 236 'icon_align', 237 [ 238 'label' => esc_html__( 'Alignment', 'elementor' ), 239 'type' => Controls_Manager::CHOOSE, 240 'options' => [ 241 'left' => [ 242 'title' => esc_html__( 'Left', 'elementor' ), 243 'icon' => 'eicon-h-align-left', 244 ], 245 'center' => [ 246 'title' => esc_html__( 'Center', 'elementor' ), 247 'icon' => 'eicon-h-align-center', 248 ], 249 'right' => [ 250 'title' => esc_html__( 'Right', 'elementor' ), 251 'icon' => 'eicon-h-align-right', 252 ], 253 ], 254 'prefix_class' => 'elementor%s-align-', 255 ] 256 ); 257 258 $this->add_control( 259 'divider', 260 [ 261 'label' => esc_html__( 'Divider', 'elementor' ), 262 'type' => Controls_Manager::SWITCHER, 263 'label_off' => esc_html__( 'Off', 'elementor' ), 264 'label_on' => esc_html__( 'On', 'elementor' ), 265 'selectors' => [ 266 '{{WRAPPER}} .elementor-icon-list-item:not(:last-child):after' => 'content: ""', 267 ], 268 'separator' => 'before', 269 ] 270 ); 271 272 $this->add_control( 273 'divider_style', 274 [ 275 'label' => esc_html__( 'Style', 'elementor' ), 276 'type' => Controls_Manager::SELECT, 277 'options' => [ 278 'solid' => esc_html__( 'Solid', 'elementor' ), 279 'double' => esc_html__( 'Double', 'elementor' ), 280 'dotted' => esc_html__( 'Dotted', 'elementor' ), 281 'dashed' => esc_html__( 'Dashed', 'elementor' ), 282 ], 283 'default' => 'solid', 284 'condition' => [ 285 'divider' => 'yes', 286 ], 287 'selectors' => [ 288 '{{WRAPPER}} .elementor-icon-list-items:not(.elementor-inline-items) .elementor-icon-list-item:not(:last-child):after' => 'border-top-style: {{VALUE}}', 289 '{{WRAPPER}} .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item:not(:last-child):after' => 'border-left-style: {{VALUE}}', 290 ], 291 ] 292 ); 293 294 $this->add_control( 295 'divider_weight', 296 [ 297 'label' => esc_html__( 'Weight', 'elementor' ), 298 'type' => Controls_Manager::SLIDER, 299 'default' => [ 300 'size' => 1, 301 ], 302 'range' => [ 303 'px' => [ 304 'min' => 1, 305 'max' => 20, 306 ], 307 ], 308 'condition' => [ 309 'divider' => 'yes', 310 ], 311 'selectors' => [ 312 '{{WRAPPER}} .elementor-icon-list-items:not(.elementor-inline-items) .elementor-icon-list-item:not(:last-child):after' => 'border-top-width: {{SIZE}}{{UNIT}}', 313 '{{WRAPPER}} .elementor-inline-items .elementor-icon-list-item:not(:last-child):after' => 'border-left-width: {{SIZE}}{{UNIT}}', 314 ], 315 ] 316 ); 317 318 $this->add_control( 319 'divider_width', 320 [ 321 'label' => esc_html__( 'Width', 'elementor' ), 322 'type' => Controls_Manager::SLIDER, 323 'default' => [ 324 'unit' => '%', 325 ], 326 'condition' => [ 327 'divider' => 'yes', 328 'view!' => 'inline', 329 ], 330 'selectors' => [ 331 '{{WRAPPER}} .elementor-icon-list-item:not(:last-child):after' => 'width: {{SIZE}}{{UNIT}}', 332 ], 333 ] 334 ); 335 336 $this->add_control( 337 'divider_height', 338 [ 339 'label' => esc_html__( 'Height', 'elementor' ), 340 'type' => Controls_Manager::SLIDER, 341 'size_units' => [ '%', 'px' ], 342 'default' => [ 343 'unit' => '%', 344 ], 345 'range' => [ 346 'px' => [ 347 'min' => 1, 348 'max' => 100, 349 ], 350 '%' => [ 351 'min' => 1, 352 'max' => 100, 353 ], 354 ], 355 'condition' => [ 356 'divider' => 'yes', 357 'view' => 'inline', 358 ], 359 'selectors' => [ 360 '{{WRAPPER}} .elementor-icon-list-item:not(:last-child):after' => 'height: {{SIZE}}{{UNIT}}', 361 ], 362 ] 363 ); 364 365 $this->add_control( 366 'divider_color', 367 [ 368 'label' => esc_html__( 'Color', 'elementor' ), 369 'type' => Controls_Manager::COLOR, 370 'default' => '#ddd', 371 'global' => [ 372 'default' => Global_Colors::COLOR_TEXT, 373 ], 374 'condition' => [ 375 'divider' => 'yes', 376 ], 377 'selectors' => [ 378 '{{WRAPPER}} .elementor-icon-list-item:not(:last-child):after' => 'border-color: {{VALUE}}', 379 ], 380 ] 381 ); 382 383 $this->end_controls_section(); 384 385 $this->start_controls_section( 386 'section_icon_style', 387 [ 388 'label' => esc_html__( 'Icon', 'elementor' ), 389 'tab' => Controls_Manager::TAB_STYLE, 390 ] 391 ); 392 393 $this->add_control( 394 'icon_color', 395 [ 396 'label' => esc_html__( 'Color', 'elementor' ), 397 'type' => Controls_Manager::COLOR, 398 'default' => '', 399 'selectors' => [ 400 '{{WRAPPER}} .elementor-icon-list-icon i' => 'color: {{VALUE}};', 401 '{{WRAPPER}} .elementor-icon-list-icon svg' => 'fill: {{VALUE}};', 402 ], 403 'global' => [ 404 'default' => Global_Colors::COLOR_PRIMARY, 405 ], 406 ] 407 ); 408 409 $this->add_control( 410 'icon_color_hover', 411 [ 412 'label' => esc_html__( 'Hover', 'elementor' ), 413 'type' => Controls_Manager::COLOR, 414 'default' => '', 415 'selectors' => [ 416 '{{WRAPPER}} .elementor-icon-list-item:hover .elementor-icon-list-icon i' => 'color: {{VALUE}};', 417 '{{WRAPPER}} .elementor-icon-list-item:hover .elementor-icon-list-icon svg' => 'fill: {{VALUE}};', 418 ], 419 ] 420 ); 421 422 $this->add_responsive_control( 423 'icon_size', 424 [ 425 'label' => esc_html__( 'Size', 'elementor' ), 426 'type' => Controls_Manager::SLIDER, 427 'default' => [ 428 'size' => 14, 429 ], 430 'range' => [ 431 'px' => [ 432 'min' => 6, 433 ], 434 ], 435 'selectors' => [ 436 '{{WRAPPER}}' => '--e-icon-list-icon-size: {{SIZE}}{{UNIT}};', 437 ], 438 ] 439 ); 440 441 $e_icon_list_icon_css_var = 'var(--e-icon-list-icon-size, 1em)'; 442 $e_icon_list_icon_align_left = sprintf( '0 calc(%s * 0.25) 0 0', $e_icon_list_icon_css_var ); 443 $e_icon_list_icon_align_center = sprintf( '0 calc(%s * 0.125)', $e_icon_list_icon_css_var ); 444 $e_icon_list_icon_align_right = sprintf( '0 0 0 calc(%s * 0.25)', $e_icon_list_icon_css_var ); 445 446 $this->add_responsive_control( 447 'icon_self_align', 448 [ 449 'label' => esc_html__( 'Alignment', 'elementor' ), 450 'type' => Controls_Manager::CHOOSE, 451 'options' => [ 452 'left' => [ 453 'title' => esc_html__( 'Left', 'elementor' ), 454 'icon' => 'eicon-h-align-left', 455 ], 456 'center' => [ 457 'title' => esc_html__( 'Center', 'elementor' ), 458 'icon' => 'eicon-h-align-center', 459 ], 460 'right' => [ 461 'title' => esc_html__( 'Right', 'elementor' ), 462 'icon' => 'eicon-h-align-right', 463 ], 464 ], 465 'default' => '', 466 'selectors_dictionary' => [ 467 'left' => sprintf( '--e-icon-list-icon-align: left; --e-icon-list-icon-margin: %s;', $e_icon_list_icon_align_left ), 468 'center' => sprintf( '--e-icon-list-icon-align: center; --e-icon-list-icon-margin: %s;', $e_icon_list_icon_align_center ), 469 'right' => sprintf( '--e-icon-list-icon-align: right; --e-icon-list-icon-margin: %s;', $e_icon_list_icon_align_right ), 470 ], 471 'selectors' => [ 472 '{{WRAPPER}}' => '{{VALUE}}', 473 ], 474 ] 475 ); 476 477 $this->end_controls_section(); 478 479 $this->start_controls_section( 480 'section_text_style', 481 [ 482 'label' => esc_html__( 'Text', 'elementor' ), 483 'tab' => Controls_Manager::TAB_STYLE, 484 ] 485 ); 486 487 $this->add_control( 488 'text_color', 489 [ 490 'label' => esc_html__( 'Text Color', 'elementor' ), 491 'type' => Controls_Manager::COLOR, 492 'default' => '', 493 'selectors' => [ 494 '{{WRAPPER}} .elementor-icon-list-text' => 'color: {{VALUE}};', 495 ], 496 'global' => [ 497 'default' => Global_Colors::COLOR_SECONDARY, 498 ], 499 ] 500 ); 501 502 $this->add_control( 503 'text_color_hover', 504 [ 505 'label' => esc_html__( 'Hover', 'elementor' ), 506 'type' => Controls_Manager::COLOR, 507 'default' => '', 508 'selectors' => [ 509 '{{WRAPPER}} .elementor-icon-list-item:hover .elementor-icon-list-text' => 'color: {{VALUE}};', 510 ], 511 ] 512 ); 513 514 $this->add_control( 515 'text_indent', 516 [ 517 'label' => esc_html__( 'Text Indent', 'elementor' ), 518 'type' => Controls_Manager::SLIDER, 519 'range' => [ 520 'px' => [ 521 'max' => 50, 522 ], 523 ], 524 'selectors' => [ 525 '{{WRAPPER}} .elementor-icon-list-text' => is_rtl() ? 'padding-right: {{SIZE}}{{UNIT}};' : 'padding-left: {{SIZE}}{{UNIT}};', 526 ], 527 ] 528 ); 529 530 $this->add_group_control( 531 Group_Control_Typography::get_type(), 532 [ 533 'name' => 'icon_typography', 534 'selector' => '{{WRAPPER}} .elementor-icon-list-item > .elementor-icon-list-text, {{WRAPPER}} .elementor-icon-list-item > a', 535 'global' => [ 536 'default' => Global_Typography::TYPOGRAPHY_TEXT, 537 ], 538 ] 539 ); 540 541 $this->add_group_control( 542 Group_Control_Text_Shadow::get_type(), 543 [ 544 'name' => 'text_shadow', 545 'selector' => '{{WRAPPER}} .elementor-icon-list-text', 546 ] 547 ); 548 549 $this->end_controls_section(); 550 } 551 552 /** 553 * Render icon list widget output on the frontend. 554 * 555 * Written in PHP and used to generate the final HTML. 556 * 557 * @since 1.0.0 558 * @access protected 559 */ 560 protected function render() { 561 $settings = $this->get_settings_for_display(); 562 $fallback_defaults = [ 563 'fa fa-check', 564 'fa fa-times', 565 'fa fa-dot-circle-o', 566 ]; 567 568 $this->add_render_attribute( 'icon_list', 'class', 'elementor-icon-list-items' ); 569 $this->add_render_attribute( 'list_item', 'class', 'elementor-icon-list-item' ); 570 571 if ( 'inline' === $settings['view'] ) { 572 $this->add_render_attribute( 'icon_list', 'class', 'elementor-inline-items' ); 573 $this->add_render_attribute( 'list_item', 'class', 'elementor-inline-item' ); 574 } 575 ?> 576 <ul <?php $this->print_render_attribute_string( 'icon_list' ); ?>> 577 <?php 578 foreach ( $settings['icon_list'] as $index => $item ) : 579 $repeater_setting_key = $this->get_repeater_setting_key( 'text', 'icon_list', $index ); 580 581 $this->add_render_attribute( $repeater_setting_key, 'class', 'elementor-icon-list-text' ); 582 583 $this->add_inline_editing_attributes( $repeater_setting_key ); 584 $migration_allowed = Icons_Manager::is_migration_allowed(); 585 ?> 586 <li <?php $this->print_render_attribute_string( 'list_item' ); ?>> 587 <?php 588 if ( ! empty( $item['link']['url'] ) ) { 589 $link_key = 'link_' . $index; 590 591 $this->add_link_attributes( $link_key, $item['link'] ); 592 ?> 593 <a <?php $this->print_render_attribute_string( $link_key ); ?>> 594 595 <?php 596 } 597 598 // add old default 599 if ( ! isset( $item['icon'] ) && ! $migration_allowed ) { 600 $item['icon'] = isset( $fallback_defaults[ $index ] ) ? $fallback_defaults[ $index ] : 'fa fa-check'; 601 } 602 603 $migrated = isset( $item['__fa4_migrated']['selected_icon'] ); 604 $is_new = ! isset( $item['icon'] ) && $migration_allowed; 605 if ( ! empty( $item['icon'] ) || ( ! empty( $item['selected_icon']['value'] ) && $is_new ) ) : 606 ?> 607 <span class="elementor-icon-list-icon"> 608 <?php 609 if ( $is_new || $migrated ) { 610 Icons_Manager::render_icon( $item['selected_icon'], [ 'aria-hidden' => 'true' ] ); 611 } else { ?> 612 <i class="<?php echo esc_attr( $item['icon'] ); ?>" aria-hidden="true"></i> 613 <?php } ?> 614 </span> 615 <?php endif; ?> 616 <span <?php $this->print_render_attribute_string( $repeater_setting_key ); ?>><?php $this->print_unescaped_setting( 'text', 'icon_list', $index ); ?></span> 617 <?php if ( ! empty( $item['link']['url'] ) ) : ?> 618 </a> 619 <?php endif; ?> 620 </li> 621 <?php 622 endforeach; 623 ?> 624 </ul> 625 <?php 626 } 627 628 /** 629 * Render icon list widget output in the editor. 630 * 631 * Written as a Backbone JavaScript template and used to generate the live preview. 632 * 633 * @since 2.9.0 634 * @access protected 635 */ 636 protected function content_template() { 637 ?> 638 <# 639 view.addRenderAttribute( 'icon_list', 'class', 'elementor-icon-list-items' ); 640 view.addRenderAttribute( 'list_item', 'class', 'elementor-icon-list-item' ); 641 642 if ( 'inline' == settings.view ) { 643 view.addRenderAttribute( 'icon_list', 'class', 'elementor-inline-items' ); 644 view.addRenderAttribute( 'list_item', 'class', 'elementor-inline-item' ); 645 } 646 var iconsHTML = {}, 647 migrated = {}; 648 #> 649 <# if ( settings.icon_list ) { #> 650 <ul {{{ view.getRenderAttributeString( 'icon_list' ) }}}> 651 <# _.each( settings.icon_list, function( item, index ) { 652 653 var iconTextKey = view.getRepeaterSettingKey( 'text', 'icon_list', index ); 654 655 view.addRenderAttribute( iconTextKey, 'class', 'elementor-icon-list-text' ); 656 657 view.addInlineEditingAttributes( iconTextKey ); #> 658 659 <li {{{ view.getRenderAttributeString( 'list_item' ) }}}> 660 <# if ( item.link && item.link.url ) { #> 661 <a href="{{ item.link.url }}"> 662 <# } #> 663 <# if ( item.icon || item.selected_icon.value ) { #> 664 <span class="elementor-icon-list-icon"> 665 <# 666 iconsHTML[ index ] = elementor.helpers.renderIcon( view, item.selected_icon, { 'aria-hidden': true }, 'i', 'object' ); 667 migrated[ index ] = elementor.helpers.isIconMigrated( item, 'selected_icon' ); 668 if ( iconsHTML[ index ] && iconsHTML[ index ].rendered && ( ! item.icon || migrated[ index ] ) ) { #> 669 {{{ iconsHTML[ index ].value }}} 670 <# } else { #> 671 <i class="{{ item.icon }}" aria-hidden="true"></i> 672 <# } 673 #> 674 </span> 675 <# } #> 676 <span {{{ view.getRenderAttributeString( iconTextKey ) }}}>{{{ item.text }}}</span> 677 <# if ( item.link && item.link.url ) { #> 678 </a> 679 <# } #> 680 </li> 681 <# 682 } ); #> 683 </ul> 684 <# } #> 685 686 <?php 687 } 688 689 public function on_import( $element ) { 690 return Icons_Manager::on_import_migration( $element, 'icon', 'selected_icon', true ); 691 } 692 }