<?php namespace Elementor; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } use Elementor\Core\Kits\Documents\Tabs\Global_Colors; use Elementor\Core\Kits\Documents\Tabs\Global_Typography; /** * Elementor icon list widget. * * Elementor widget that displays a bullet list with any chosen icons and texts. * * @since 1.0.0 */ class Widget_Icon_List extends Widget_Base { /** * Get widget name. * * Retrieve icon list widget name. * * @since 1.0.0 * @access public * * @return string Widget name. */ public function get_name() { return 'icon-list'; } /** * Get widget title. * * Retrieve icon list widget title. * * @since 1.0.0 * @access public * * @return string Widget title. */ public function get_title() { return esc_html__( 'Icon List', 'elementor' ); } /** * Get widget icon. * * Retrieve icon list widget icon. * * @since 1.0.0 * @access public * * @return string Widget icon. */ public function get_icon() { return 'eicon-bullet-list'; } /** * Get widget keywords. * * Retrieve the list of keywords the widget belongs to. * * @since 2.1.0 * @access public * * @return array Widget keywords. */ public function get_keywords() { return [ 'icon list', 'icon', 'list' ]; } /** * Register icon list widget controls. * * Adds different input fields to allow the user to change and customize the widget settings. * * @since 3.1.0 * @access protected */ protected function register_controls() { $this->start_controls_section( 'section_icon', [ 'label' => esc_html__( 'Icon List', 'elementor' ), ] ); $this->add_control( 'view', [ 'label' => esc_html__( 'Layout', 'elementor' ), 'type' => Controls_Manager::CHOOSE, 'default' => 'traditional', 'options' => [ 'traditional' => [ 'title' => esc_html__( 'Default', 'elementor' ), 'icon' => 'eicon-editor-list-ul', ], 'inline' => [ 'title' => esc_html__( 'Inline', 'elementor' ), 'icon' => 'eicon-ellipsis-h', ], ], 'render_type' => 'template', 'classes' => 'elementor-control-start-end', 'style_transfer' => true, 'prefix_class' => 'elementor-icon-list--layout-', ] ); $repeater = new Repeater(); $repeater->add_control( 'text', [ 'label' => esc_html__( 'Text', 'elementor' ), 'type' => Controls_Manager::TEXT, 'label_block' => true, 'placeholder' => esc_html__( 'List Item', 'elementor' ), 'default' => esc_html__( 'List Item', 'elementor' ), 'dynamic' => [ 'active' => true, ], ] ); $repeater->add_control( 'selected_icon', [ 'label' => esc_html__( 'Icon', 'elementor' ), 'type' => Controls_Manager::ICONS, 'default' => [ 'value' => 'fas fa-check', 'library' => 'fa-solid', ], 'fa4compatibility' => 'icon', ] ); $repeater->add_control( 'link', [ 'label' => esc_html__( 'Link', 'elementor' ), 'type' => Controls_Manager::URL, 'dynamic' => [ 'active' => true, ], 'placeholder' => esc_html__( 'https://your-link.com', 'elementor' ), ] ); $this->add_control( 'icon_list', [ 'label' => esc_html__( 'Items', 'elementor' ), 'type' => Controls_Manager::REPEATER, 'fields' => $repeater->get_controls(), 'default' => [ [ 'text' => esc_html__( 'List Item #1', 'elementor' ), 'selected_icon' => [ 'value' => 'fas fa-check', 'library' => 'fa-solid', ], ], [ 'text' => esc_html__( 'List Item #2', 'elementor' ), 'selected_icon' => [ 'value' => 'fas fa-times', 'library' => 'fa-solid', ], ], [ 'text' => esc_html__( 'List Item #3', 'elementor' ), 'selected_icon' => [ 'value' => 'fas fa-dot-circle', 'library' => 'fa-solid', ], ], ], 'title_field' => '{{{ elementor.helpers.renderIcon( this, selected_icon, {}, "i", "panel" ) || \'<i class="{{ icon }}" aria-hidden="true"></i>\' }}} {{{ text }}}', ] ); $this->add_control( 'link_click', [ 'label' => esc_html__( 'Apply Link On', 'elementor' ), 'type' => Controls_Manager::SELECT, 'options' => [ 'full_width' => esc_html__( 'Full Width', 'elementor' ), 'inline' => esc_html__( 'Inline', 'elementor' ), ], 'default' => 'full_width', 'separator' => 'before', 'prefix_class' => 'elementor-list-item-link-', ] ); $this->end_controls_section(); $this->start_controls_section( 'section_icon_list', [ 'label' => esc_html__( 'List', 'elementor' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_responsive_control( 'space_between', [ 'label' => esc_html__( 'Space Between', 'elementor' ), 'type' => Controls_Manager::SLIDER, 'range' => [ 'px' => [ 'max' => 50, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-items:not(.elementor-inline-items) .elementor-icon-list-item:not(:last-child)' => 'padding-bottom: calc({{SIZE}}{{UNIT}}/2)', '{{WRAPPER}} .elementor-icon-list-items:not(.elementor-inline-items) .elementor-icon-list-item:not(:first-child)' => 'margin-top: calc({{SIZE}}{{UNIT}}/2)', '{{WRAPPER}} .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item' => 'margin-right: calc({{SIZE}}{{UNIT}}/2); margin-left: calc({{SIZE}}{{UNIT}}/2)', '{{WRAPPER}} .elementor-icon-list-items.elementor-inline-items' => 'margin-right: calc(-{{SIZE}}{{UNIT}}/2); margin-left: calc(-{{SIZE}}{{UNIT}}/2)', 'body.rtl {{WRAPPER}} .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item:after' => 'left: calc(-{{SIZE}}{{UNIT}}/2)', 'body:not(.rtl) {{WRAPPER}} .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item:after' => 'right: calc(-{{SIZE}}{{UNIT}}/2)', ], ] ); $this->add_responsive_control( 'icon_align', [ 'label' => esc_html__( 'Alignment', 'elementor' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor' ), 'icon' => 'eicon-h-align-left', ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor' ), 'icon' => 'eicon-h-align-center', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor' ), 'icon' => 'eicon-h-align-right', ], ], 'prefix_class' => 'elementor%s-align-', ] ); $this->add_control( 'divider', [ 'label' => esc_html__( 'Divider', 'elementor' ), 'type' => Controls_Manager::SWITCHER, 'label_off' => esc_html__( 'Off', 'elementor' ), 'label_on' => esc_html__( 'On', 'elementor' ), 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-item:not(:last-child):after' => 'content: ""', ], 'separator' => 'before', ] ); $this->add_control( 'divider_style', [ 'label' => esc_html__( 'Style', 'elementor' ), 'type' => Controls_Manager::SELECT, 'options' => [ 'solid' => esc_html__( 'Solid', 'elementor' ), 'double' => esc_html__( 'Double', 'elementor' ), 'dotted' => esc_html__( 'Dotted', 'elementor' ), 'dashed' => esc_html__( 'Dashed', 'elementor' ), ], 'default' => 'solid', 'condition' => [ 'divider' => 'yes', ], 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-items:not(.elementor-inline-items) .elementor-icon-list-item:not(:last-child):after' => 'border-top-style: {{VALUE}}', '{{WRAPPER}} .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item:not(:last-child):after' => 'border-left-style: {{VALUE}}', ], ] ); $this->add_control( 'divider_weight', [ 'label' => esc_html__( 'Weight', 'elementor' ), 'type' => Controls_Manager::SLIDER, 'default' => [ 'size' => 1, ], 'range' => [ 'px' => [ 'min' => 1, 'max' => 20, ], ], 'condition' => [ 'divider' => 'yes', ], 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-items:not(.elementor-inline-items) .elementor-icon-list-item:not(:last-child):after' => 'border-top-width: {{SIZE}}{{UNIT}}', '{{WRAPPER}} .elementor-inline-items .elementor-icon-list-item:not(:last-child):after' => 'border-left-width: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'divider_width', [ 'label' => esc_html__( 'Width', 'elementor' ), 'type' => Controls_Manager::SLIDER, 'default' => [ 'unit' => '%', ], 'condition' => [ 'divider' => 'yes', 'view!' => 'inline', ], 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-item:not(:last-child):after' => 'width: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'divider_height', [ 'label' => esc_html__( 'Height', 'elementor' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ '%', 'px' ], 'default' => [ 'unit' => '%', ], 'range' => [ 'px' => [ 'min' => 1, 'max' => 100, ], '%' => [ 'min' => 1, 'max' => 100, ], ], 'condition' => [ 'divider' => 'yes', 'view' => 'inline', ], 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-item:not(:last-child):after' => 'height: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'divider_color', [ 'label' => esc_html__( 'Color', 'elementor' ), 'type' => Controls_Manager::COLOR, 'default' => '#ddd', 'global' => [ 'default' => Global_Colors::COLOR_TEXT, ], 'condition' => [ 'divider' => 'yes', ], 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-item:not(:last-child):after' => 'border-color: {{VALUE}}', ], ] ); $this->end_controls_section(); $this->start_controls_section( 'section_icon_style', [ 'label' => esc_html__( 'Icon', 'elementor' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'icon_color', [ 'label' => esc_html__( 'Color', 'elementor' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-icon i' => 'color: {{VALUE}};', '{{WRAPPER}} .elementor-icon-list-icon svg' => 'fill: {{VALUE}};', ], 'global' => [ 'default' => Global_Colors::COLOR_PRIMARY, ], ] ); $this->add_control( 'icon_color_hover', [ 'label' => esc_html__( 'Hover', 'elementor' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-item:hover .elementor-icon-list-icon i' => 'color: {{VALUE}};', '{{WRAPPER}} .elementor-icon-list-item:hover .elementor-icon-list-icon svg' => 'fill: {{VALUE}};', ], ] ); $this->add_responsive_control( 'icon_size', [ 'label' => esc_html__( 'Size', 'elementor' ), 'type' => Controls_Manager::SLIDER, 'default' => [ 'size' => 14, ], 'range' => [ 'px' => [ 'min' => 6, ], ], 'selectors' => [ '{{WRAPPER}}' => '--e-icon-list-icon-size: {{SIZE}}{{UNIT}};', ], ] ); $e_icon_list_icon_css_var = 'var(--e-icon-list-icon-size, 1em)'; $e_icon_list_icon_align_left = sprintf( '0 calc(%s * 0.25) 0 0', $e_icon_list_icon_css_var ); $e_icon_list_icon_align_center = sprintf( '0 calc(%s * 0.125)', $e_icon_list_icon_css_var ); $e_icon_list_icon_align_right = sprintf( '0 0 0 calc(%s * 0.25)', $e_icon_list_icon_css_var ); $this->add_responsive_control( 'icon_self_align', [ 'label' => esc_html__( 'Alignment', 'elementor' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor' ), 'icon' => 'eicon-h-align-left', ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor' ), 'icon' => 'eicon-h-align-center', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor' ), 'icon' => 'eicon-h-align-right', ], ], 'default' => '', 'selectors_dictionary' => [ 'left' => sprintf( '--e-icon-list-icon-align: left; --e-icon-list-icon-margin: %s;', $e_icon_list_icon_align_left ), 'center' => sprintf( '--e-icon-list-icon-align: center; --e-icon-list-icon-margin: %s;', $e_icon_list_icon_align_center ), 'right' => sprintf( '--e-icon-list-icon-align: right; --e-icon-list-icon-margin: %s;', $e_icon_list_icon_align_right ), ], 'selectors' => [ '{{WRAPPER}}' => '{{VALUE}}', ], ] ); $this->end_controls_section(); $this->start_controls_section( 'section_text_style', [ 'label' => esc_html__( 'Text', 'elementor' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'text_color', [ 'label' => esc_html__( 'Text Color', 'elementor' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-text' => 'color: {{VALUE}};', ], 'global' => [ 'default' => Global_Colors::COLOR_SECONDARY, ], ] ); $this->add_control( 'text_color_hover', [ 'label' => esc_html__( 'Hover', 'elementor' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-item:hover .elementor-icon-list-text' => 'color: {{VALUE}};', ], ] ); $this->add_control( 'text_indent', [ 'label' => esc_html__( 'Text Indent', 'elementor' ), 'type' => Controls_Manager::SLIDER, 'range' => [ 'px' => [ 'max' => 50, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-icon-list-text' => is_rtl() ? 'padding-right: {{SIZE}}{{UNIT}};' : 'padding-left: {{SIZE}}{{UNIT}};', ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'icon_typography', 'selector' => '{{WRAPPER}} .elementor-icon-list-item > .elementor-icon-list-text, {{WRAPPER}} .elementor-icon-list-item > a', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_TEXT, ], ] ); $this->add_group_control( Group_Control_Text_Shadow::get_type(), [ 'name' => 'text_shadow', 'selector' => '{{WRAPPER}} .elementor-icon-list-text', ] ); $this->end_controls_section(); } /** * Render icon list widget output on the frontend. * * Written in PHP and used to generate the final HTML. * * @since 1.0.0 * @access protected */ protected function render() { $settings = $this->get_settings_for_display(); $fallback_defaults = [ 'fa fa-check', 'fa fa-times', 'fa fa-dot-circle-o', ]; $this->add_render_attribute( 'icon_list', 'class', 'elementor-icon-list-items' ); $this->add_render_attribute( 'list_item', 'class', 'elementor-icon-list-item' ); if ( 'inline' === $settings['view'] ) { $this->add_render_attribute( 'icon_list', 'class', 'elementor-inline-items' ); $this->add_render_attribute( 'list_item', 'class', 'elementor-inline-item' ); } ?> <ul <?php $this->print_render_attribute_string( 'icon_list' ); ?>> <?php foreach ( $settings['icon_list'] as $index => $item ) : $repeater_setting_key = $this->get_repeater_setting_key( 'text', 'icon_list', $index ); $this->add_render_attribute( $repeater_setting_key, 'class', 'elementor-icon-list-text' ); $this->add_inline_editing_attributes( $repeater_setting_key ); $migration_allowed = Icons_Manager::is_migration_allowed(); ?> <li <?php $this->print_render_attribute_string( 'list_item' ); ?>> <?php if ( ! empty( $item['link']['url'] ) ) { $link_key = 'link_' . $index; $this->add_link_attributes( $link_key, $item['link'] ); ?> <a <?php $this->print_render_attribute_string( $link_key ); ?>> <?php } // add old default if ( ! isset( $item['icon'] ) && ! $migration_allowed ) { $item['icon'] = isset( $fallback_defaults[ $index ] ) ? $fallback_defaults[ $index ] : 'fa fa-check'; } $migrated = isset( $item['__fa4_migrated']['selected_icon'] ); $is_new = ! isset( $item['icon'] ) && $migration_allowed; if ( ! empty( $item['icon'] ) || ( ! empty( $item['selected_icon']['value'] ) && $is_new ) ) : ?> <span class="elementor-icon-list-icon"> <?php if ( $is_new || $migrated ) { Icons_Manager::render_icon( $item['selected_icon'], [ 'aria-hidden' => 'true' ] ); } else { ?> <i class="<?php echo esc_attr( $item['icon'] ); ?>" aria-hidden="true"></i> <?php } ?> </span> <?php endif; ?> <span <?php $this->print_render_attribute_string( $repeater_setting_key ); ?>><?php $this->print_unescaped_setting( 'text', 'icon_list', $index ); ?></span> <?php if ( ! empty( $item['link']['url'] ) ) : ?> </a> <?php endif; ?> </li> <?php endforeach; ?> </ul> <?php } /** * Render icon list widget output in the editor. * * Written as a Backbone JavaScript template and used to generate the live preview. * * @since 2.9.0 * @access protected */ protected function content_template() { ?> <# view.addRenderAttribute( 'icon_list', 'class', 'elementor-icon-list-items' ); view.addRenderAttribute( 'list_item', 'class', 'elementor-icon-list-item' ); if ( 'inline' == settings.view ) { view.addRenderAttribute( 'icon_list', 'class', 'elementor-inline-items' ); view.addRenderAttribute( 'list_item', 'class', 'elementor-inline-item' ); } var iconsHTML = {}, migrated = {}; #> <# if ( settings.icon_list ) { #> <ul {{{ view.getRenderAttributeString( 'icon_list' ) }}}> <# _.each( settings.icon_list, function( item, index ) { var iconTextKey = view.getRepeaterSettingKey( 'text', 'icon_list', index ); view.addRenderAttribute( iconTextKey, 'class', 'elementor-icon-list-text' ); view.addInlineEditingAttributes( iconTextKey ); #> <li {{{ view.getRenderAttributeString( 'list_item' ) }}}> <# if ( item.link && item.link.url ) { #> <a href="{{ item.link.url }}"> <# } #> <# if ( item.icon || item.selected_icon.value ) { #> <span class="elementor-icon-list-icon"> <# iconsHTML[ index ] = elementor.helpers.renderIcon( view, item.selected_icon, { 'aria-hidden': true }, 'i', 'object' ); migrated[ index ] = elementor.helpers.isIconMigrated( item, 'selected_icon' ); if ( iconsHTML[ index ] && iconsHTML[ index ].rendered && ( ! item.icon || migrated[ index ] ) ) { #> {{{ iconsHTML[ index ].value }}} <# } else { #> <i class="{{ item.icon }}" aria-hidden="true"></i> <# } #> </span> <# } #> <span {{{ view.getRenderAttributeString( iconTextKey ) }}}>{{{ item.text }}}</span> <# if ( item.link && item.link.url ) { #> </a> <# } #> </li> <# } ); #> </ul> <# } #> <?php } public function on_import( $element ) { return Icons_Manager::on_import_migration( $element, 'icon', 'selected_icon', true ); } }