first commit

This commit is contained in:
2024-07-31 13:12:38 +07:00
commit b4e8cbe182
10213 changed files with 3125839 additions and 0 deletions

View File

@@ -0,0 +1,704 @@
<?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 accordion widget.
*
* Elementor widget that displays a collapsible display of content in an
* accordion style, showing only one item at a time.
*
* @since 1.0.0
*/
class Widget_Accordion extends Widget_Base {
/**
* Get widget name.
*
* Retrieve accordion widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'accordion';
}
/**
* Get widget title.
*
* Retrieve accordion widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Accordion', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve accordion widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-accordion';
}
/**
* 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 [ 'accordion', 'tabs', 'toggle' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Hide widget from panel.
*
* Hide the toggle widget from the panel if nested-accordion experiment is active.
*
* @since 3.15.0
* @return bool
*/
public function show_in_panel(): bool {
return ! Plugin::$instance->experiments->is_feature_active( 'nested-elements' );
}
/**
* Register accordion 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_title',
[
'label' => esc_html__( 'Accordion', 'elementor' ),
]
);
$repeater = new Repeater();
$repeater->add_control(
'tab_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'default' => esc_html__( 'Accordion Title', 'elementor' ),
'dynamic' => [
'active' => true,
],
'label_block' => true,
]
);
$repeater->add_control(
'tab_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'type' => Controls_Manager::WYSIWYG,
'default' => esc_html__( 'Accordion Content', 'elementor' ),
]
);
if ( Plugin::$instance->widgets_manager->get_widget_types( 'nested-accordion' ) ) {
$this->add_deprecation_message(
'3.15.0',
esc_html__(
'You are currently editing an Accordion Widget in its old version. Any new Accordion widget dragged into the canvas will be the new Accordion widget, with the improved Nested capabilities.',
'elementor'
),
'nested-accordion'
);
}
$this->add_control(
'tabs',
[
'label' => esc_html__( 'Accordion Items', 'elementor' ),
'type' => Controls_Manager::REPEATER,
'fields' => $repeater->get_controls(),
'default' => [
[
'tab_title' => esc_html__( 'Accordion #1', 'elementor' ),
'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
],
[
'tab_title' => esc_html__( 'Accordion #2', 'elementor' ),
'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
],
],
'title_field' => '{{{ tab_title }}}',
]
);
$this->add_control(
'selected_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'separator' => 'before',
'fa4compatibility' => 'icon',
'default' => [
'value' => 'fas fa-plus',
'library' => 'fa-solid',
],
'recommended' => [
'fa-solid' => [
'chevron-down',
'angle-down',
'angle-double-down',
'caret-down',
'caret-square-down',
],
'fa-regular' => [
'caret-square-down',
],
],
'skin' => 'inline',
'label_block' => false,
]
);
$this->add_control(
'selected_active_icon',
[
'label' => esc_html__( 'Active Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'fa4compatibility' => 'icon_active',
'default' => [
'value' => 'fas fa-minus',
'library' => 'fa-solid',
],
'recommended' => [
'fa-solid' => [
'chevron-up',
'angle-up',
'angle-double-up',
'caret-up',
'caret-square-up',
],
'fa-regular' => [
'caret-square-up',
],
],
'skin' => 'inline',
'label_block' => false,
'condition' => [
'selected_icon[value]!' => '',
],
]
);
$this->add_control(
'title_html_tag',
[
'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'div',
],
'default' => 'div',
'separator' => 'before',
]
);
$this->add_control(
'faq_schema',
[
'label' => esc_html__( 'FAQ Schema', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'separator' => 'before',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_title_style',
[
'label' => esc_html__( 'Accordion', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'border_width',
[
'label' => esc_html__( 'Border Width', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'max' => 20,
],
'em' => [
'max' => 2,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-accordion-item' => 'border-width: {{SIZE}}{{UNIT}};',
'{{WRAPPER}} .elementor-accordion-item .elementor-tab-content' => 'border-width: {{SIZE}}{{UNIT}};',
'{{WRAPPER}} .elementor-accordion-item .elementor-tab-title.elementor-active' => 'border-width: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_control(
'border_color',
[
'label' => esc_html__( 'Border Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-accordion-item' => 'border-color: {{VALUE}};',
'{{WRAPPER}} .elementor-accordion-item .elementor-tab-content' => 'border-top-color: {{VALUE}};',
'{{WRAPPER}} .elementor-accordion-item .elementor-tab-title.elementor-active' => 'border-bottom-color: {{VALUE}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_toggle_style_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'title_background',
[
'label' => esc_html__( 'Background', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-accordion-icon, {{WRAPPER}} .elementor-accordion-title' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-accordion-icon svg' => 'fill: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
]
);
$this->add_control(
'tab_active_color',
[
'label' => esc_html__( 'Active Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-active .elementor-accordion-icon, {{WRAPPER}} .elementor-active .elementor-accordion-title' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-active .elementor-accordion-icon svg' => 'fill: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_ACCENT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'title_typography',
'selector' => '{{WRAPPER}} .elementor-accordion-title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Text_Stroke::get_type(),
[
'name' => 'text_stroke',
'selector' => '{{WRAPPER}} .elementor-accordion-title',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-accordion-title',
]
);
$this->add_responsive_control(
'title_padding',
[
'label' => esc_html__( 'Padding', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-tab-title' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_toggle_style_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'selected_icon[value]!' => '',
],
]
);
$this->add_control(
'icon_align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => 'eicon-h-align-left',
],
'right' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => 'eicon-h-align-right',
],
],
'default' => is_rtl() ? 'right' : 'left',
'toggle' => false,
]
);
$this->add_control(
'icon_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title .elementor-accordion-icon i:before' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-tab-title .elementor-accordion-icon svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_control(
'icon_active_color',
[
'label' => esc_html__( 'Active Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title.elementor-active .elementor-accordion-icon i:before' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-tab-title.elementor-active .elementor-accordion-icon svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'icon_space',
[
'label' => esc_html__( 'Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'max' => 1,
],
'rem' => [
'max' => 1,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-accordion-icon.elementor-accordion-icon-left' => 'margin-right: {{SIZE}}{{UNIT}};',
'{{WRAPPER}} .elementor-accordion-icon.elementor-accordion-icon-right' => 'margin-left: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_toggle_style_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'content_background_color',
[
'label' => esc_html__( 'Background', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-content' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'content_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-content' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'content_typography',
'selector' => '{{WRAPPER}} .elementor-tab-content',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'content_shadow',
'selector' => '{{WRAPPER}} .elementor-tab-content',
]
);
$this->add_responsive_control(
'content_padding',
[
'label' => esc_html__( 'Padding', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-tab-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
}
/**
* Render accordion 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();
$migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
if ( ! isset( $settings['icon'] ) && ! Icons_Manager::is_migration_allowed() ) {
// @todo: remove when deprecated
// added as bc in 2.6
// add old default
$settings['icon'] = 'fa fa-plus';
$settings['icon_active'] = 'fa fa-minus';
$settings['icon_align'] = $this->get_settings( 'icon_align' );
}
$is_new = empty( $settings['icon'] ) && Icons_Manager::is_migration_allowed();
$has_icon = ( ! $is_new || ! empty( $settings['selected_icon']['value'] ) );
$id_int = substr( $this->get_id_int(), 0, 3 );
?>
<div class="elementor-accordion">
<?php
foreach ( $settings['tabs'] as $index => $item ) :
$tab_count = $index + 1;
$tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
$tab_content_setting_key = $this->get_repeater_setting_key( 'tab_content', 'tabs', $index );
$this->add_render_attribute( $tab_title_setting_key, [
'id' => 'elementor-tab-title-' . $id_int . $tab_count,
'class' => [ 'elementor-tab-title' ],
'data-tab' => $tab_count,
'role' => 'button',
'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
'aria-expanded' => 'false',
] );
$this->add_render_attribute( $tab_content_setting_key, [
'id' => 'elementor-tab-content-' . $id_int . $tab_count,
'class' => [ 'elementor-tab-content', 'elementor-clearfix' ],
'data-tab' => $tab_count,
'role' => 'region',
'aria-labelledby' => 'elementor-tab-title-' . $id_int . $tab_count,
] );
$this->add_inline_editing_attributes( $tab_content_setting_key, 'advanced' );
?>
<div class="elementor-accordion-item">
<<?php Utils::print_validated_html_tag( $settings['title_html_tag'] ); ?> <?php $this->print_render_attribute_string( $tab_title_setting_key ); ?>>
<?php if ( $has_icon ) : ?>
<span class="elementor-accordion-icon elementor-accordion-icon-<?php echo esc_attr( $settings['icon_align'] ); ?>" aria-hidden="true">
<?php
if ( $is_new || $migrated ) { ?>
<span class="elementor-accordion-icon-closed"><?php Icons_Manager::render_icon( $settings['selected_icon'] ); ?></span>
<span class="elementor-accordion-icon-opened"><?php Icons_Manager::render_icon( $settings['selected_active_icon'] ); ?></span>
<?php } else { ?>
<i class="elementor-accordion-icon-closed <?php echo esc_attr( $settings['icon'] ); ?>"></i>
<i class="elementor-accordion-icon-opened <?php echo esc_attr( $settings['icon_active'] ); ?>"></i>
<?php } ?>
</span>
<?php endif; ?>
<a class="elementor-accordion-title" tabindex="0"><?php
$this->print_unescaped_setting( 'tab_title', 'tabs', $index );
?></a>
</<?php Utils::print_validated_html_tag( $settings['title_html_tag'] ); ?>>
<div <?php $this->print_render_attribute_string( $tab_content_setting_key ); ?>><?php
$this->print_text_editor( $item['tab_content'] );
?></div>
</div>
<?php endforeach; ?>
<?php
if ( isset( $settings['faq_schema'] ) && 'yes' === $settings['faq_schema'] ) {
$json = [
'@context' => 'https://schema.org',
'@type' => 'FAQPage',
'mainEntity' => [],
];
foreach ( $settings['tabs'] as $index => $item ) {
$json['mainEntity'][] = [
'@type' => 'Question',
'name' => wp_strip_all_tags( $item['tab_title'] ),
'acceptedAnswer' => [
'@type' => 'Answer',
'text' => $this->parse_text_editor( $item['tab_content'] ),
],
];
}
?>
<script type="application/ld+json"><?php echo wp_json_encode( $json ); ?></script>
<?php } ?>
</div>
<?php
}
/**
* Render accordion 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() {
?>
<div class="elementor-accordion">
<#
if ( settings.tabs ) {
var tabindex = view.getIDInt().toString().substr( 0, 3 ),
iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, {}, 'i' , 'object' ),
iconActiveHTML = elementor.helpers.renderIcon( view, settings.selected_active_icon, {}, 'i' , 'object' ),
migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' );
_.each( settings.tabs, function( item, index ) {
var tabCount = index + 1,
tabTitleKey = view.getRepeaterSettingKey( 'tab_title', 'tabs', index ),
tabContentKey = view.getRepeaterSettingKey( 'tab_content', 'tabs', index );
view.addRenderAttribute( tabTitleKey, {
'id': 'elementor-tab-title-' + tabindex + tabCount,
'class': [ 'elementor-tab-title' ],
'tabindex': tabindex + tabCount,
'data-tab': tabCount,
'role': 'button',
'aria-controls': 'elementor-tab-content-' + tabindex + tabCount,
'aria-expanded': 'false',
} );
view.addRenderAttribute( tabContentKey, {
'id': 'elementor-tab-content-' + tabindex + tabCount,
'class': [ 'elementor-tab-content', 'elementor-clearfix' ],
'data-tab': tabCount,
'role': 'region',
'aria-labelledby': 'elementor-tab-title-' + tabindex + tabCount
} );
view.addInlineEditingAttributes( tabContentKey, 'advanced' );
var titleHTMLTag = elementor.helpers.validateHTMLTag( settings.title_html_tag );
#>
<div class="elementor-accordion-item">
<{{{ titleHTMLTag }}} {{{ view.getRenderAttributeString( tabTitleKey ) }}}>
<# if ( settings.icon || settings.selected_icon ) { #>
<span class="elementor-accordion-icon elementor-accordion-icon-{{ settings.icon_align }}" aria-hidden="true">
<# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
<span class="elementor-accordion-icon-closed">{{{ iconHTML.value }}}</span>
<span class="elementor-accordion-icon-opened">{{{ iconActiveHTML.value }}}</span>
<# } else { #>
<i class="elementor-accordion-icon-closed {{ settings.icon }}"></i>
<i class="elementor-accordion-icon-opened {{ settings.icon_active }}"></i>
<# } #>
</span>
<# } #>
<a class="elementor-accordion-title" tabindex="0">{{{ item.tab_title }}}</a>
</{{{ titleHTMLTag }}}>
<div {{{ view.getRenderAttributeString( tabContentKey ) }}}>{{{ item.tab_content }}}</div>
</div>
<#
} );
} #>
</div>
<?php
}
}

View File

@@ -0,0 +1,557 @@
<?php
namespace Elementor;
use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
use Elementor\Icons_Manager;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor alert widget.
*
* Elementor widget that displays a collapsible display of content in an toggle
* style, allowing the user to open multiple items.
*
* @since 1.0.0
*/
class Widget_Alert extends Widget_Base {
/**
* Get widget name.
*
* Retrieve alert widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'alert';
}
/**
* Get widget title.
*
* Retrieve alert widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Alert', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve alert widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-alert';
}
/**
* 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 [ 'alert', 'notice', 'message' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register alert 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_alert',
[
'label' => esc_html__( 'Alert', 'elementor' ),
]
);
$this->add_control(
'alert_type',
[
'label' => esc_html__( 'Type', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'info',
'options' => [
'info' => esc_html__( 'Info', 'elementor' ),
'success' => esc_html__( 'Success', 'elementor' ),
'warning' => esc_html__( 'Warning', 'elementor' ),
'danger' => esc_html__( 'Danger', 'elementor' ),
],
'prefix_class' => 'elementor-alert-',
]
);
$this->add_control(
'alert_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'placeholder' => esc_html__( 'Enter your title', 'elementor' ),
'default' => esc_html__( 'This is an Alert', 'elementor' ),
'label_block' => true,
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'alert_description',
[
'label' => esc_html__( 'Content', 'elementor' ),
'type' => Controls_Manager::TEXTAREA,
'placeholder' => esc_html__( 'Enter your description', 'elementor' ),
'default' => esc_html__( 'I am a description. Click the edit button to change this text.', 'elementor' ),
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'show_dismiss',
[
'label' => esc_html__( 'Dismiss Icon', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_on' => esc_html__( 'Show', 'elementor' ),
'label_off' => esc_html__( 'Hide', 'elementor' ),
'return_value' => 'show',
'default' => 'show',
]
);
$this->add_control(
'dismiss_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'fa4compatibility' => 'icon',
'skin' => 'inline',
'label_block' => false,
'render_type' => 'template',
'skin_settings' => [
'inline' => [
'none' => [
'label' => 'Default',
'icon' => 'eicon-close',
],
'icon' => [
'icon' => 'eicon-star',
],
],
],
'recommended' => [
'fa-regular' => [
'times-circle',
],
'fa-solid' => [
'times',
'times-circle',
],
],
'condition' => [
'show_dismiss' => 'show',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_type',
[
'label' => esc_html__( 'Alert', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'background',
[
'label' => esc_html__( 'Background Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-alert' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'border_color',
[
'label' => esc_html__( 'Border Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-alert' => 'border-color: {{VALUE}};',
],
]
);
$this->add_control(
'border_left-width',
[
'label' => esc_html__( 'Left Border Width', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-alert' => 'border-left-width: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-alert-title' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'alert_title',
'selector' => '{{WRAPPER}} .elementor-alert-title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-alert-title',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_description',
[
'label' => esc_html__( 'Description', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'description_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-alert-description' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'alert_description',
'selector' => '{{WRAPPER}} .elementor-alert-description',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'description_shadow',
'selector' => '{{WRAPPER}} .elementor-alert-description',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_dismiss_icon',
[
'label' => esc_html__( 'Dismiss Icon', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'show_dismiss' => 'show',
],
]
);
$this->add_responsive_control(
'dismiss_icon_size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'max' => 10,
],
'rem' => [
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}}' => '--dismiss-icon-size: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_responsive_control(
'dismiss_icon_vertical_position',
[
'label' => esc_html__( 'Vertical Position', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => -100,
'max' => 100,
],
],
'size_units' => [ 'px', '%', 'em', 'rem', 'vh', 'custom' ],
'selectors' => [
'{{WRAPPER}}' => '--dismiss-icon-vertical-position: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_responsive_control(
'dismiss_icon_horizontal_position',
[
'label' => esc_html__( 'Horizontal Position', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => -100,
'max' => 100,
],
],
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}}' => '--dismiss-icon-horizontal-position: {{SIZE}}{{UNIT}};',
],
]
);
$this->start_controls_tabs( 'dismiss_icon_colors' );
$this->start_controls_tab( 'dismiss_icon_normal_colors', [
'label' => esc_html__( 'Normal', 'elementor' ),
] );
$this->add_control(
'dismiss_icon_normal_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}}' => '--dismiss-icon-normal-color: {{VALUE}};',
],
]
);
$this->end_controls_tab();
$this->start_controls_tab( 'dismiss_icon_hover_colors', [
'label' => esc_html__( 'Hover', 'elementor' ),
] );
$this->add_control(
'dismiss_icon_hover_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}}' => '--dismiss-icon-hover-color: {{VALUE}};',
],
]
);
$this->add_control(
'dismiss_icon_hover_transition_duration',
[
'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => 0,
'max' => 3,
'step' => 0.1,
],
],
'selectors' => [
'{{WRAPPER}}' => '--dismiss-icon-hover-transition-duration: {{SIZE}}s',
],
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->end_controls_section();
}
/**
* Render alert 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();
if ( Utils::is_empty( $settings['alert_title'] ) && Utils::is_empty( $settings['alert_description'] ) ) {
return;
}
$this->add_render_attribute( 'alert_wrapper', 'class', 'elementor-alert' );
$this->add_render_attribute( 'alert_wrapper', 'role', 'alert' );
$this->add_render_attribute( 'alert_title', 'class', 'elementor-alert-title' );
$this->add_render_attribute( 'alert_description', 'class', 'elementor-alert-description' );
$this->add_inline_editing_attributes( 'alert_title', 'none' );
$this->add_inline_editing_attributes( 'alert_description' );
?>
<div <?php $this->print_render_attribute_string( 'alert_wrapper' ); ?>>
<?php if ( ! Utils::is_empty( $settings['alert_title'] ) ) : ?>
<span <?php $this->print_render_attribute_string( 'alert_title' ); ?>><?php $this->print_unescaped_setting( 'alert_title' ); ?></span>
<?php endif; ?>
<?php if ( ! Utils::is_empty( $settings['alert_description'] ) ) : ?>
<span <?php $this->print_render_attribute_string( 'alert_description' ); ?>><?php $this->print_unescaped_setting( 'alert_description' ); ?></span>
<?php endif; ?>
<?php if ( 'show' === $settings['show_dismiss'] ) : ?>
<button type="button" class="elementor-alert-dismiss">
<?php
if ( ! empty( $settings['dismiss_icon']['value'] ) ) {
Icons_Manager::render_icon( $settings['dismiss_icon'], [ 'aria-hidden' => 'true' ] );
} else { ?>
<span aria-hidden="true">&times;</span>
<?php } ?>
<span class="elementor-screen-only"><?php echo esc_html__( 'Dismiss this alert.', 'elementor' ); ?></span>
</button>
<?php endif; ?>
</div>
<?php
}
/**
* Render alert 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() {
?>
<#
if ( ! settings.alert_title && ! settings.alert_description ) {
return;
}
view.addRenderAttribute( 'alert_wrapper', 'class', 'elementor-alert' );
view.addRenderAttribute( 'alert_wrapper', 'role', 'alert' );
view.addRenderAttribute( 'alert_title', 'class', 'elementor-alert-title' );
view.addRenderAttribute( 'alert_description', 'class', 'elementor-alert-description' );
view.addInlineEditingAttributes( 'alert_title', 'none' );
view.addInlineEditingAttributes( 'alert_description' );
var iconHTML = elementor.helpers.renderIcon( view, settings.dismiss_icon, { 'aria-hidden': true }, 'i' , 'object' ),
migrated = elementor.helpers.isIconMigrated( settings, 'dismiss_icon' );
#>
<div {{{ view.getRenderAttributeString( 'alert_wrapper' ) }}}>
<# if ( settings.alert_title ) { #>
<span {{{ view.getRenderAttributeString( 'alert_title' ) }}}>{{{ settings.alert_title }}}</span>
<# } #>
<# if ( settings.alert_description ) { #>
<span {{{ view.getRenderAttributeString( 'alert_description' ) }}}>{{{ settings.alert_description }}}</span>
<# } #>
<# if ( 'show' === settings.show_dismiss ) { #>
<button type="button" class="elementor-alert-dismiss">
<# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
{{{ iconHTML.value }}}
<# } else { #>
<span aria-hidden="true">&times;</span>
<# } #>
<span class="elementor-screen-only"><?php echo esc_html__( 'Dismiss this alert.', 'elementor' ); ?></span>
</button>
<# } #>
</div>
<?php
}
}

View File

@@ -0,0 +1,342 @@
<?php
namespace Elementor;
use Elementor\Modules\DynamicTags\Module as TagsModule;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor audio widget.
*
* Elementor widget that displays an audio player.
*
* @since 1.0.0
*/
class Widget_Audio extends Widget_Base {
/**
* Current instance.
*
* @access protected
*
* @var array
*/
protected $_current_instance = [];
/**
* Get widget name.
*
* Retrieve audio widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'audio';
}
/**
* Get widget title.
*
* Retrieve audio widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'SoundCloud', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve audio widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-headphones';
}
/**
* 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 [ 'audio', 'player', 'soundcloud', 'embed' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register audio 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_audio',
[
'label' => esc_html__( 'SoundCloud', 'elementor' ),
]
);
$this->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'dynamic' => [
'active' => true,
'categories' => [
TagsModule::POST_META_CATEGORY,
TagsModule::URL_CATEGORY,
],
],
'default' => [
'url' => 'https://soundcloud.com/shchxango/john-coltrane-1963-my-favorite',
],
'options' => false,
]
);
$this->add_control(
'visual',
[
'label' => esc_html__( 'Visual Player', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'no',
'options' => [
'yes' => esc_html__( 'Yes', 'elementor' ),
'no' => esc_html__( 'No', 'elementor' ),
],
]
);
$this->add_control(
'sc_options',
[
'label' => esc_html__( 'Additional Options', 'elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->add_control(
'sc_auto_play',
[
'label' => esc_html__( 'Autoplay', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
]
);
$this->add_control(
'sc_buying',
[
'label' => esc_html__( 'Buy Button', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Hide', 'elementor' ),
'label_on' => esc_html__( 'Show', 'elementor' ),
'default' => 'yes',
]
);
$this->add_control(
'sc_liking',
[
'label' => esc_html__( 'Like Button', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Hide', 'elementor' ),
'label_on' => esc_html__( 'Show', 'elementor' ),
'default' => 'yes',
]
);
$this->add_control(
'sc_download',
[
'label' => esc_html__( 'Download Button', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Hide', 'elementor' ),
'label_on' => esc_html__( 'Show', 'elementor' ),
'default' => 'yes',
]
);
$this->add_control(
'sc_show_artwork',
[
'label' => esc_html__( 'Artwork', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Hide', 'elementor' ),
'label_on' => esc_html__( 'Show', 'elementor' ),
'default' => 'yes',
'condition' => [
'visual' => 'no',
],
]
);
$this->add_control(
'sc_sharing',
[
'label' => esc_html__( 'Share Button', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Hide', 'elementor' ),
'label_on' => esc_html__( 'Show', 'elementor' ),
'default' => 'yes',
]
);
$this->add_control(
'sc_show_comments',
[
'label' => esc_html__( 'Comments', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Hide', 'elementor' ),
'label_on' => esc_html__( 'Show', 'elementor' ),
'default' => 'yes',
]
);
$this->add_control(
'sc_show_playcount',
[
'label' => esc_html__( 'Play Counts', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Hide', 'elementor' ),
'label_on' => esc_html__( 'Show', 'elementor' ),
'default' => 'yes',
]
);
$this->add_control(
'sc_show_user',
[
'label' => esc_html__( 'Username', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Hide', 'elementor' ),
'label_on' => esc_html__( 'Show', 'elementor' ),
'default' => 'yes',
]
);
$this->add_control(
'sc_color',
[
'label' => esc_html__( 'Controls Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
]
);
$this->end_controls_section();
}
/**
* Render audio 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();
if ( empty( $settings['link'] ) ) {
return;
}
$this->_current_instance = $settings;
add_filter( 'oembed_result', [ $this, 'filter_oembed_result' ], 50, 3 );
$video_html = wp_oembed_get( $settings['link']['url'], wp_embed_defaults() );
remove_filter( 'oembed_result', [ $this, 'filter_oembed_result' ], 50 );
if ( $video_html ) : ?>
<div class="elementor-soundcloud-wrapper">
<?php Utils::print_wp_kses_extended( $video_html, [ 'iframe' ] ); ?>
</div>
<?php
endif;
}
/**
* Filter audio widget oEmbed results.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access public
*
* @param string $html The HTML returned by the oEmbed provider.
*
* @return string Filtered audio widget oEmbed HTML.
*/
public function filter_oembed_result( $html ) {
$param_keys = [
'auto_play',
'buying',
'liking',
'download',
'sharing',
'show_comments',
'show_playcount',
'show_user',
'show_artwork',
];
$params = [];
foreach ( $param_keys as $param_key ) {
$params[ $param_key ] = 'yes' === $this->_current_instance[ 'sc_' . $param_key ] ? 'true' : 'false';
}
$params['color'] = str_replace( '#', '', $this->_current_instance['sc_color'] );
preg_match( '/<iframe.*src=\"(.*)\".*><\/iframe>/isU', $html, $matches );
$url = esc_url( add_query_arg( $params, $matches[1] ) );
$visual = 'yes' === $this->_current_instance['visual'] ? 'true' : 'false';
$html = str_replace( [ $matches[1], 'visual=true' ], [ $url, 'visual=' . $visual ], $html );
if ( 'false' === $visual ) {
$html = str_replace( 'height="400"', 'height="200"', $html );
}
return $html;
}
/**
* Render audio 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 File

@@ -0,0 +1,142 @@
<?php
namespace Elementor;
use Elementor\Includes\Widgets\Traits\Button_Trait;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor button widget.
*
* Elementor widget that displays a button with the ability to control every
* aspect of the button design.
*
* @since 1.0.0
*/
class Widget_Button extends Widget_Base {
use Button_Trait;
/**
* Get widget name.
*
* Retrieve button widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'button';
}
/**
* Get widget title.
*
* Retrieve button widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Button', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve button widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-button';
}
/**
* Get widget categories.
*
* Retrieve the list of categories the button widget belongs to.
*
* Used to determine where to display the widget in the editor.
*
* @since 2.0.0
* @access public
*
* @return array Widget categories.
*/
public function get_categories() {
return [ 'basic' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Get widget upsale data.
*
* Retrieve the widget promotion data.
*
* @since 3.19.0
* @access protected
*
* @return array Widget promotion data.
*/
protected function get_upsale_data() {
return [
'condition' => ! Utils::has_pro(),
'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ),
'image_alt' => esc_attr__( 'Upgrade', 'elementor' ),
'title' => esc_html__( 'Convert visitors into customers', 'elementor' ),
'description' => esc_html__( 'Get the Call to Action widget and grow your toolbox with Elementor Pro.', 'elementor' ),
'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-button-widget/' ),
'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ),
];
}
protected function register_controls() {
$this->start_controls_section(
'section_button',
[
'label' => esc_html__( 'Button', 'elementor' ),
]
);
$this->register_button_content_controls();
$this->end_controls_section();
$this->start_controls_section(
'section_style',
[
'label' => esc_html__( 'Button', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->register_button_style_controls();
$this->end_controls_section();
}
/**
* Render button widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$this->render_button();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,695 @@
<?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 counter widget.
*
* Elementor widget that displays stats and numbers in an escalating manner.
*
* @since 1.0.0
*/
class Widget_Counter extends Widget_Base {
/**
* Get widget name.
*
* Retrieve counter widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'counter';
}
/**
* Get widget title.
*
* Retrieve counter widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Counter', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve counter widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-counter';
}
/**
* Retrieve the list of scripts the counter widget depended on.
*
* Used to set scripts dependencies required to run the widget.
*
* @since 1.3.0
* @access public
*
* @return array Widget scripts dependencies.
*/
public function get_script_depends() {
return [ 'jquery-numerator' ];
}
/**
* 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 [ 'counter' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register counter 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() {
$start = is_rtl() ? 'right' : 'left';
$end = ! is_rtl() ? 'right' : 'left';
$this->start_controls_section(
'section_counter',
[
'label' => esc_html__( 'Counter', 'elementor' ),
]
);
$this->add_control(
'starting_number',
[
'label' => esc_html__( 'Starting Number', 'elementor' ),
'type' => Controls_Manager::NUMBER,
'default' => 0,
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'ending_number',
[
'label' => esc_html__( 'Ending Number', 'elementor' ),
'type' => Controls_Manager::NUMBER,
'default' => 100,
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'prefix',
[
'label' => esc_html__( 'Number Prefix', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'ai' => [
'active' => false,
],
'default' => '',
]
);
$this->add_control(
'suffix',
[
'label' => esc_html__( 'Number Suffix', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'ai' => [
'active' => false,
],
'default' => '',
]
);
$this->add_control(
'duration',
[
'label' => esc_html__( 'Animation Duration', 'elementor' ) . ' (ms)',
'type' => Controls_Manager::NUMBER,
'default' => 2000,
'min' => 100,
'step' => 100,
]
);
$this->add_control(
'thousand_separator',
[
'label' => esc_html__( 'Thousand Separator', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'default' => 'yes',
'label_on' => esc_html__( 'Show', 'elementor' ),
'label_off' => esc_html__( 'Hide', 'elementor' ),
]
);
$this->add_control(
'thousand_separator_char',
[
'label' => esc_html__( 'Separator', 'elementor' ),
'type' => Controls_Manager::SELECT,
'condition' => [
'thousand_separator' => 'yes',
],
'options' => [
'' => 'Default',
'.' => 'Dot',
' ' => 'Space',
'_' => 'Underline',
"'" => 'Apostrophe',
],
]
);
$this->add_control(
'title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'label_block' => true,
'separator' => 'before',
'dynamic' => [
'active' => true,
],
'default' => esc_html__( 'Cool Number', 'elementor' ),
]
);
$this->add_control(
'title_tag',
[
'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'div',
'span' => 'span',
'p' => 'p',
],
'default' => 'div',
'condition' => [
'title!' => '',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_counter_style',
[
'label' => esc_html__( 'Counter', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'title_position',
[
'label' => esc_html__( 'Title Position', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'before' => [
'title' => esc_html__( 'Before', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
'after' => [
'title' => esc_html__( 'After', 'elementor' ),
'icon' => 'eicon-v-align-bottom',
],
'start' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => "eicon-h-align-$start",
],
'end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => "eicon-h-align-$end",
],
],
'selectors_dictionary' => [
'before' => 'flex-direction: column;',
'after' => 'flex-direction: column-reverse;',
'start' => 'flex-direction: row;',
'end' => 'flex-direction: row-reverse;',
],
'selectors' => [
'{{WRAPPER}} .elementor-counter' => '{{VALUE}}',
],
'condition' => [
'title!' => '',
],
]
);
$this->add_responsive_control(
'title_horizontal_alignment',
[
'label' => esc_html__( 'Title Horizontal Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'start' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => "eicon-h-align-$start",
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-h-align-center',
],
'end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => "eicon-h-align-$end",
],
],
'separator' => 'before',
'selectors' => [
'{{WRAPPER}} .elementor-counter-title' => 'justify-content: {{VALUE}};',
],
'condition' => [
'title!' => '',
],
]
);
$this->add_responsive_control(
'title_vertical_alignment',
[
'label' => esc_html__( 'Title Vertical Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'start' => [
'title' => esc_html__( 'Top', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
'center' => [
'title' => esc_html__( 'Middle', 'elementor' ),
'icon' => 'eicon-v-align-middle',
],
'end' => [
'title' => esc_html__( 'Bottom', 'elementor' ),
'icon' => 'eicon-v-align-bottom',
],
],
'selectors' => [
'{{WRAPPER}} .elementor-counter-title' => 'align-items: {{VALUE}};',
],
'condition' => [
'title!' => '',
'title_position' => [ 'start', 'end' ],
],
]
);
$this->add_responsive_control(
'title_gap',
[
'label' => esc_html__( 'Title Gap', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-counter' => 'gap: {{SIZE}}{{UNIT}};',
],
'condition' => [
'title!' => '',
'title_position' => [ '', 'before', 'after' ],
],
]
);
$this->add_responsive_control(
'number_position',
[
'label' => esc_html__( 'Number Position', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'start' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => "eicon-h-align-$start",
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-h-align-center',
],
'end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => "eicon-h-align-$end",
],
'stretch' => [
'title' => esc_html__( 'Stretch', 'elementor' ),
'icon' => 'eicon-grow',
],
],
'selectors_dictionary' => [
'start' => 'text-align: {{VALUE}}; --counter-prefix-grow: 0; --counter-suffix-grow: 1; --counter-number-grow: 0;',
'center' => 'text-align: {{VALUE}}; --counter-prefix-grow: 1; --counter-suffix-grow: 1; --counter-number-grow: 0;',
'end' => 'text-align: {{VALUE}}; --counter-prefix-grow: 1; --counter-suffix-grow: 0; --counter-number-grow: 0;',
'stretch' => '--counter-prefix-grow: 0; --counter-suffix-grow: 0; --counter-number-grow: 1;',
],
'selectors' => [
'{{WRAPPER}} .elementor-counter-number-wrapper' => '{{VALUE}}',
],
'separator' => 'before',
]
);
$this->add_responsive_control(
'number_alignment',
[
'label' => esc_html__( 'Number Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'start' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => "eicon-text-align-$start",
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => "eicon-text-align-$end",
],
],
'selectors' => [
'{{WRAPPER}} .elementor-counter-number' => 'text-align: {{VALUE}};',
],
'condition' => [
'number_position' => 'stretch',
],
]
);
$this->add_responsive_control(
'number_gap',
[
'label' => esc_html__( 'Number Gap', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-counter-number-wrapper' => 'gap: {{SIZE}}{{UNIT}};',
],
'conditions' => [
'relation' => 'and',
'terms' => [
[
'name' => 'number_position',
'operator' => '!==',
'value' => 'stretch',
],
[
'relation' => 'or',
'terms' => [
[
'name' => 'prefix',
'operator' => '!==',
'value' => '',
],
[
'name' => 'suffix',
'operator' => '!==',
'value' => '',
],
],
],
],
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_number',
[
'label' => esc_html__( 'Number', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'number_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
'selectors' => [
'{{WRAPPER}} .elementor-counter-number-wrapper' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography_number',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
'selector' => '{{WRAPPER}} .elementor-counter-number-wrapper',
]
);
$this->add_group_control(
Group_Control_Text_Stroke::get_type(),
[
'name' => 'number_stroke',
'selector' => '{{WRAPPER}} .elementor-counter-number-wrapper',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'number_shadow',
'selector' => '{{WRAPPER}} .elementor-counter-number-wrapper',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'title!' => '',
],
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_SECONDARY,
],
'selectors' => [
'{{WRAPPER}} .elementor-counter-title' => 'color: {{VALUE}};',
],
'condition' => [
'title!' => '',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography_title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_SECONDARY,
],
'selector' => '{{WRAPPER}} .elementor-counter-title',
'condition' => [
'title!' => '',
],
]
);
$this->add_group_control(
Group_Control_Text_Stroke::get_type(),
[
'name' => 'title_stroke',
'selector' => '{{WRAPPER}} .elementor-counter-title',
'condition' => [
'title!' => '',
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-counter-title',
'condition' => [
'title!' => '',
],
]
);
$this->end_controls_section();
}
/**
* Render counter 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( 'elementor-counter', 'class', 'elementor-counter' );
view.addRenderAttribute( 'counter-number', 'class', 'elementor-counter-number-wrapper' );
view.addRenderAttribute(
'counter',
{
'class': 'elementor-counter-number',
'data-duration': settings.duration,
'data-to-value': settings.ending_number,
'data-from-value': settings.starting_number,
}
);
if ( settings.thousand_separator ) {
const delimiter = settings.thousand_separator_char ? settings.thousand_separator_char : ',';
view.addRenderAttribute( 'counter', 'data-delimiter', delimiter );
}
view.addRenderAttribute( 'prefix', 'class', 'elementor-counter-number-prefix' );
view.addRenderAttribute( 'suffix', 'class', 'elementor-counter-number-suffix' );
view.addRenderAttribute( 'counter-title', 'class', 'elementor-counter-title' );
view.addInlineEditingAttributes( 'counter-title' );
const titleTag = elementor.helpers.validateHTMLTag( settings.title_tag );
#>
<div {{{ view.getRenderAttributeString( 'elementor-counter' ) }}}>
<# if ( settings.title ) {
#><{{ titleTag }} {{{ view.getRenderAttributeString( 'counter-title' ) }}}>{{{ settings.title }}}</{{ titleTag }}><#
} #>
<div {{{ view.getRenderAttributeString( 'counter-number' ) }}}>
<span {{{ view.getRenderAttributeString( 'prefix' ) }}}>{{{ settings.prefix }}}</span>
<span {{{ view.getRenderAttributeString( 'counter' ) }}}>{{{ settings.starting_number }}}</span>
<span {{{ view.getRenderAttributeString( 'suffix' ) }}}>{{{ settings.suffix }}}</span>
</div>
</div>
<?php
}
/**
* Render counter 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();
$this->add_render_attribute( 'elementor-counter', 'class', 'elementor-counter' );
$this->add_render_attribute( 'counter-number', 'class', 'elementor-counter-number-wrapper' );
$this->add_render_attribute(
'counter',
[
'class' => 'elementor-counter-number',
'data-duration' => $settings['duration'],
'data-to-value' => $settings['ending_number'],
'data-from-value' => $settings['starting_number'],
]
);
if ( ! empty( $settings['thousand_separator'] ) ) {
$delimiter = empty( $settings['thousand_separator_char'] ) ? ',' : $settings['thousand_separator_char'];
$this->add_render_attribute( 'counter', 'data-delimiter', $delimiter );
}
$this->add_render_attribute( 'prefix', 'class', 'elementor-counter-number-prefix' );
$this->add_render_attribute( 'suffix', 'class', 'elementor-counter-number-suffix' );
$this->add_render_attribute( 'counter-title', 'class', 'elementor-counter-title' );
$this->add_inline_editing_attributes( 'counter-title' );
$title_tag = Utils::validate_html_tag( $settings['title_tag'] );
?>
<div <?php $this->print_render_attribute_string( 'elementor-counter' ); ?>>
<?php
if ( $settings['title'] ) :
?><<?php Utils::print_validated_html_tag( $title_tag ); ?> <?php $this->print_render_attribute_string( 'counter-title' ); ?>><?php $this->print_unescaped_setting( 'title' ); ?></<?php Utils::print_validated_html_tag( $title_tag ); ?>><?php
endif;
?>
<div <?php $this->print_render_attribute_string( 'counter-number' ); ?>>
<span <?php $this->print_render_attribute_string( 'prefix' ); ?>><?php $this->print_unescaped_setting( 'prefix' ); ?></span>
<span <?php $this->print_render_attribute_string( 'counter' ); ?>><?php $this->print_unescaped_setting( 'starting_number' ); ?></span>
<span <?php $this->print_render_attribute_string( 'suffix' ); ?>><?php $this->print_unescaped_setting( 'suffix' ); ?></span>
</div>
</div>
<?php
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,310 @@
<?php
namespace Elementor;
use Elementor\Modules\DynamicTags\Module as TagsModule;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor google maps widget.
*
* Elementor widget that displays an embedded google map.
*
* @since 1.0.0
*/
class Widget_Google_Maps extends Widget_Base {
/**
* Get widget name.
*
* Retrieve google maps widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'google_maps';
}
/**
* Get widget title.
*
* Retrieve google maps widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Google Maps', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve google maps widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-google-maps';
}
/**
* Get widget categories.
*
* Retrieve the list of categories the google maps widget belongs to.
*
* Used to determine where to display the widget in the editor.
*
* @since 2.0.0
* @access public
*
* @return array Widget categories.
*/
public function get_categories() {
return [ 'basic' ];
}
/**
* 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 [ 'google', 'map', 'embed', 'location' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register google maps 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_map',
[
'label' => esc_html__( 'Google Maps', 'elementor' ),
]
);
if ( Plugin::$instance->editor->is_edit_mode() ) {
$api_key = get_option( 'elementor_google_maps_api_key' );
if ( ! $api_key ) {
$this->add_control(
'api_key_notification',
[
'type' => Controls_Manager::ALERT,
'alert_type' => 'info',
'content' => sprintf(
/* translators: 1: Integration settings link open tag, 2: Create API key link open tag, 3: Link close tag. */
esc_html__( 'Set your Google Maps API Key in Elementor\'s %1$sIntegrations Settings%3$s page. Create your key %2$shere.%3$s', 'elementor' ),
'<a href="' . Settings::get_settings_tab_url( 'integrations' ) . '" target="_blank">',
'<a href="https://developers.google.com/maps/documentation/embed/get-api-key" target="_blank">',
'</a>'
),
]
);
}
}
$default_address = esc_html__( 'London Eye, London, United Kingdom', 'elementor' );
$this->add_control(
'address',
[
'label' => esc_html__( 'Location', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
'categories' => [
TagsModule::POST_META_CATEGORY,
],
],
'ai' => [
'active' => false,
],
'placeholder' => $default_address,
'default' => $default_address,
'label_block' => true,
]
);
$this->add_control(
'zoom',
[
'label' => esc_html__( 'Zoom', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 10,
],
'range' => [
'px' => [
'min' => 1,
'max' => 20,
],
],
'separator' => 'before',
]
);
$this->add_responsive_control(
'height',
[
'label' => esc_html__( 'Height', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => 40,
'max' => 1440,
],
],
'size_units' => [ 'px', 'em', 'rem', 'vh', 'custom' ],
'selectors' => [
'{{WRAPPER}} iframe' => 'height: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_map_style',
[
'label' => esc_html__( 'Google Maps', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->start_controls_tabs( 'map_filter' );
$this->start_controls_tab( 'normal',
[
'label' => esc_html__( 'Normal', 'elementor' ),
]
);
$this->add_group_control(
Group_Control_Css_Filter::get_type(),
[
'name' => 'css_filters',
'selector' => '{{WRAPPER}} iframe',
]
);
$this->end_controls_tab();
$this->start_controls_tab( 'hover',
[
'label' => esc_html__( 'Hover', 'elementor' ),
]
);
$this->add_group_control(
Group_Control_Css_Filter::get_type(),
[
'name' => 'css_filters_hover',
'selector' => '{{WRAPPER}}:hover iframe',
]
);
$this->add_control(
'hover_transition',
[
'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => 0,
'max' => 3,
'step' => 0.1,
],
],
'selectors' => [
'{{WRAPPER}} iframe' => 'transition-duration: {{SIZE}}s',
],
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->end_controls_section();
}
/**
* Render google maps 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();
if ( empty( $settings['address'] ) ) {
return;
}
if ( 0 === absint( $settings['zoom']['size'] ) ) {
$settings['zoom']['size'] = 10;
}
$api_key = esc_html( get_option( 'elementor_google_maps_api_key' ) );
$params = [
rawurlencode( $settings['address'] ),
absint( $settings['zoom']['size'] ),
];
if ( $api_key ) {
$params[] = $api_key;
$url = 'https://www.google.com/maps/embed/v1/place?key=%3$s&q=%1$s&amp;zoom=%2$d';
} else {
$url = 'https://maps.google.com/maps?q=%1$s&amp;t=m&amp;z=%2$d&amp;output=embed&amp;iwloc=near';
}
?>
<div class="elementor-custom-embed">
<iframe loading="lazy"
src="<?php echo esc_url( vsprintf( $url, $params ) ); ?>"
title="<?php echo esc_attr( $settings['address'] ); ?>"
aria-label="<?php echo esc_attr( $settings['address'] ); ?>"
></iframe>
</div>
<?php
}
/**
* Render google maps 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 File

@@ -0,0 +1,413 @@
<?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;
use Elementor\Modules\ContentSanitizer\Interfaces\Sanitizable;
/**
* Elementor heading widget.
*
* Elementor widget that displays an eye-catching headlines.
*
* @since 1.0.0
*/
class Widget_Heading extends Widget_Base implements Sanitizable {
/**
* Get widget name.
*
* Retrieve heading widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'heading';
}
/**
* Get widget title.
*
* Retrieve heading widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Heading', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve heading widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-t-letter';
}
/**
* Get widget categories.
*
* Retrieve the list of categories the heading widget belongs to.
*
* Used to determine where to display the widget in the editor.
*
* @since 2.0.0
* @access public
*
* @return array Widget categories.
*/
public function get_categories() {
return [ 'basic' ];
}
/**
* 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 [ 'heading', 'title', 'text' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Remove data attributes from the html.
*
* @param string $content Heading title
* @return string
*/
public function sanitize( $content ): string {
$allowed_tags = wp_kses_allowed_html( 'post' );
$allowed_tags_for_heading = [];
$non_allowed_tags = [ 'img' ];
foreach ( $allowed_tags as $tag => $attributes ) {
if ( in_array( $tag, $non_allowed_tags, true ) ) {
continue;
}
$filtered_attributes = array_filter( $attributes, function( $attribute ) {
return ! substr( $attribute, 0, 5 ) === 'data-';
}, ARRAY_FILTER_USE_KEY );
$allowed_tags_for_heading[ $tag ] = $filtered_attributes;
}
return wp_kses( $content, $allowed_tags_for_heading );
}
/**
* Get widget upsale data.
*
* Retrieve the widget promotion data.
*
* @since 3.18.0
* @access protected
*
* @return array Widget promotion data.
*/
protected function get_upsale_data() {
return [
'condition' => ! Utils::has_pro(),
'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ),
'image_alt' => esc_attr__( 'Upgrade', 'elementor' ),
'description' => esc_html__( 'Create captivating headings that rotate with the Animated Headline Widget.', 'elementor' ),
'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-heading-widget/' ),
'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ),
];
}
/**
* Register heading 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_title',
[
'label' => esc_html__( 'Heading', 'elementor' ),
]
);
$this->add_control(
'title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXTAREA,
'ai' => [
'type' => 'text',
],
'dynamic' => [
'active' => true,
],
'placeholder' => esc_html__( 'Enter your title', 'elementor' ),
'default' => esc_html__( 'Add Your Heading Text Here', 'elementor' ),
]
);
$this->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'dynamic' => [
'active' => true,
],
'default' => [
'url' => '',
],
]
);
$this->add_control(
'size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'default' => esc_html__( 'Default', 'elementor' ),
'small' => esc_html__( 'Small', 'elementor' ),
'medium' => esc_html__( 'Medium', 'elementor' ),
'large' => esc_html__( 'Large', 'elementor' ),
'xl' => esc_html__( 'XL', 'elementor' ),
'xxl' => esc_html__( 'XXL', 'elementor' ),
],
'default' => 'default',
'condition' => [
'size!' => 'default', // a workaround to hide the control, unless it's in use (not default).
],
]
);
$this->add_control(
'header_size',
[
'label' => esc_html__( 'HTML Tag', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'div',
'span' => 'span',
'p' => 'p',
],
'default' => 'h2',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_title_style',
[
'label' => esc_html__( 'Heading', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
'title' => esc_html__( 'Justified', 'elementor' ),
'icon' => 'eicon-text-align-justify',
],
],
'default' => '',
'selectors' => [
'{{WRAPPER}}' => 'text-align: {{VALUE}};',
],
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
'selectors' => [
'{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
'selector' => '{{WRAPPER}} .elementor-heading-title',
]
);
$this->add_group_control(
Group_Control_Text_Stroke::get_type(),
[
'name' => 'text_stroke',
'selector' => '{{WRAPPER}} .elementor-heading-title',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'text_shadow',
'selector' => '{{WRAPPER}} .elementor-heading-title',
]
);
$this->add_control(
'blend_mode',
[
'label' => esc_html__( 'Blend Mode', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'' => esc_html__( 'Normal', 'elementor' ),
'multiply' => esc_html__( 'Multiply', 'elementor' ),
'screen' => esc_html__( 'Screen', 'elementor' ),
'overlay' => esc_html__( 'Overlay', 'elementor' ),
'darken' => esc_html__( 'Darken', 'elementor' ),
'lighten' => esc_html__( 'Lighten', 'elementor' ),
'color-dodge' => esc_html__( 'Color Dodge', 'elementor' ),
'saturation' => esc_html__( 'Saturation', 'elementor' ),
'color' => esc_html__( 'Color', 'elementor' ),
'difference' => esc_html__( 'Difference', 'elementor' ),
'exclusion' => esc_html__( 'Exclusion', 'elementor' ),
'hue' => esc_html__( 'Hue', 'elementor' ),
'luminosity' => esc_html__( 'Luminosity', 'elementor' ),
],
'selectors' => [
'{{WRAPPER}} .elementor-heading-title' => 'mix-blend-mode: {{VALUE}}',
],
]
);
$this->end_controls_section();
}
/**
* Render heading 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();
if ( '' === $settings['title'] ) {
return;
}
$this->add_render_attribute( 'title', 'class', 'elementor-heading-title' );
if ( ! empty( $settings['size'] ) ) {
$this->add_render_attribute( 'title', 'class', 'elementor-size-' . $settings['size'] );
} else {
$this->add_render_attribute( 'title', 'class', 'elementor-size-default' );
}
$this->add_inline_editing_attributes( 'title' );
$title = $settings['title'];
if ( ! empty( $settings['link']['url'] ) ) {
$this->add_link_attributes( 'url', $settings['link'] );
$title = sprintf( '<a %1$s>%2$s</a>', $this->get_render_attribute_string( 'url' ), $title );
}
$title_html = sprintf( '<%1$s %2$s>%3$s</%1$s>', Utils::validate_html_tag( $settings['header_size'] ), $this->get_render_attribute_string( 'title' ), $title );
// PHPCS - the variable $title_html holds safe data.
echo $title_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Render heading 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() {
?>
<#
let title = elementor.helpers.sanitize( settings.title, { ALLOW_DATA_ATTR: false } );
if ( '' !== settings.link.url ) {
title = '<a href="' + elementor.helpers.sanitizeUrl( settings.link.url ) + '">' + title + '</a>';
}
view.addRenderAttribute( 'title', 'class', [ 'elementor-heading-title' ] );
if ( '' !== settings.size ) {
view.addRenderAttribute( 'title', 'class', [ 'elementor-size-' + settings.size ] );
} else {
view.addRenderAttribute( 'title', 'class', [ 'elementor-size-default' ] );
}
view.addInlineEditingAttributes( 'title' );
var headerSizeTag = elementor.helpers.validateHTMLTag( settings.header_size ),
title_html = '<' + headerSizeTag + ' ' + view.getRenderAttributeString( 'title' ) + '>' + title + '</' + headerSizeTag + '>';
print( title_html );
#>
<?php
}
}

View File

@@ -0,0 +1,139 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor HTML widget.
*
* Elementor widget that insert a custom HTML code into the page.
*
* @since 1.0.0
*/
class Widget_Html extends Widget_Base {
/**
* Get widget name.
*
* Retrieve HTML widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'html';
}
/**
* Get widget title.
*
* Retrieve HTML widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'HTML', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve HTML widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-code';
}
/**
* 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 [ 'html', 'code', 'embed', 'script' ];
}
protected function is_dynamic_content(): bool {
return false;
}
public function show_in_panel() {
return User::is_current_user_can_use_custom_html();
}
/**
* Register HTML 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_title',
[
'label' => esc_html__( 'HTML Code', 'elementor' ),
]
);
$this->add_control(
'html',
[
'label' => esc_html__( 'HTML Code', 'elementor' ),
'type' => Controls_Manager::CODE,
'default' => '',
'placeholder' => esc_html__( 'Enter your code', 'elementor' ),
'dynamic' => [
'active' => true,
],
'is_editable' => User::is_current_user_can_use_custom_html(),
]
);
$this->end_controls_section();
}
/**
* Render HTML widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$this->print_unescaped_setting( 'html' );
}
/**
* Render HTML 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() {
?>
{{{ settings.html }}}
<?php
}
}

View File

@@ -0,0 +1,840 @@
<?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 box widget.
*
* Elementor widget that displays an icon, a headline and a text.
*
* @since 1.0.0
*/
class Widget_Icon_Box extends Widget_Base {
/**
* Get widget name.
*
* Retrieve icon box widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'icon-box';
}
/**
* Get widget title.
*
* Retrieve icon box widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Icon Box', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve icon box widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-icon-box';
}
/**
* 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 box', 'icon' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register icon box 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 Box', 'elementor' ),
]
);
$this->add_control(
'selected_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'fa4compatibility' => 'icon',
'default' => [
'value' => 'fas fa-star',
'library' => 'fa-solid',
],
]
);
$this->add_control(
'view',
[
'label' => esc_html__( 'View', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'default' => esc_html__( 'Default', 'elementor' ),
'stacked' => esc_html__( 'Stacked', 'elementor' ),
'framed' => esc_html__( 'Framed', 'elementor' ),
],
'default' => 'default',
'prefix_class' => 'elementor-view-',
'condition' => [
'selected_icon[value]!' => '',
],
]
);
$this->add_control(
'shape',
[
'label' => esc_html__( 'Shape', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'circle' => esc_html__( 'Circle', 'elementor' ),
'square' => esc_html__( 'Square', 'elementor' ),
],
'default' => 'circle',
'condition' => [
'view!' => 'default',
'selected_icon[value]!' => '',
],
'prefix_class' => 'elementor-shape-',
]
);
$this->add_control(
'title_text',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'default' => esc_html__( 'This is the heading', 'elementor' ),
'placeholder' => esc_html__( 'Enter your title', 'elementor' ),
'label_block' => true,
]
);
$this->add_control(
'description_text',
[
'label' => esc_html__( 'Description', 'elementor' ),
'type' => Controls_Manager::TEXTAREA,
'dynamic' => [
'active' => true,
],
'default' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
'placeholder' => esc_html__( 'Enter your description', 'elementor' ),
'rows' => 10,
]
);
$this->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'dynamic' => [
'active' => true,
],
'separator' => 'before',
]
);
$this->add_control(
'title_size',
[
'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'div',
'span' => 'span',
'p' => 'p',
],
'default' => 'h3',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style_box',
[
'label' => esc_html__( 'Box', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'position',
[
'label' => esc_html__( 'Icon Position', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'default' => 'top',
'mobile_default' => 'top',
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-h-align-left',
],
'top' => [
'title' => esc_html__( 'Top', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-h-align-right',
],
],
'prefix_class' => 'elementor%s-position-',
'condition' => [
'selected_icon[value]!' => '',
],
]
);
$this->add_responsive_control(
'content_vertical_alignment',
[
'label' => esc_html__( 'Vertical Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'top' => [
'title' => esc_html__( 'Top', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
'middle' => [
'title' => esc_html__( 'Middle', 'elementor' ),
'icon' => 'eicon-v-align-middle',
],
'bottom' => [
'title' => esc_html__( 'Bottom', 'elementor' ),
'icon' => 'eicon-v-align-bottom',
],
],
'default' => 'top',
'toggle' => false,
'prefix_class' => 'elementor-vertical-align-',
'condition' => [
'position!' => 'top',
],
]
);
$this->add_responsive_control(
'text_align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
'title' => esc_html__( 'Justified', 'elementor' ),
'icon' => 'eicon-text-align-justify',
],
],
'selectors' => [
'{{WRAPPER}} .elementor-icon-box-wrapper' => 'text-align: {{VALUE}};',
],
'separator' => 'after',
]
);
$this->add_responsive_control(
'icon_space',
[
'label' => esc_html__( 'Icon Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'default' => [
'size' => 15,
],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'max' => 10,
],
'rem' => [
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}}' => '--icon-box-icon-margin: {{SIZE}}{{UNIT}}',
],
'condition' => [
'selected_icon[value]!' => '',
],
]
);
$this->add_responsive_control(
'title_bottom_space',
[
'label' => esc_html__( 'Content Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'min' => 0,
'max' => 10,
],
'rem' => [
'min' => 0,
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-icon-box-title' => 'margin-bottom: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'selected_icon[value]!' => '',
],
]
);
$this->start_controls_tabs( 'icon_colors' );
$this->start_controls_tab(
'icon_colors_normal',
[
'label' => esc_html__( 'Normal', 'elementor' ),
]
);
$this->add_control(
'primary_color',
[
'label' => esc_html__( 'Primary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
'default' => '',
'selectors' => [
'{{WRAPPER}}.elementor-view-stacked .elementor-icon' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-framed .elementor-icon, {{WRAPPER}}.elementor-view-default .elementor-icon' => 'fill: {{VALUE}}; color: {{VALUE}}; border-color: {{VALUE}};',
],
]
);
$this->add_control(
'secondary_color',
[
'label' => esc_html__( 'Secondary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'condition' => [
'view!' => 'default',
],
'selectors' => [
'{{WRAPPER}}.elementor-view-framed .elementor-icon' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-stacked .elementor-icon' => 'fill: {{VALUE}}; color: {{VALUE}};',
],
]
);
$this->end_controls_tab();
$this->start_controls_tab(
'icon_colors_hover',
[
'label' => esc_html__( 'Hover', 'elementor' ),
]
);
$this->add_control(
'hover_primary_color',
[
'label' => esc_html__( 'Primary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}}.elementor-view-stacked .elementor-icon:hover' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-framed .elementor-icon:hover, {{WRAPPER}}.elementor-view-default .elementor-icon:hover' => 'fill: {{VALUE}}; color: {{VALUE}}; border-color: {{VALUE}};',
],
]
);
$this->add_control(
'hover_secondary_color',
[
'label' => esc_html__( 'Secondary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'condition' => [
'view!' => 'default',
],
'selectors' => [
'{{WRAPPER}}.elementor-view-framed .elementor-icon:hover' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-stacked .elementor-icon:hover' => 'fill: {{VALUE}}; color: {{VALUE}};',
],
]
);
$this->add_control(
'hover_animation',
[
'label' => esc_html__( 'Hover Animation', 'elementor' ),
'type' => Controls_Manager::HOVER_ANIMATION,
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_responsive_control(
'icon_size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'min' => 6,
'max' => 300,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'font-size: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_responsive_control(
'icon_padding',
[
'label' => esc_html__( 'Padding', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'padding: {{SIZE}}{{UNIT}};',
],
'range' => [
'px' => [
'max' => 50,
],
'em' => [
'min' => 0,
'max' => 5,
],
'rem' => [
'min' => 0,
'max' => 5,
],
],
'condition' => [
'view!' => 'default',
],
]
);
$active_breakpoints = Plugin::$instance->breakpoints->get_active_breakpoints();
$rotate_device_args = [];
$rotate_device_settings = [
'default' => [
'unit' => 'deg',
],
];
foreach ( $active_breakpoints as $breakpoint_name => $breakpoint ) {
$rotate_device_args[ $breakpoint_name ] = $rotate_device_settings;
}
$this->add_responsive_control(
'rotate',
[
'label' => esc_html__( 'Rotate', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'deg', 'grad', 'rad', 'turn', 'custom' ],
'default' => [
'unit' => 'deg',
],
'tablet_default' => [
'unit' => 'deg',
],
'mobile_default' => [
'unit' => 'deg',
],
'device_args' => $rotate_device_args,
'selectors' => [
'{{WRAPPER}} .elementor-icon i' => 'transform: rotate({{SIZE}}{{UNIT}});',
],
]
);
$this->add_responsive_control(
'border_width',
[
'label' => esc_html__( 'Border Width', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
'condition' => [
'view' => 'framed',
],
]
);
$this->add_responsive_control(
'border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
'condition' => [
'view!' => 'default',
],
'separator' => 'before',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'heading_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-icon-box-title' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'title_typography',
'selector' => '{{WRAPPER}} .elementor-icon-box-title, {{WRAPPER}} .elementor-icon-box-title a',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Text_Stroke::get_type(),
[
'name' => 'text_stroke',
'selector' => '{{WRAPPER}} .elementor-icon-box-title',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-icon-box-title',
]
);
$this->add_control(
'heading_description',
[
'label' => esc_html__( 'Description', 'elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->add_control(
'description_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-icon-box-description' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'description_typography',
'selector' => '{{WRAPPER}} .elementor-icon-box-description',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'description_shadow',
'selector' => '{{WRAPPER}} .elementor-icon-box-description',
]
);
$this->end_controls_section();
}
/**
* Render icon box 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();
$has_link = ! empty( $settings['link']['url'] );
$html_tag = $has_link ? 'a' : 'span';
$this->add_render_attribute( 'icon', 'class', [ 'elementor-icon', 'elementor-animation-' . $settings['hover_animation'] ] );
$has_icon = ! empty( $settings['selected_icon']['value'] );
$has_content = ! Utils::is_empty( $settings['title_text'] ) || ! Utils::is_empty( $settings['description_text'] );
if ( ! $has_icon && ! $has_content ) {
return;
}
if ( $has_link ) {
$this->add_link_attributes( 'link', $settings['link'] );
$this->add_render_attribute( 'icon', 'tabindex', '-1' );
}
if ( ! isset( $settings['icon'] ) && ! Icons_Manager::is_migration_allowed() ) {
// add old default
$settings['icon'] = 'fa fa-star';
}
if ( ! empty( $settings['icon'] ) ) {
$this->add_render_attribute( 'i', 'class', $settings['icon'] );
$this->add_render_attribute( 'i', 'aria-hidden', 'true' );
}
$this->add_render_attribute( 'description_text', 'class', 'elementor-icon-box-description' );
$this->add_inline_editing_attributes( 'title_text', 'none' );
$this->add_inline_editing_attributes( 'description_text' );
$migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
$is_new = ! isset( $settings['icon'] ) && Icons_Manager::is_migration_allowed();
?>
<div class="elementor-icon-box-wrapper">
<?php if ( $has_icon ) : ?>
<div class="elementor-icon-box-icon">
<<?php Utils::print_validated_html_tag( $html_tag ); ?> <?php $this->print_render_attribute_string( 'link' ); ?> <?php $this->print_render_attribute_string( 'icon' ); ?>>
<?php
if ( $is_new || $migrated ) {
Icons_Manager::render_icon( $settings['selected_icon'], [ 'aria-hidden' => 'true' ] );
} elseif ( ! empty( $settings['icon'] ) ) {
?><i <?php $this->print_render_attribute_string( 'i' ); ?>></i><?php
}
?>
</<?php Utils::print_validated_html_tag( $html_tag ); ?>>
</div>
<?php endif; ?>
<?php if ( $has_content ) : ?>
<div class="elementor-icon-box-content">
<?php if ( ! Utils::is_empty( $settings['title_text'] ) ) : ?>
<<?php Utils::print_validated_html_tag( $settings['title_size'] ); ?> class="elementor-icon-box-title">
<<?php Utils::print_validated_html_tag( $html_tag ); ?> <?php $this->print_render_attribute_string( 'link' ); ?> <?php $this->print_render_attribute_string( 'title_text' ); ?>>
<?php $this->print_unescaped_setting( 'title_text' ); ?>
</<?php Utils::print_validated_html_tag( $html_tag ); ?>>
</<?php Utils::print_validated_html_tag( $settings['title_size'] ); ?>>
<?php endif; ?>
<?php if ( ! Utils::is_empty( $settings['description_text'] ) ) : ?>
<p <?php $this->print_render_attribute_string( 'description_text' ); ?>>
<?php $this->print_unescaped_setting( 'description_text' ); ?>
</p>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php
}
/**
* Render icon box 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() {
?>
<#
// For older version `settings.icon` is needed.
var hasIcon = settings.icon || settings.selected_icon.value;
var hasContent = settings.title_text || settings.description_text;
if ( ! hasIcon && ! hasContent ) {
return;
}
var hasLink = settings.link.url,
htmlTag = hasLink ? 'a' : 'span',
iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, { 'aria-hidden': true }, 'i' , 'object' ),
migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' ),
titleSizeTag = elementor.helpers.validateHTMLTag( settings.title_size );
view.addRenderAttribute( 'icon', 'class', 'elementor-icon elementor-animation-' + settings.hover_animation );
if ( hasLink ) {
view.addRenderAttribute( 'link', 'href', elementor.helpers.sanitizeUrl( settings.link.url ) );
view.addRenderAttribute( 'icon', 'tabindex', '-1' );
}
view.addRenderAttribute( 'description_text', 'class', 'elementor-icon-box-description' );
view.addInlineEditingAttributes( 'title_text', 'none' );
view.addInlineEditingAttributes( 'description_text' );
#>
<div class="elementor-icon-box-wrapper">
<# if ( hasIcon ) { #>
<div class="elementor-icon-box-icon">
<{{{ htmlTag }}} {{{ view.getRenderAttributeString( 'link' ) }}} {{{ view.getRenderAttributeString( 'icon' ) }}}>
<# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
{{{ elementor.helpers.sanitize( iconHTML.value ) }}}
<# } else { #>
<i class="{{ _.escape( settings.icon ) }}" aria-hidden="true"></i>
<# } #>
</{{{ htmlTag }}}>
</div>
<# } #>
<# if ( hasContent ) { #>
<div class="elementor-icon-box-content">
<# if ( settings.title_text ) { #>
<{{{ titleSizeTag }}} class="elementor-icon-box-title">
<{{{ htmlTag }}} {{{ view.getRenderAttributeString( 'link' ) }}} {{{ view.getRenderAttributeString( 'title_text' ) }}}>
{{{ elementor.helpers.sanitize( settings.title_text ) }}}
</{{{ htmlTag }}}>
</{{{ titleSizeTag }}}>
<# } #>
<# if ( settings.description_text ) { #>
<p {{{ view.getRenderAttributeString( 'description_text' ) }}}>{{{ elementor.helpers.sanitize( settings.description_text ) }}}</p>
<# } #>
</div>
<# } #>
</div>
<?php
}
public function on_import( $element ) {
return Icons_Manager::on_import_migration( $element, 'icon', 'selected_icon', true );
}
}

View File

@@ -0,0 +1,840 @@
<?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' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* 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,
],
]
);
$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,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'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,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'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,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'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', '%', 'em', 'rem', 'vh', 'custom' ],
'default' => [
'unit' => '%',
],
'range' => [
'px' => [
'min' => 1,
'max' => 100,
],
'%' => [
'min' => 1,
'max' => 100,
],
'vh' => [
'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->start_controls_tabs( 'icon_colors' );
$this->start_controls_tab(
'icon_colors_normal',
[
'label' => esc_html__( 'Normal', 'elementor' ),
]
);
$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->end_controls_tab();
$this->start_controls_tab(
'icon_colors_hover',
[
'label' => esc_html__( 'Hover', 'elementor' ),
]
);
$this->add_control(
'icon_color_hover',
[
'label' => esc_html__( 'Color', '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_control(
'icon_color_hover_transition',
[
'label' => esc_html__( 'Transition Duration', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 's', 'ms', 'custom' ],
'default' => [
'unit' => 's',
'size' => 0.3,
],
'selectors' => [
'{{WRAPPER}} .elementor-icon-list-icon i' => 'transition: color {{SIZE}}{{UNIT}}',
'{{WRAPPER}} .elementor-icon-list-icon svg' => 'transition: fill {{SIZE}}{{UNIT}}',
],
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_responsive_control(
'icon_size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'default' => [
'size' => 14,
],
'range' => [
'px' => [
'min' => 6,
],
'%' => [
'min' => 6,
],
'vw' => [
'min' => 6,
],
],
'separator' => 'before',
'selectors' => [
'{{WRAPPER}}' => '--e-icon-list-icon-size: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_control(
'text_indent',
[
'label' => esc_html__( 'Gap', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'max' => 50,
],
],
'separator' => 'after',
'selectors' => [
'{{WRAPPER}} .elementor-icon-list-icon' => is_rtl() ? 'padding-left: {{SIZE}}{{UNIT}};' : 'padding-right: {{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__( 'Horizontal 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->add_responsive_control(
'icon_self_vertical_align',
[
'label' => esc_html__( 'Vertical Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'flex-start' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-v-align-middle',
],
'flex-end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => 'eicon-v-align-bottom',
],
],
'default' => '',
'selectors' => [
'{{WRAPPER}}' => '--icon-vertical-align: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'icon_vertical_offset',
[
'label' => esc_html__( 'Adjust Vertical Position', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'default' => [
'size' => 0,
],
'range' => [
'px' => [
'min' => -15,
'max' => 15,
],
'em' => [
'min' => -1,
'max' => 1,
],
],
'selectors' => [
'{{WRAPPER}}' => '--icon-vertical-offset: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_text_style',
[
'label' => esc_html__( 'Text', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$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->start_controls_tabs( 'text_colors' );
$this->start_controls_tab(
'text_colors_normal',
[
'label' => esc_html__( 'Normal', 'elementor' ),
]
);
$this->add_control(
'text_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-icon-list-text' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_SECONDARY,
],
]
);
$this->end_controls_tab();
$this->start_controls_tab(
'text_colors_hover',
[
'label' => esc_html__( 'Hover', 'elementor' ),
]
);
$this->add_control(
'text_color_hover',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-icon-list-item:hover .elementor-icon-list-text' => 'color: {{VALUE}};',
],
]
);
$this->add_control(
'text_color_hover_transition',
[
'label' => esc_html__( 'Transition Duration', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 's', 'ms', 'custom' ],
'default' => [
'unit' => 's',
'size' => 0.3,
],
'selectors' => [
'{{WRAPPER}} .elementor-icon-list-text' => 'transition: color {{SIZE}}{{UNIT}}',
],
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$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="{{ elementor.helpers.sanitizeUrl( 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 );
}
}

View File

@@ -0,0 +1,505 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
/**
* Elementor icon widget.
*
* Elementor widget that displays an icon from over 600+ icons.
*
* @since 1.0.0
*/
class Widget_Icon extends Widget_Base {
/**
* Get widget name.
*
* Retrieve icon widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'icon';
}
/**
* Get widget title.
*
* Retrieve icon widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Icon', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve icon widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-favorite';
}
/**
* Get widget categories.
*
* Retrieve the list of categories the icon widget belongs to.
*
* Used to determine where to display the widget in the editor.
*
* @since 2.0.0
* @access public
*
* @return array Widget categories.
*/
public function get_categories() {
return [ 'basic' ];
}
/**
* 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' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register icon 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', 'elementor' ),
]
);
$this->add_control(
'selected_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'fa4compatibility' => 'icon',
'default' => [
'value' => 'fas fa-star',
'library' => 'fa-solid',
],
]
);
$this->add_control(
'view',
[
'label' => esc_html__( 'View', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'default' => esc_html__( 'Default', 'elementor' ),
'stacked' => esc_html__( 'Stacked', 'elementor' ),
'framed' => esc_html__( 'Framed', 'elementor' ),
],
'default' => 'default',
'prefix_class' => 'elementor-view-',
]
);
$this->add_control(
'shape',
[
'label' => esc_html__( 'Shape', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'circle' => esc_html__( 'Circle', 'elementor' ),
'square' => esc_html__( 'Square', 'elementor' ),
],
'default' => 'circle',
'condition' => [
'view!' => 'default',
],
'prefix_class' => 'elementor-shape-',
]
);
$this->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'dynamic' => [
'active' => true,
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'selectors' => [
'{{WRAPPER}} .elementor-icon-wrapper' => 'text-align: {{VALUE}};',
],
]
);
$this->start_controls_tabs( 'icon_colors' );
$this->start_controls_tab(
'icon_colors_normal',
[
'label' => esc_html__( 'Normal', 'elementor' ),
]
);
$this->add_control(
'primary_color',
[
'label' => esc_html__( 'Primary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}}.elementor-view-stacked .elementor-icon' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-framed .elementor-icon, {{WRAPPER}}.elementor-view-default .elementor-icon' => 'color: {{VALUE}}; border-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-framed .elementor-icon, {{WRAPPER}}.elementor-view-default .elementor-icon svg' => 'fill: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
]
);
$this->add_control(
'secondary_color',
[
'label' => esc_html__( 'Secondary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'condition' => [
'view!' => 'default',
],
'selectors' => [
'{{WRAPPER}}.elementor-view-framed .elementor-icon' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-stacked .elementor-icon' => 'color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-stacked .elementor-icon svg' => 'fill: {{VALUE}};',
],
]
);
$this->end_controls_tab();
$this->start_controls_tab(
'icon_colors_hover',
[
'label' => esc_html__( 'Hover', 'elementor' ),
]
);
$this->add_control(
'hover_primary_color',
[
'label' => esc_html__( 'Primary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}}.elementor-view-stacked .elementor-icon:hover' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-framed .elementor-icon:hover, {{WRAPPER}}.elementor-view-default .elementor-icon:hover' => 'color: {{VALUE}}; border-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-framed .elementor-icon:hover, {{WRAPPER}}.elementor-view-default .elementor-icon:hover svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_control(
'hover_secondary_color',
[
'label' => esc_html__( 'Secondary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'condition' => [
'view!' => 'default',
],
'selectors' => [
'{{WRAPPER}}.elementor-view-framed .elementor-icon:hover' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-stacked .elementor-icon:hover' => 'color: {{VALUE}};',
'{{WRAPPER}}.elementor-view-stacked .elementor-icon:hover svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_control(
'hover_animation',
[
'label' => esc_html__( 'Hover Animation', 'elementor' ),
'type' => Controls_Manager::HOVER_ANIMATION,
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_responsive_control(
'size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'min' => 6,
'max' => 300,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'font-size: {{SIZE}}{{UNIT}};',
'{{WRAPPER}} .elementor-icon svg' => 'height: {{SIZE}}{{UNIT}};',
],
'separator' => 'before',
]
);
$this->add_control(
'fit_to_size',
[
'label' => esc_html__( 'Fit to Size', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'description' => 'Avoid gaps around icons when width and height aren\'t equal',
'label_off' => esc_html__( 'Off', 'elementor' ),
'label_on' => esc_html__( 'On', 'elementor' ),
'condition' => [
'selected_icon[library]' => 'svg',
],
'selectors' => [
'{{WRAPPER}} .elementor-icon-wrapper svg' => 'width: 100%;',
],
]
);
$this->add_control(
'icon_padding',
[
'label' => esc_html__( 'Padding', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'padding: {{SIZE}}{{UNIT}};',
],
'range' => [
'px' => [
'max' => 50,
],
'em' => [
'min' => 0,
'max' => 5,
],
'rem' => [
'min' => 0,
'max' => 5,
],
],
'condition' => [
'view!' => 'default',
],
]
);
$this->add_responsive_control(
'rotate',
[
'label' => esc_html__( 'Rotate', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'deg', 'grad', 'rad', 'turn', 'custom' ],
'default' => [
'unit' => 'deg',
],
'tablet_default' => [
'unit' => 'deg',
],
'mobile_default' => [
'unit' => 'deg',
],
'selectors' => [
'{{WRAPPER}} .elementor-icon i, {{WRAPPER}} .elementor-icon svg' => 'transform: rotate({{SIZE}}{{UNIT}});',
],
]
);
$this->add_control(
'border_width',
[
'label' => esc_html__( 'Border Width', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
'condition' => [
'view' => 'framed',
],
]
);
$this->add_responsive_control(
'border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
'condition' => [
'view!' => 'default',
],
]
);
$this->end_controls_section();
}
/**
* Render icon 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();
if ( empty( $settings['selected_icon']['value'] ) ) {
return;
}
$this->add_render_attribute( 'wrapper', 'class', 'elementor-icon-wrapper' );
$this->add_render_attribute( 'icon-wrapper', 'class', 'elementor-icon' );
if ( ! empty( $settings['hover_animation'] ) ) {
$this->add_render_attribute( 'icon-wrapper', 'class', 'elementor-animation-' . $settings['hover_animation'] );
}
$icon_tag = 'div';
if ( ! empty( $settings['link']['url'] ) ) {
$this->add_link_attributes( 'icon-wrapper', $settings['link'] );
$icon_tag = 'a';
}
if ( empty( $settings['icon'] ) && ! Icons_Manager::is_migration_allowed() ) {
// add old default
$settings['icon'] = 'fa fa-star';
}
if ( ! empty( $settings['icon'] ) ) {
$this->add_render_attribute( 'icon', 'class', $settings['icon'] );
$this->add_render_attribute( 'icon', 'aria-hidden', 'true' );
}
$migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
$is_new = empty( $settings['icon'] ) && Icons_Manager::is_migration_allowed();
?>
<div <?php $this->print_render_attribute_string( 'wrapper' ); ?>>
<<?php Utils::print_unescaped_internal_string( $icon_tag . ' ' . $this->get_render_attribute_string( 'icon-wrapper' ) ); ?>>
<?php if ( $is_new || $migrated ) :
Icons_Manager::render_icon( $settings['selected_icon'], [ 'aria-hidden' => 'true' ] );
else : ?>
<i <?php $this->print_render_attribute_string( 'icon' ); ?>></i>
<?php endif; ?>
</<?php Utils::print_unescaped_internal_string( $icon_tag ); ?>>
</div>
<?php
}
/**
* Render icon 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() {
?>
<#
if ( '' === settings.selected_icon.value ) {
return;
}
const link = settings.link.url ? 'href="' + elementor.helpers.sanitizeUrl( settings.link.url ) + '"' : '',
iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, { 'aria-hidden': true }, 'i' , 'object' ),
migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' ),
iconTag = link ? 'a' : 'div';
#>
<div class="elementor-icon-wrapper">
<{{{ iconTag }}} class="elementor-icon elementor-animation-{{ settings.hover_animation }}" {{{ link }}}>
<# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
{{{ iconHTML.value }}}
<# } else { #>
<i class="{{ settings.icon }}" aria-hidden="true"></i>
<# } #>
</{{{ iconTag }}}>
</div>
<?php
}
}

View File

@@ -0,0 +1,744 @@
<?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 image box widget.
*
* Elementor widget that displays an image, a headline and a text.
*
* @since 1.0.0
*/
class Widget_Image_Box extends Widget_Base {
/**
* Get widget name.
*
* Retrieve image box widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'image-box';
}
/**
* Get widget title.
*
* Retrieve image box widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Image Box', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve image box widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-image-box';
}
/**
* 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 [ 'image', 'photo', 'visual', 'box' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register image box 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_image',
[
'label' => esc_html__( 'Image Box', 'elementor' ),
]
);
$this->add_control(
'image',
[
'label' => esc_html__( 'Choose Image', 'elementor' ),
'type' => Controls_Manager::MEDIA,
'dynamic' => [
'active' => true,
],
'default' => [
'url' => Utils::get_placeholder_image_src(),
],
]
);
$this->add_group_control(
Group_Control_Image_Size::get_type(),
[
'name' => 'thumbnail', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `thumbnail_size` and `thumbnail_custom_dimension`.
'default' => 'full',
'condition' => [
'image[url]!' => '',
],
]
);
$this->add_control(
'title_text',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'default' => esc_html__( 'This is the heading', 'elementor' ),
'placeholder' => esc_html__( 'Enter your title', 'elementor' ),
'label_block' => true,
]
);
$this->add_control(
'description_text',
[
'label' => esc_html__( 'Description', 'elementor' ),
'type' => Controls_Manager::TEXTAREA,
'dynamic' => [
'active' => true,
],
'default' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
'placeholder' => esc_html__( 'Enter your description', 'elementor' ),
'rows' => 10,
]
);
$this->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'dynamic' => [
'active' => true,
],
'separator' => 'before',
]
);
$this->add_control(
'title_size',
[
'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'div',
'span' => 'span',
'p' => 'p',
],
'default' => 'h3',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style_box',
[
'label' => esc_html__( 'Box', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'position',
[
'label' => esc_html__( 'Image Position', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'default' => 'top',
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-h-align-left',
],
'top' => [
'title' => esc_html__( 'Top', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-h-align-right',
],
],
'prefix_class' => 'elementor-position-',
'toggle' => false,
'condition' => [
'image[url]!' => '',
],
]
);
$this->add_responsive_control(
'content_vertical_alignment',
[
'label' => esc_html__( 'Vertical Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'top' => [
'title' => esc_html__( 'Top', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
'middle' => [
'title' => esc_html__( 'Middle', 'elementor' ),
'icon' => 'eicon-v-align-middle',
],
'bottom' => [
'title' => esc_html__( 'Bottom', 'elementor' ),
'icon' => 'eicon-v-align-bottom',
],
],
'default' => 'top',
'toggle' => false,
'prefix_class' => 'elementor-vertical-align-',
'condition' => [
'position!' => 'top',
],
]
);
$this->add_responsive_control(
'text_align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
'title' => esc_html__( 'Justified', 'elementor' ),
'icon' => 'eicon-text-align-justify',
],
],
'selectors' => [
'{{WRAPPER}} .elementor-image-box-wrapper' => 'text-align: {{VALUE}};',
],
'separator' => 'after',
]
);
$this->add_responsive_control(
'image_space',
[
'label' => esc_html__( 'Image Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'default' => [
'size' => 15,
],
'range' => [
'px' => [
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}}.elementor-position-right .elementor-image-box-img' => 'margin-left: {{SIZE}}{{UNIT}};',
'{{WRAPPER}}.elementor-position-left .elementor-image-box-img' => 'margin-right: {{SIZE}}{{UNIT}};',
'{{WRAPPER}}.elementor-position-top .elementor-image-box-img' => 'margin-bottom: {{SIZE}}{{UNIT}};',
'(mobile){{WRAPPER}} .elementor-image-box-img' => 'margin-bottom: {{SIZE}}{{UNIT}};',
],
'condition' => [
'image[url]!' => '',
],
]
);
$this->add_responsive_control(
'title_bottom_space',
[
'label' => esc_html__( 'Content Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'min' => 0,
'max' => 10,
],
'rem' => [
'min' => 0,
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-image-box-title' => 'margin-bottom: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style_image',
[
'label' => esc_html__( 'Image', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'image[url]!' => '',
],
]
);
$this->add_responsive_control(
'image_size',
[
'label' => esc_html__( 'Width', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 30,
'unit' => '%',
],
'tablet_default' => [
'unit' => '%',
],
'mobile_default' => [
'unit' => '%',
],
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'%' => [
'min' => 5,
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-image-box-wrapper .elementor-image-box-img' => 'width: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_group_control(
Group_Control_Border::get_type(),
[
'name' => 'image_border',
'selector' => '{{WRAPPER}} .elementor-image-box-img img',
'separator' => 'before',
]
);
$this->add_responsive_control(
'image_border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'separator' => 'after',
'selectors' => [
'{{WRAPPER}} .elementor-image-box-img img' => 'border-radius: {{SIZE}}{{UNIT}};',
],
]
);
$this->start_controls_tabs( 'image_effects' );
$this->start_controls_tab(
'normal',
[
'label' => esc_html__( 'Normal', 'elementor' ),
]
);
$this->add_group_control(
Group_Control_Css_Filter::get_type(),
[
'name' => 'css_filters',
'selector' => '{{WRAPPER}} .elementor-image-box-img img',
]
);
$this->add_control(
'image_opacity',
[
'label' => esc_html__( 'Opacity', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'max' => 1,
'min' => 0.10,
'step' => 0.01,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-image-box-img img' => 'opacity: {{SIZE}};',
],
]
);
$this->end_controls_tab();
$this->start_controls_tab(
'hover',
[
'label' => esc_html__( 'Hover', 'elementor' ),
]
);
$this->add_group_control(
Group_Control_Css_Filter::get_type(),
[
'name' => 'css_filters_hover',
'selector' => '{{WRAPPER}}:hover .elementor-image-box-img img',
]
);
$this->add_control(
'image_opacity_hover',
[
'label' => esc_html__( 'Opacity', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'max' => 1,
'min' => 0.10,
'step' => 0.01,
],
],
'selectors' => [
'{{WRAPPER}}:hover .elementor-image-box-img img' => 'opacity: {{SIZE}};',
],
]
);
$this->add_control(
'background_hover_transition',
[
'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 0.3,
],
'range' => [
'px' => [
'min' => 0,
'max' => 3,
'step' => 0.1,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-image-box-img img' => 'transition-duration: {{SIZE}}s',
],
]
);
$this->add_control(
'hover_animation',
[
'label' => esc_html__( 'Hover Animation', 'elementor' ),
'type' => Controls_Manager::HOVER_ANIMATION,
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->end_controls_section();
$this->start_controls_section(
'section_style_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'heading_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-image-box-title' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'title_typography',
'selector' => '{{WRAPPER}} .elementor-image-box-title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Text_Stroke::get_type(),
[
'name' => 'title_stroke',
'selector' => '{{WRAPPER}} .elementor-image-box-title',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-image-box-title',
]
);
$this->add_control(
'heading_description',
[
'label' => esc_html__( 'Description', 'elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->add_control(
'description_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-image-box-description' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'description_typography',
'selector' => '{{WRAPPER}} .elementor-image-box-description',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'description_shadow',
'selector' => '{{WRAPPER}} .elementor-image-box-description',
]
);
$this->end_controls_section();
}
/**
* Render image box 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();
$has_image = ! empty( $settings['image']['url'] );
$has_content = ! Utils::is_empty( $settings['title_text'] ) || ! Utils::is_empty( $settings['description_text'] );
if ( ! $has_image && ! $has_content ) {
return;
}
$html = '<div class="elementor-image-box-wrapper">';
if ( ! empty( $settings['link']['url'] ) ) {
$this->add_link_attributes( 'link', $settings['link'] );
}
if ( $has_image ) {
$image_html = wp_kses_post( Group_Control_Image_Size::get_attachment_image_html( $settings, 'thumbnail', 'image' ) );
if ( ! empty( $settings['link']['url'] ) ) {
$image_html = '<a ' . $this->get_render_attribute_string( 'link' ) . ' tabindex="-1">' . $image_html . '</a>';
}
$html .= '<figure class="elementor-image-box-img">' . $image_html . '</figure>';
}
if ( $has_content ) {
$html .= '<div class="elementor-image-box-content">';
if ( ! Utils::is_empty( $settings['title_text'] ) ) {
$this->add_render_attribute( 'title_text', 'class', 'elementor-image-box-title' );
$this->add_inline_editing_attributes( 'title_text', 'none' );
$title_html = $settings['title_text'];
if ( ! empty( $settings['link']['url'] ) ) {
$title_html = '<a ' . $this->get_render_attribute_string( 'link' ) . '>' . $title_html . '</a>';
}
$html .= sprintf( '<%1$s %2$s>%3$s</%1$s>', Utils::validate_html_tag( $settings['title_size'] ), $this->get_render_attribute_string( 'title_text' ), $title_html );
}
if ( ! Utils::is_empty( $settings['description_text'] ) ) {
$this->add_render_attribute( 'description_text', 'class', 'elementor-image-box-description' );
$this->add_inline_editing_attributes( 'description_text' );
$html .= sprintf( '<p %1$s>%2$s</p>', $this->get_render_attribute_string( 'description_text' ), $settings['description_text'] );
}
$html .= '</div>';
}
$html .= '</div>';
Utils::print_unescaped_internal_string( $html );
}
/**
* Render image box 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() {
?>
<#
var hasImage = !! settings.image.url;
var hasContent = !! ( settings.title_text || settings.description_text );
if ( ! hasImage && ! hasContent ) {
return;
}
var html = '<div class="elementor-image-box-wrapper">';
if ( hasImage ) {
var image = {
id: settings.image.id,
url: settings.image.url,
size: settings.thumbnail_size,
dimension: settings.thumbnail_custom_dimension,
model: view.getEditModel()
};
var image_url = elementor.imagesManager.getImageUrl( image );
var imageHtml = '<img src="' + _.escape( image_url ) + '" class="elementor-animation-' + _.escape( settings.hover_animation ) + '" />';
if ( settings.link.url ) {
imageHtml = '<a href="' + elementor.helpers.sanitizeUrl( settings.link.url ) + '" tabindex="-1">' + imageHtml + '</a>';
}
html += '<figure class="elementor-image-box-img">' + imageHtml + '</figure>';
}
if ( hasContent ) {
html += '<div class="elementor-image-box-content">';
if ( settings.title_text ) {
var title_html = elementor.helpers.sanitize( settings.title_text ),
titleSizeTag = elementor.helpers.validateHTMLTag( settings.title_size );
if ( settings.link.url ) {
title_html = '<a href="' + elementor.helpers.sanitizeUrl( settings.link.url ) + '">' + title_html + '</a>';
}
view.addRenderAttribute( 'title_text', 'class', 'elementor-image-box-title' );
view.addInlineEditingAttributes( 'title_text', 'none' );
html += '<' + titleSizeTag + ' ' + view.getRenderAttributeString( 'title_text' ) + '>' + title_html + '</' + titleSizeTag + '>';
}
if ( settings.description_text ) {
view.addRenderAttribute( 'description_text', 'class', 'elementor-image-box-description' );
view.addInlineEditingAttributes( 'description_text' );
html += '<p ' + view.getRenderAttributeString( 'description_text' ) + '>' + settings.description_text + '</p>';
}
html += '</div>';
}
html += '</div>';
print( html );
#>
<?php
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,440 @@
<?php
namespace Elementor;
use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor image gallery widget.
*
* Elementor widget that displays a set of images in an aligned grid.
*
* @since 1.0.0
*/
class Widget_Image_Gallery extends Widget_Base {
/**
* Get widget name.
*
* Retrieve image gallery widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'image-gallery';
}
/**
* Get widget title.
*
* Retrieve image gallery widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Basic Gallery', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve image gallery widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-gallery-grid';
}
/**
* 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 [ 'image', 'photo', 'visual', 'gallery' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Get widget upsale data.
*
* Retrieve the widget promotion data.
*
* @since 3.18.0
* @access protected
*
* @return array Widget promotion data.
*/
protected function get_upsale_data() {
return [
'condition' => ! Utils::has_pro(),
'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ),
'image_alt' => esc_attr__( 'Upgrade', 'elementor' ),
'description' => esc_html__( 'Use interesting masonry layouts and other overlay features with Elementor\'s Pro Gallery widget.', 'elementor' ),
'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-basic-gallery-widget/' ),
'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ),
];
}
/**
* Register image gallery 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_gallery',
[
'label' => esc_html__( 'Basic Gallery', 'elementor' ),
]
);
$this->add_control(
'wp_gallery',
[
'label' => esc_html__( 'Add Images', 'elementor' ),
'type' => Controls_Manager::GALLERY,
'show_label' => false,
'dynamic' => [
'active' => true,
],
]
);
$this->add_group_control(
Group_Control_Image_Size::get_type(),
[
'name' => 'thumbnail', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `thumbnail_size` and `thumbnail_custom_dimension`.
'exclude' => [ 'custom' ],
]
);
$gallery_columns = range( 1, 10 );
$gallery_columns = array_combine( $gallery_columns, $gallery_columns );
$this->add_control(
'gallery_columns',
[
'label' => esc_html__( 'Columns', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 4,
'options' => $gallery_columns,
]
);
$this->add_control(
'gallery_display_caption',
[
'label' => esc_html__( 'Caption', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => '',
'options' => [
'none' => esc_html__( 'None', 'elementor' ),
'' => esc_html__( 'Attachment Caption', 'elementor' ),
],
'selectors' => [
'{{WRAPPER}} .gallery-item .gallery-caption' => 'display: {{VALUE}};',
],
]
);
$this->add_control(
'gallery_link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'file',
'options' => [
'file' => esc_html__( 'Media File', 'elementor' ),
'attachment' => esc_html__( 'Attachment Page', 'elementor' ),
'none' => esc_html__( 'None', 'elementor' ),
],
]
);
$this->add_control(
'open_lightbox',
[
'label' => esc_html__( 'Lightbox', 'elementor' ),
'type' => Controls_Manager::SELECT,
'description' => sprintf(
/* translators: 1: Link open tag, 2: Link close tag. */
esc_html__( 'Manage your sites lightbox settings in the %1$sLightbox panel%2$s.', 'elementor' ),
'<a href="javascript: $e.run( \'panel/global/open\' ).then( () => $e.route( \'panel/global/settings-lightbox\' ) )">',
'</a>'
),
'default' => 'default',
'options' => [
'default' => esc_html__( 'Default', 'elementor' ),
'yes' => esc_html__( 'Yes', 'elementor' ),
'no' => esc_html__( 'No', 'elementor' ),
],
'condition' => [
'gallery_link' => 'file',
],
]
);
$this->add_control(
'gallery_rand',
[
'label' => esc_html__( 'Order By', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'' => esc_html__( 'Default', 'elementor' ),
'rand' => esc_html__( 'Random', 'elementor' ),
],
'default' => '',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_gallery_images',
[
'label' => esc_html__( 'Images', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'image_spacing',
[
'label' => esc_html__( 'Spacing', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'' => esc_html__( 'Default', 'elementor' ),
'custom' => esc_html__( 'Custom', 'elementor' ),
],
'prefix_class' => 'gallery-spacing-',
'default' => '',
]
);
$columns_margin = is_rtl() ? '0 0 -{{SIZE}}{{UNIT}} -{{SIZE}}{{UNIT}};' : '0 -{{SIZE}}{{UNIT}} -{{SIZE}}{{UNIT}} 0;';
$columns_padding = is_rtl() ? '0 0 {{SIZE}}{{UNIT}} {{SIZE}}{{UNIT}};' : '0 {{SIZE}}{{UNIT}} {{SIZE}}{{UNIT}} 0;';
$this->add_control(
'image_spacing_custom',
[
'label' => esc_html__( 'Custom Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'max' => 10,
],
'rem' => [
'max' => 10,
],
],
'default' => [
'size' => 15,
],
'selectors' => [
'{{WRAPPER}} .gallery-item' => 'padding:' . $columns_padding,
'{{WRAPPER}} .gallery' => 'margin: ' . $columns_margin,
],
'condition' => [
'image_spacing' => 'custom',
],
]
);
$this->add_group_control(
Group_Control_Border::get_type(),
[
'name' => 'image_border',
'selector' => '{{WRAPPER}} .gallery-item img',
'separator' => 'before',
]
);
$this->add_responsive_control(
'image_border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .gallery-item img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_caption',
[
'label' => esc_html__( 'Caption', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'gallery_display_caption' => '',
],
]
);
$this->add_responsive_control(
'align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
'title' => esc_html__( 'Justified', 'elementor' ),
'icon' => 'eicon-text-align-justify',
],
],
'default' => 'center',
'selectors' => [
'{{WRAPPER}} .gallery-item .gallery-caption' => 'text-align: {{VALUE}};',
],
'condition' => [
'gallery_display_caption' => '',
],
]
);
$this->add_control(
'text_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .gallery-item .gallery-caption' => 'color: {{VALUE}};',
],
'condition' => [
'gallery_display_caption' => '',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_ACCENT,
],
'selector' => '{{WRAPPER}} .gallery-item .gallery-caption',
'condition' => [
'gallery_display_caption' => '',
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'caption_shadow',
'selector' => '{{WRAPPER}} .gallery-item .gallery-caption',
'condition' => [
'gallery_display_caption' => '',
],
]
);
$this->add_responsive_control(
'caption_space',
[
'label' => esc_html__( 'Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .gallery-item .gallery-caption' => 'margin-block-start: {{SIZE}}{{UNIT}};',
],
'condition' => [
'gallery_display_caption' => '',
],
]
);
$this->end_controls_section();
}
/**
* Render image gallery 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();
if ( ! $settings['wp_gallery'] ) {
return;
}
$ids = wp_list_pluck( $settings['wp_gallery'], 'id' );
$this->add_render_attribute( 'shortcode', 'ids', implode( ',', $ids ) );
$this->add_render_attribute( 'shortcode', 'size', $settings['thumbnail_size'] );
if ( $settings['gallery_columns'] ) {
$this->add_render_attribute( 'shortcode', 'columns', $settings['gallery_columns'] );
}
if ( $settings['gallery_link'] ) {
$this->add_render_attribute( 'shortcode', 'link', $settings['gallery_link'] );
}
if ( ! empty( $settings['gallery_rand'] ) ) {
$this->add_render_attribute( 'shortcode', 'orderby', $settings['gallery_rand'] );
}
?>
<div class="elementor-image-gallery">
<?php
add_filter( 'wp_get_attachment_link', [ $this, 'add_lightbox_data_to_image_link' ], 10, 2 );
echo do_shortcode( '[gallery ' . $this->get_render_attribute_string( 'shortcode' ) . ']' );
remove_filter( 'wp_get_attachment_link', [ $this, 'add_lightbox_data_to_image_link' ] );
?>
</div>
<?php
}
}

View File

@@ -0,0 +1,871 @@
<?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 image widget.
*
* Elementor widget that displays an image into the page.
*
* @since 1.0.0
*/
class Widget_Image extends Widget_Base {
/**
* Get widget name.
*
* Retrieve image widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'image';
}
/**
* Get widget title.
*
* Retrieve image widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Image', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve image widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-image';
}
/**
* Get widget categories.
*
* Retrieve the list of categories the image widget belongs to.
*
* Used to determine where to display the widget in the editor.
*
* @since 2.0.0
* @access public
*
* @return array Widget categories.
*/
public function get_categories() {
return [ 'basic' ];
}
/**
* 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 [ 'image', 'photo', 'visual' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register image 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_image',
[
'label' => esc_html__( 'Image', 'elementor' ),
]
);
$this->add_control(
'image',
[
'label' => esc_html__( 'Choose Image', 'elementor' ),
'type' => Controls_Manager::MEDIA,
'dynamic' => [
'active' => true,
],
'default' => [
'url' => Utils::get_placeholder_image_src(),
],
]
);
$this->add_group_control(
Group_Control_Image_Size::get_type(),
[
'name' => 'image', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `image_size` and `image_custom_dimension`.
'default' => 'large',
'condition' => [
'image[url]!' => '',
],
]
);
$this->add_control(
'caption_source',
[
'label' => esc_html__( 'Caption', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'none' => esc_html__( 'None', 'elementor' ),
'attachment' => esc_html__( 'Attachment Caption', 'elementor' ),
'custom' => esc_html__( 'Custom Caption', 'elementor' ),
],
'default' => 'none',
'condition' => [
'image[url]!' => '',
],
]
);
$this->add_control(
'caption',
[
'label' => esc_html__( 'Custom Caption', 'elementor' ),
'type' => Controls_Manager::TEXT,
'default' => '',
'placeholder' => esc_html__( 'Enter your image caption', 'elementor' ),
'condition' => [
'image[url]!' => '',
'caption_source' => 'custom',
],
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'link_to',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'none',
'options' => [
'none' => esc_html__( 'None', 'elementor' ),
'file' => esc_html__( 'Media File', 'elementor' ),
'custom' => esc_html__( 'Custom URL', 'elementor' ),
],
'condition' => [
'image[url]!' => '',
],
]
);
$this->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'dynamic' => [
'active' => true,
],
'condition' => [
'image[url]!' => '',
'link_to' => 'custom',
],
'show_label' => false,
]
);
$this->add_control(
'open_lightbox',
[
'label' => esc_html__( 'Lightbox', 'elementor' ),
'type' => Controls_Manager::SELECT,
'description' => sprintf(
/* translators: 1: Link open tag, 2: Link close tag. */
esc_html__( 'Manage your sites lightbox settings in the %1$sLightbox panel%2$s.', 'elementor' ),
'<a href="javascript: $e.run( \'panel/global/open\' ).then( () => $e.route( \'panel/global/settings-lightbox\' ) )">',
'</a>'
),
'default' => 'default',
'options' => [
'default' => esc_html__( 'Default', 'elementor' ),
'yes' => esc_html__( 'Yes', 'elementor' ),
'no' => esc_html__( 'No', 'elementor' ),
],
'condition' => [
'image[url]!' => '',
'link_to' => 'file',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style_image',
[
'label' => esc_html__( 'Image', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
],
'selectors' => [
'{{WRAPPER}}' => 'text-align: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'width',
[
'label' => esc_html__( 'Width', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'default' => [
'unit' => '%',
],
'tablet_default' => [
'unit' => '%',
],
'mobile_default' => [
'unit' => '%',
],
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'%' => [
'min' => 1,
'max' => 100,
],
'px' => [
'min' => 1,
'max' => 1000,
],
'vw' => [
'min' => 1,
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}} img' => 'width: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_responsive_control(
'space',
[
'label' => esc_html__( 'Max Width', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'default' => [
'unit' => '%',
],
'tablet_default' => [
'unit' => '%',
],
'mobile_default' => [
'unit' => '%',
],
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'%' => [
'min' => 1,
'max' => 100,
],
'px' => [
'min' => 1,
'max' => 1000,
],
'vw' => [
'min' => 1,
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}} img' => 'max-width: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_responsive_control(
'height',
[
'label' => esc_html__( 'Height', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vh', 'custom' ],
'range' => [
'px' => [
'min' => 1,
'max' => 500,
],
'vh' => [
'min' => 1,
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}} img' => 'height: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_responsive_control(
'object-fit',
[
'label' => esc_html__( 'Object Fit', 'elementor' ),
'type' => Controls_Manager::SELECT,
'condition' => [
'height[size]!' => '',
],
'options' => [
'' => esc_html__( 'Default', 'elementor' ),
'fill' => esc_html__( 'Fill', 'elementor' ),
'cover' => esc_html__( 'Cover', 'elementor' ),
'contain' => esc_html__( 'Contain', 'elementor' ),
'scale-down' => esc_html__( 'Scale Down', 'elementor' ),
],
'default' => '',
'selectors' => [
'{{WRAPPER}} img' => 'object-fit: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'object-position',
[
'label' => esc_html__( 'Object Position', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'center center' => esc_html__( 'Center Center', 'elementor' ),
'center left' => esc_html__( 'Center Left', 'elementor' ),
'center right' => esc_html__( 'Center Right', 'elementor' ),
'top center' => esc_html__( 'Top Center', 'elementor' ),
'top left' => esc_html__( 'Top Left', 'elementor' ),
'top right' => esc_html__( 'Top Right', 'elementor' ),
'bottom center' => esc_html__( 'Bottom Center', 'elementor' ),
'bottom left' => esc_html__( 'Bottom Left', 'elementor' ),
'bottom right' => esc_html__( 'Bottom Right', 'elementor' ),
],
'default' => 'center center',
'selectors' => [
'{{WRAPPER}} img' => 'object-position: {{VALUE}};',
],
'condition' => [
'height[size]!' => '',
'object-fit' => [ 'cover', 'contain', 'scale-down' ],
],
]
);
$this->add_control(
'separator_panel_style',
[
'type' => Controls_Manager::DIVIDER,
'style' => 'thick',
]
);
$this->start_controls_tabs( 'image_effects' );
$this->start_controls_tab( 'normal',
[
'label' => esc_html__( 'Normal', 'elementor' ),
]
);
$this->add_control(
'opacity',
[
'label' => esc_html__( 'Opacity', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'max' => 1,
'min' => 0.10,
'step' => 0.01,
],
],
'selectors' => [
'{{WRAPPER}} img' => 'opacity: {{SIZE}};',
],
]
);
$this->add_group_control(
Group_Control_Css_Filter::get_type(),
[
'name' => 'css_filters',
'selector' => '{{WRAPPER}} img',
]
);
$this->end_controls_tab();
$this->start_controls_tab( 'hover',
[
'label' => esc_html__( 'Hover', 'elementor' ),
]
);
$this->add_control(
'opacity_hover',
[
'label' => esc_html__( 'Opacity', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'max' => 1,
'min' => 0.10,
'step' => 0.01,
],
],
'selectors' => [
'{{WRAPPER}}:hover img' => 'opacity: {{SIZE}};',
],
]
);
$this->add_group_control(
Group_Control_Css_Filter::get_type(),
[
'name' => 'css_filters_hover',
'selector' => '{{WRAPPER}}:hover img',
]
);
$this->add_control(
'background_hover_transition',
[
'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => 0,
'max' => 3,
'step' => 0.1,
],
],
'selectors' => [
'{{WRAPPER}} img' => 'transition-duration: {{SIZE}}s',
],
]
);
$this->add_control(
'hover_animation',
[
'label' => esc_html__( 'Hover Animation', 'elementor' ),
'type' => Controls_Manager::HOVER_ANIMATION,
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_group_control(
Group_Control_Border::get_type(),
[
'name' => 'image_border',
'selector' => '{{WRAPPER}} img',
'separator' => 'before',
]
);
$this->add_responsive_control(
'image_border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->add_group_control(
Group_Control_Box_Shadow::get_type(),
[
'name' => 'image_box_shadow',
'exclude' => [
'box_shadow_position',
],
'selector' => '{{WRAPPER}} img',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style_caption',
[
'label' => esc_html__( 'Caption', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'image[url]!' => '',
'caption_source!' => 'none',
],
]
);
$this->add_responsive_control(
'caption_align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
'title' => esc_html__( 'Justified', 'elementor' ),
'icon' => 'eicon-text-align-justify',
],
],
'default' => '',
'selectors' => [
'{{WRAPPER}} .widget-image-caption' => 'text-align: {{VALUE}};',
],
]
);
$this->add_control(
'text_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .widget-image-caption' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
]
);
$this->add_control(
'caption_background_color',
[
'label' => esc_html__( 'Background Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .widget-image-caption' => 'background-color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'caption_typography',
'selector' => '{{WRAPPER}} .widget-image-caption',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'caption_text_shadow',
'selector' => '{{WRAPPER}} .widget-image-caption',
]
);
$this->add_responsive_control(
'caption_space',
[
'label' => esc_html__( 'Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'min' => 0,
'max' => 10,
],
'rem' => [
'min' => 0,
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}} .widget-image-caption' => 'margin-top: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
}
/**
* Check if the current widget has caption
*
* @access private
* @since 2.3.0
*
* @param array $settings
*
* @return boolean
*/
private function has_caption( $settings ) {
return ( ! empty( $settings['caption_source'] ) && 'none' !== $settings['caption_source'] );
}
/**
* Get the caption for current widget.
*
* @access private
* @since 2.3.0
* @param $settings
*
* @return string
*/
private function get_caption( $settings ) {
$caption = '';
if ( ! empty( $settings['caption_source'] ) ) {
switch ( $settings['caption_source'] ) {
case 'attachment':
$caption = wp_get_attachment_caption( $settings['image']['id'] );
break;
case 'custom':
$caption = ! Utils::is_empty( $settings['caption'] ) ? $settings['caption'] : '';
}
}
return $caption;
}
/**
* Render image 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();
if ( empty( $settings['image']['url'] ) ) {
return;
}
$has_caption = $this->has_caption( $settings );
$link = $this->get_link_url( $settings );
if ( $link ) {
$this->add_link_attributes( 'link', $link );
if ( Plugin::$instance->editor->is_edit_mode() ) {
$this->add_render_attribute( 'link', [
'class' => 'elementor-clickable',
] );
}
if ( 'custom' !== $settings['link_to'] ) {
$this->add_lightbox_data_attributes( 'link', $settings['image']['id'], $settings['open_lightbox'] );
}
} ?>
<?php if ( $has_caption ) : ?>
<figure class="wp-caption">
<?php endif; ?>
<?php if ( $link ) : ?>
<a <?php $this->print_render_attribute_string( 'link' ); ?>>
<?php endif; ?>
<?php Group_Control_Image_Size::print_attachment_image_html( $settings ); ?>
<?php if ( $link ) : ?>
</a>
<?php endif; ?>
<?php if ( $has_caption ) : ?>
<figcaption class="widget-image-caption wp-caption-text"><?php
echo wp_kses_post( $this->get_caption( $settings ) );
?></figcaption>
<?php endif; ?>
<?php if ( $has_caption ) : ?>
</figure>
<?php endif; ?>
<?php
}
/**
* Render image 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() {
?>
<# if ( settings.image.url ) {
var image = {
id: settings.image.id,
url: settings.image.url,
size: settings.image_size,
dimension: settings.image_custom_dimension,
model: view.getEditModel()
};
var image_url = elementor.imagesManager.getImageUrl( image );
if ( ! image_url ) {
return;
}
var hasCaption = function() {
if( ! settings.caption_source || 'none' === settings.caption_source ) {
return false;
}
return true;
}
var ensureAttachmentData = function( id ) {
if ( 'undefined' === typeof wp.media.attachment( id ).get( 'caption' ) ) {
wp.media.attachment( id ).fetch().then( function( data ) {
view.render();
} );
}
}
var getAttachmentCaption = function( id ) {
if ( ! id ) {
return '';
}
ensureAttachmentData( id );
return wp.media.attachment( id ).get( 'caption' );
}
var getCaption = function() {
if ( ! hasCaption() ) {
return '';
}
return 'custom' === settings.caption_source ? settings.caption : getAttachmentCaption( settings.image.id );
}
var link_url;
if ( 'custom' === settings.link_to ) {
link_url = settings.link.url;
}
if ( 'file' === settings.link_to ) {
link_url = settings.image.url;
}
var imgClass = '';
if ( '' !== settings.hover_animation ) {
imgClass = 'elementor-animation-' + settings.hover_animation;
}
if ( hasCaption() ) {
#><figure class="wp-caption"><#
}
if ( link_url ) {
#><a class="elementor-clickable" data-elementor-open-lightbox="{{ settings.open_lightbox }}" href="{{ elementor.helpers.sanitizeUrl( link_url ) }}"><#
}
#><img src="{{ image_url }}" class="{{ imgClass }}" /><#
if ( link_url ) {
#></a><#
}
if ( hasCaption() ) {
#><figcaption class="widget-image-caption wp-caption-text">{{{ getCaption() }}}</figcaption><#
}
if ( hasCaption() ) {
#></figure><#
}
} #>
<?php
}
/**
* Retrieve image widget link URL.
*
* @since 3.11.0
* @access protected
*
* @param array $settings
*
* @return array|string|false An array/string containing the link URL, or false if no link.
*/
protected function get_link_url( $settings ) {
if ( 'none' === $settings['link_to'] ) {
return false;
}
if ( 'custom' === $settings['link_to'] ) {
if ( empty( $settings['link']['url'] ) ) {
return false;
}
return $settings['link'];
}
return [
'url' => $settings['image']['url'],
];
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor Inner Section widget.
*
* Elementor widget that creates nested columns within a section.
*
* @since 3.5.0
*/
class Widget_Inner_Section extends Widget_Base {
/**
* @inheritDoc
*/
public static function get_type() {
return 'section';
}
/**
* @inheritDoc
*/
public function get_name() {
return 'inner-section';
}
/**
* @inheritDoc
*/
public function get_title() {
return esc_html__( 'Inner Section', 'elementor' );
}
/**
* @inheritDoc
*/
public function get_icon() {
return 'eicon-columns';
}
/**
* @inheritDoc
*/
public function get_categories() {
return [ 'basic' ];
}
/**
* @inheritDoc
*/
public function get_keywords() {
return [ 'row', 'columns', 'nested' ];
}
protected function is_dynamic_content(): bool {
return false;
}
}

View File

@@ -0,0 +1,186 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor menu anchor widget.
*
* Elementor widget that allows to link and menu to a specific position on the
* page.
*
* @since 1.0.0
*/
class Widget_Menu_Anchor extends Widget_Base {
/**
* Get widget name.
*
* Retrieve menu anchor widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'menu-anchor';
}
/**
* Get widget title.
*
* Retrieve menu anchor widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Menu Anchor', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve menu anchor widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-anchor';
}
/**
* 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 [ 'menu', 'anchor', 'link' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register menu anchor 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_anchor',
[
'label' => esc_html__( 'Menu Anchor', 'elementor' ),
]
);
$this->add_control(
'anchor',
[
'label' => esc_html__( 'The ID of Menu Anchor.', 'elementor' ),
'type' => Controls_Manager::TEXT,
'ai' => [
'active' => false,
],
'placeholder' => esc_html__( 'For Example: About', 'elementor' ),
'description' => esc_html__( 'This ID will be the CSS ID you will have to use in your own page, Without #.', 'elementor' ),
'label_block' => true,
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'anchor_note',
[
'type' => Controls_Manager::ALERT,
'alert_type' => 'warning',
'content' => sprintf(
/* translators: %s: Accepted chars. */
esc_html__( 'Note: The ID link ONLY accepts these chars: %s', 'elementor' ),
'`A-Z, a-z, 0-9, _ , -`'
),
]
);
$this->end_controls_section();
}
/**
* Render menu anchor widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$anchor = $this->get_settings_for_display( 'anchor' );
if ( empty( $anchor ) ) {
return;
}
$this->add_render_attribute(
'inner',
[
'class' => 'elementor-menu-anchor',
'id' => sanitize_html_class( $anchor ),
]
);
?>
<div <?php $this->print_render_attribute_string( 'inner' ); ?>></div>
<?php
}
/**
* Render menu anchor 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() {
?>
<#
if ( '' === settings.anchor ) {
return;
}
view.addRenderAttribute(
'inner',
{
'class': 'elementor-menu-anchor',
'id': settings.anchor,
}
);
#>
<div {{{ view.getRenderAttributeString( 'inner' ) }}}></div>
<?php
}
protected function on_save( array $settings ) {
$settings['anchor'] = sanitize_html_class( $settings['anchor'] );
return $settings;
}
}

View File

@@ -0,0 +1,492 @@
<?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 progress widget.
*
* Elementor widget that displays an escalating progress bar.
*
* @since 1.0.0
*/
class Widget_Progress extends Widget_Base {
/**
* Get widget name.
*
* Retrieve progress widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'progress';
}
/**
* Get widget title.
*
* Retrieve progress widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Progress Bar', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve progress widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-skill-bar';
}
/**
* 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 [ 'progress', 'bar' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register progress 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_progress',
[
'label' => esc_html__( 'Progress Bar', 'elementor' ),
]
);
$this->add_control(
'title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'placeholder' => esc_html__( 'Enter your title', 'elementor' ),
'default' => esc_html__( 'My Skill', 'elementor' ),
'label_block' => true,
]
);
$this->add_control(
'title_tag',
[
'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'div',
'span' => 'span',
'p' => 'p',
],
'default' => 'span',
'condition' => [
'title!' => '',
],
]
);
$this->add_control(
'progress_type',
[
'label' => esc_html__( 'Type', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'' => esc_html__( 'Default', 'elementor' ),
'info' => esc_html__( 'Info', 'elementor' ),
'success' => esc_html__( 'Success', 'elementor' ),
'warning' => esc_html__( 'Warning', 'elementor' ),
'danger' => esc_html__( 'Danger', 'elementor' ),
],
'default' => '',
'condition' => [
'progress_type!' => '', // a workaround to hide the control, unless it's in use (not default).
],
'separator' => 'before',
]
);
$this->add_control(
'percent',
[
'label' => esc_html__( 'Percentage', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 50,
'unit' => '%',
],
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'display_percentage',
[
'label' => esc_html__( 'Display Percentage', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_on' => esc_html__( 'Show', 'elementor' ),
'label_off' => esc_html__( 'Hide', 'elementor' ),
'return_value' => 'show',
'default' => 'show',
]
);
$this->add_control(
'inner_text',
[
'label' => esc_html__( 'Inner Text', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'placeholder' => esc_html__( 'e.g. Web Designer', 'elementor' ),
'default' => esc_html__( 'Web Designer', 'elementor' ),
'label_block' => true,
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_progress_style',
[
'label' => esc_html__( 'Progress Bar', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'bar_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
'selectors' => [
'{{WRAPPER}} .elementor-progress-wrapper .elementor-progress-bar' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'bar_bg_color',
[
'label' => esc_html__( 'Background Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-progress-wrapper' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'bar_height',
[
'label' => esc_html__( 'Height', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-progress-bar' => 'height: {{SIZE}}{{UNIT}}; line-height: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_control(
'bar_border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-progress-wrapper' => 'border-radius: {{SIZE}}{{UNIT}}; overflow: hidden;',
],
]
);
$this->add_control(
'inner_text_heading',
[
'label' => esc_html__( 'Inner Text', 'elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->add_control(
'bar_inline_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-progress-bar' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'bar_inner_typography',
'selector' => '{{WRAPPER}} .elementor-progress-bar',
'exclude' => [
'line_height',
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'bar_inner_shadow',
'selector' => '{{WRAPPER}} .elementor-progress-bar',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_title',
[
'label' => esc_html__( 'Title Style', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-title' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography',
'selector' => '{{WRAPPER}} .elementor-title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-title',
]
);
$this->end_controls_section();
}
/**
* Render progress widget output on the frontend.
* Make sure value does no exceed 100%.
*
* 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();
if ( empty( $settings['title'] ) && empty( $settings['percent']['size'] ) ) {
return;
}
$progressbar_id = 'elementor-progress-bar-' . $this->get_id();
$progress_percentage = is_numeric( $settings['percent']['size'] ) ? $settings['percent']['size'] : '0';
if ( 100 < $progress_percentage ) {
$progress_percentage = 100;
}
if ( ! Utils::is_empty( $settings['title'] ) ) {
$this->add_render_attribute(
'title',
[
'class' => 'elementor-title',
'id' => $progressbar_id,
]
);
$this->add_inline_editing_attributes( 'title' );
$this->add_render_attribute( 'wrapper', 'aria-labelledby', $progressbar_id );
}
$this->add_render_attribute(
'wrapper',
[
'class' => 'elementor-progress-wrapper',
'role' => 'progressbar',
'aria-valuemin' => '0',
'aria-valuemax' => '100',
'aria-valuenow' => $progress_percentage,
]
);
if ( ! empty( $settings['inner_text'] ) ) {
$this->add_render_attribute( 'wrapper', 'aria-valuetext', "{$progress_percentage}% ({$settings['inner_text']})" );
}
if ( ! empty( $settings['progress_type'] ) ) {
$this->add_render_attribute( 'wrapper', 'class', 'progress-' . $settings['progress_type'] );
}
$this->add_render_attribute(
'progress-bar',
[
'class' => 'elementor-progress-bar',
'data-max' => $progress_percentage,
]
);
$this->add_render_attribute( 'inner_text', 'class', 'elementor-progress-text' );
$this->add_inline_editing_attributes( 'inner_text' );
if ( ! Utils::is_empty( $settings['title'] ) ) { ?>
<<?php Utils::print_validated_html_tag( $settings['title_tag'] ); ?> <?php $this->print_render_attribute_string( 'title' ); ?>>
<?php $this->print_unescaped_setting( 'title' ); ?>
</<?php Utils::print_validated_html_tag( $settings['title_tag'] ); ?>>
<?php } ?>
<div <?php $this->print_render_attribute_string( 'wrapper' ); ?>>
<div <?php $this->print_render_attribute_string( 'progress-bar' ); ?>>
<span <?php $this->print_render_attribute_string( 'inner_text' ); ?>><?php $this->print_unescaped_setting( 'inner_text' ); ?></span>
<?php if ( 'show' === $settings['display_percentage'] ) { ?>
<span class="elementor-progress-percentage"><?php echo $progress_percentage; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>%</span>
<?php } ?>
</div>
</div>
<?php
}
/**
* Render progress 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() {
?>
<#
if ( '' === settings.title && '' === settings.percent.size ) {
return;
}
const title_tag = elementor.helpers.validateHTMLTag( settings.title_tag );
const progressbar_id = 'elementor-progress-bar-<?php echo esc_attr( $this->get_id() ); ?>';
let progress_percentage = 0;
if ( ! isNaN( settings.percent.size ) ) {
progress_percentage = 100 < settings.percent.size ? 100 : settings.percent.size;
}
if ( settings.title ) {
view.addRenderAttribute(
'title',
{
'class': 'elementor-title',
'id': progressbar_id,
}
);
view.addInlineEditingAttributes( 'title' );
view.addRenderAttribute( 'wrapper', 'aria-labelledby', progressbar_id );
}
view.addRenderAttribute(
'progressWrapper',
{
'class': [ 'elementor-progress-wrapper', 'progress-' + settings.progress_type ],
'role': 'progressbar',
'aria-valuemin': '0',
'aria-valuemax': '100',
'aria-valuenow': progress_percentage,
}
);
if ( '' !== settings.inner_text ) {
view.addRenderAttribute( 'progressWrapper', 'aria-valuetext', progress_percentage + '% (' + settings.inner_text + ')' );
}
view.addRenderAttribute( 'inner_text', 'class', 'elementor-progress-text' );
view.addInlineEditingAttributes( 'inner_text' );
#>
<# if ( settings.title ) { #>
<{{ title_tag }} {{{ view.getRenderAttributeString( 'title' ) }}}>{{{ settings.title }}}</{{ title_tag }}>
<# } #>
<div {{{ view.getRenderAttributeString( 'progressWrapper' ) }}}>
<div class="elementor-progress-bar" data-max="{{ progress_percentage }}">
<span {{{ view.getRenderAttributeString( 'inner_text' ) }}}>{{{ settings.inner_text }}}</span>
<# if ( 'show' === settings.display_percentage ) { #>
<span class="elementor-progress-percentage">{{{ progress_percentage }}}%</span>
<# } #>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,315 @@
<?php
namespace Elementor;
use Elementor\Icons_Manager;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor (new) rating widget.
*
* @since 3.17.0
*/
class Widget_Rating extends Widget_Base {
public function get_name() {
return 'rating';
}
public function get_title() {
return esc_html__( 'Rating', 'elementor' );
}
public function get_icon() {
return 'eicon-rating';
}
public function get_keywords() {
return [ 'star', 'rating', 'review', 'score', 'scale' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* @return void
*/
private function add_style_tab() {
$this->start_controls_section(
'section_icon_style',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'icon_size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'min' => 0,
'max' => 10,
],
'rem' => [
'min' => 0,
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}}' => '--e-rating-icon-font-size: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_responsive_control(
'icon_gap',
[
'label' => esc_html__( 'Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'min' => 0,
'max' => 10,
],
'rem' => [
'min' => 0,
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}}' => '--e-rating-gap: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_control(
'icon_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}}' => '--e-rating-icon-marked-color: {{VALUE}}',
],
'separator' => 'before',
]
);
$this->add_control(
'icon_unmarked_color',
[
'label' => esc_html__( 'Unmarked Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}}' => '--e-rating-icon-color: {{VALUE}}',
],
]
);
$this->end_controls_section();
}
protected function register_controls() {
$start_logical = is_rtl() ? 'end' : 'start';
$end_logical = is_rtl() ? 'start' : 'end';
$this->start_controls_section(
'section_rating',
[
'label' => esc_html__( 'Rating', 'elementor' ),
]
);
$this->add_control(
'rating_scale',
[
'label' => esc_html__( 'Rating Scale', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => 1,
'max' => 10,
],
],
'default' => [
'size' => 5,
],
]
);
$this->add_control(
'rating_value',
[
'label' => esc_html__( 'Rating', 'elementor' ),
'type' => Controls_Manager::NUMBER,
'min' => 0,
'step' => 0.5,
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'rating_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'fa4compatibility' => 'icon',
'skin' => 'inline',
'label_block' => false,
'skin_settings' => [
'inline' => [
'icon' => [
'icon' => 'eicon-star',
],
],
],
'default' => [
'value' => 'eicon-star',
'library' => 'eicons',
],
'separator' => 'before',
'exclude_inline_options' => [ 'none' ],
]
);
$this->add_responsive_control( 'icon_alignment', [
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'start' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => "eicon-align-$start_logical-h",
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-align-center-h',
],
'end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => "eicon-align-$end_logical-h",
],
],
'selectors_dictionary' => [
'start' => '--e-rating-justify-content: flex-start;',
'center' => '--e-rating-justify-content: center;',
'end' => '--e-rating-justify-content: flex-end;',
],
'selectors' => [
'{{WRAPPER}}' => '{{VALUE}}',
],
'separator' => 'before',
] );
$this->end_controls_section();
$this->add_style_tab();
}
protected function get_rating_value(): float {
$initial_value = $this->get_rating_scale();
$rating_value = $this->get_settings_for_display( 'rating_value' );
if ( '' === $rating_value ) {
$rating_value = $initial_value;
}
$rating_value = floatval( $rating_value );
return round( $rating_value, 2 );
}
protected function get_rating_scale(): int {
return intval( $this->get_settings_for_display( 'rating_scale' )['size'] );
}
protected function get_icon_marked_width( $icon_index ): string {
$rating_value = $this->get_rating_value();
$width = '0%';
if ( $rating_value >= $icon_index ) {
$width = '100%';
} elseif ( intval( ceil( $rating_value ) ) === $icon_index ) {
$width = ( $rating_value - ( $icon_index - 1 ) ) * 100 . '%';
}
return $width;
}
protected function get_icon_markup(): string {
$icon = $this->get_settings_for_display( 'rating_icon' );
$rating_scale = $this->get_rating_scale();
ob_start();
for ( $index = 1; $index <= $rating_scale; $index++ ) {
$this->add_render_attribute( 'icon_marked_' . $index, [
'class' => 'e-icon-wrapper e-icon-marked',
] );
$icon_marked_width = $this->get_icon_marked_width( $index );
if ( '100%' !== $icon_marked_width ) {
$this->add_render_attribute( 'icon_marked_' . $index, [
'style' => '--e-rating-icon-marked-width: ' . $icon_marked_width . ';',
] );
}
?>
<div class="e-icon">
<div <?php $this->print_render_attribute_string( 'icon_marked_' . $index ); ?>>
<?php echo Icons_Manager::try_get_icon_html( $icon, [ 'aria-hidden' => 'true' ] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<div class="e-icon-wrapper e-icon-unmarked">
<?php echo Icons_Manager::try_get_icon_html( $icon, [ 'aria-hidden' => 'true' ] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
</div>
<?php
}
return ob_get_clean();
}
protected function render() {
$this->add_render_attribute( 'widget', [
'class' => 'e-rating',
'itemtype' => 'https://schema.org/Rating',
'itemscope' => '',
'itemprop' => 'reviewRating',
] );
$this->add_render_attribute( 'widget_wrapper', [
'class' => 'e-rating-wrapper',
'itemprop' => 'ratingValue',
'content' => $this->get_rating_value(),
'role' => 'img',
'aria-label' => sprintf( esc_html__( 'Rated %1$s out of %2$s', 'elementor' ),
$this->get_rating_value(),
$this->get_rating_scale()
),
] );
?>
<div <?php $this->print_render_attribute_string( 'widget' ); ?>>
<meta itemprop="worstRating" content="0">
<meta itemprop="bestRating" content="<?php echo $this->get_rating_scale(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>">
<div <?php $this->print_render_attribute_string( 'widget_wrapper' ); ?>>
<?php echo $this->get_icon_markup(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,157 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor HTML widget.
*
* Elementor widget that insert a custom HTML code into the page.
*
*/
class Widget_Read_More extends Widget_Base {
/**
* Get widget name.
*
* Retrieve Read More widget name.
*
* @since 2.4.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'read-more';
}
/**
* Get widget title.
*
* Retrieve Read More widget title.
*
* @since 2.4.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Read More', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve Read More widget icon.
*
* @since 2.4.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-post-excerpt';
}
/**
* Get widget keywords.
*
* Retrieve the list of keywords the widget belongs to.
*
* @since 2.4.0
* @access public
*
* @return array Widget keywords.
*/
public function get_keywords() {
return [ 'read', 'more', 'tag', 'excerpt' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register HTML 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_title',
[
'label' => esc_html__( 'Read More', 'elementor' ),
]
);
$default_link_text = esc_html__( 'Continue reading', 'elementor' );
/**
* Read More widgets link text.
*
* Filters the link text in the "Read More" widget.
*
* This hook can be used to set different default text in the widget.
*
* @param string $default_link_text The link text in the "Read More" widget. Default is "Continue reading".
*/
$default_link_text = apply_filters( 'elementor/widgets/read_more/default_link_text', $default_link_text );
$this->add_control(
'theme_support',
[
'type' => Controls_Manager::ALERT,
'alert_type' => 'warning',
'content' => sprintf(
/* translators: %s: The `the_content` function. */
esc_html__( 'Note: This widget only affects themes that use `%s` in archive pages.', 'elementor' ),
'the_content'
),
]
);
$this->add_control(
'link_text',
[
'label' => esc_html__( 'Read More Text', 'elementor' ),
'placeholder' => $default_link_text,
'default' => $default_link_text,
'dynamic' => [
'active' => true,
],
]
);
$this->end_controls_section();
}
/**
* Render Read More widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @access protected
*/
protected function render() {
printf( '<!--more %s-->', wp_kses_post( $this->get_settings_for_display( 'link_text' ) ) );
}
/**
* Render Read More 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() {
?>
<!--more {{ settings.link_text }}-->
<?php
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* @deprecated will be removed in version 3.24
*/
class Widget_Share_Buttons extends Widget_Base {
private static $supported_networks = [
'facebook',
'x-twitter',
'twitter',
'linkedin',
'pinterest',
'threads',
'reddit',
'vk',
'odnoklassniki',
'tumblr',
'digg',
'skype',
'stumbleupon',
'mix',
'telegram',
'pocket',
'xing',
'whatsapp',
'email',
'print',
];
/**
* @deprecated will be removed in version 3.24
*/
public function get_name() {
return 'share-buttons-dummy';
}
/**
* @deprecated will be removed in version 3.24
*/
public function get_title() {
return 'share-buttons-dummy';
}
/**
* @deprecated will be removed in version 3.24
*/
public function show_in_panel(): bool {
return false;
}
/**
* @deprecated will be removed in version 3.24
*/
public static function get_supported_networks(): array {
return self::$supported_networks;
}
}

View File

@@ -0,0 +1,165 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor shortcode widget.
*
* Elementor widget that insert any shortcodes into the page.
*
* @since 1.0.0
*/
class Widget_Shortcode extends Widget_Base {
/**
* Get widget name.
*
* Retrieve shortcode widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'shortcode';
}
/**
* Get widget title.
*
* Retrieve shortcode widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Shortcode', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve shortcode widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-shortcode';
}
/**
* 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 [ 'shortcode', 'code' ];
}
/**
* Whether the reload preview is required or not.
*
* Used to determine whether the reload preview is required.
*
* @since 1.0.0
* @access public
*
* @return bool Whether the reload preview is required.
*/
public function is_reload_preview_required() {
return true;
}
/**
* Register shortcode 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_shortcode',
[
'label' => esc_html__( 'Shortcode', 'elementor' ),
]
);
$this->add_control(
'shortcode',
[
'label' => esc_html__( 'Enter your shortcode', 'elementor' ),
'type' => Controls_Manager::TEXTAREA,
'dynamic' => [
'active' => true,
],
'ai' => [
'active' => false,
],
'placeholder' => '[gallery id="123" size="medium"]',
'default' => '',
]
);
$this->end_controls_section();
}
/**
* Render shortcode widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$shortcode = $this->get_settings_for_display( 'shortcode' );
if ( empty( $shortcode ) ) {
return;
}
$shortcode = do_shortcode( shortcode_unautop( $shortcode ) );
?>
<div class="elementor-shortcode"><?php echo $shortcode; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
<?php
}
/**
* Render shortcode widget as plain content.
*
* Override the default behavior by printing the shortcode instead of rendering it.
*
* @since 1.0.0
* @access public
*/
public function render_plain_content() {
// In plain mode, render without shortcode
$this->print_unescaped_setting( 'shortcode' );
}
/**
* Render shortcode 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 File

@@ -0,0 +1,156 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor sidebar widget.
*
* Elementor widget that insert any sidebar into the page.
*
* @since 1.0.0
*/
class Widget_Sidebar extends Widget_Base {
/**
* Get widget name.
*
* Retrieve sidebar widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'sidebar';
}
/**
* Get widget title.
*
* Retrieve sidebar widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Sidebar', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve sidebar widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-sidebar';
}
/**
* 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 [ 'sidebar', 'widget' ];
}
/**
* Register sidebar 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() {
global $wp_registered_sidebars;
$options = [];
if ( ! $wp_registered_sidebars ) {
$options[''] = esc_html__( 'No sidebars were found', 'elementor' );
} else {
$options[''] = esc_html__( 'Choose Sidebar', 'elementor' );
foreach ( $wp_registered_sidebars as $sidebar_id => $sidebar ) {
$options[ $sidebar_id ] = $sidebar['name'];
}
}
$default_key = array_keys( $options );
$default_key = array_shift( $default_key );
$this->start_controls_section(
'section_sidebar',
[
'label' => esc_html__( 'Sidebar', 'elementor' ),
]
);
$this->add_control(
'sidebar',
[
'label' => esc_html__( 'Choose Sidebar', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => $default_key,
'options' => $options,
]
);
$this->end_controls_section();
}
/**
* Render sidebar widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$sidebar = $this->get_settings_for_display( 'sidebar' );
if ( empty( $sidebar ) ) {
return;
}
dynamic_sidebar( $sidebar );
}
/**
* Render sidebar 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() {}
/**
* Render sidebar widget as plain content.
*
* Override the default render behavior, don't render sidebar content.
*
* @since 1.0.0
* @access public
*/
public function render_plain_content() {}
}

View File

@@ -0,0 +1,679 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor social icons widget.
*
* Elementor widget that displays icons to social pages like Facebook and Twitter.
*
* @since 1.0.0
*/
class Widget_Social_Icons extends Widget_Base {
/**
* Get widget name.
*
* Retrieve social icons widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'social-icons';
}
/**
* Get widget title.
*
* Retrieve social icons widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Social Icons', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve social icons widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-social-icons';
}
/**
* 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 [ 'social', 'icon', 'link' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register social icons 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_social_icon',
[
'label' => esc_html__( 'Social Icons', 'elementor' ),
]
);
$repeater = new Repeater();
$repeater->add_control(
'social_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'fa4compatibility' => 'social',
'default' => [
'value' => 'fab fa-wordpress',
'library' => 'fa-brands',
],
'recommended' => [
'fa-brands' => [
'android',
'apple',
'behance',
'bitbucket',
'codepen',
'delicious',
'deviantart',
'digg',
'dribbble',
'elementor',
'facebook',
'flickr',
'foursquare',
'free-code-camp',
'github',
'gitlab',
'globe',
'houzz',
'instagram',
'jsfiddle',
'linkedin',
'medium',
'meetup',
'mix',
'mixcloud',
'odnoklassniki',
'pinterest',
'product-hunt',
'reddit',
'shopping-cart',
'skype',
'slideshare',
'snapchat',
'soundcloud',
'spotify',
'stack-overflow',
'steam',
'telegram',
'thumb-tack',
'threads',
'tripadvisor',
'tumblr',
'twitch',
'twitter',
'viber',
'vimeo',
'vk',
'weibo',
'weixin',
'whatsapp',
'wordpress',
'xing',
'x-twitter',
'yelp',
'youtube',
'500px',
],
'fa-solid' => [
'envelope',
'link',
'rss',
],
],
]
);
$repeater->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'default' => [
'is_external' => 'true',
],
'dynamic' => [
'active' => true,
],
]
);
$repeater->add_control(
'item_icon_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'default',
'options' => [
'default' => esc_html__( 'Official Color', 'elementor' ),
'custom' => esc_html__( 'Custom', 'elementor' ),
],
]
);
$repeater->add_control(
'item_icon_primary_color',
[
'label' => esc_html__( 'Primary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'condition' => [
'item_icon_color' => 'custom',
],
'selectors' => [
'{{WRAPPER}} {{CURRENT_ITEM}}.elementor-social-icon' => 'background-color: {{VALUE}};',
],
]
);
$repeater->add_control(
'item_icon_secondary_color',
[
'label' => esc_html__( 'Secondary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'condition' => [
'item_icon_color' => 'custom',
],
'selectors' => [
'{{WRAPPER}} {{CURRENT_ITEM}}.elementor-social-icon i' => 'color: {{VALUE}};',
'{{WRAPPER}} {{CURRENT_ITEM}}.elementor-social-icon svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_control(
'social_icon_list',
[
'label' => esc_html__( 'Social Icons', 'elementor' ),
'type' => Controls_Manager::REPEATER,
'fields' => $repeater->get_controls(),
'default' => [
[
'social_icon' => [
'value' => 'fab fa-facebook',
'library' => 'fa-brands',
],
],
[
'social_icon' => [
'value' => 'fab fa-twitter',
'library' => 'fa-brands',
],
],
[
'social_icon' => [
'value' => 'fab fa-youtube',
'library' => 'fa-brands',
],
],
],
'title_field' => '<# var migrated = "undefined" !== typeof __fa4_migrated, social = ( "undefined" === typeof social ) ? false : social; #>{{{ elementor.helpers.getSocialNetworkNameFromIcon( social_icon, social, true, migrated, true ) }}}',
]
);
$this->add_control(
'shape',
[
'label' => esc_html__( 'Shape', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'rounded',
'options' => [
'rounded' => esc_html__( 'Rounded', 'elementor' ),
'square' => esc_html__( 'Square', 'elementor' ),
'circle' => esc_html__( 'Circle', 'elementor' ),
],
'prefix_class' => 'elementor-shape-',
]
);
$this->add_responsive_control(
'columns',
[
'label' => esc_html__( 'Columns', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => '0',
'options' => [
'0' => esc_html__( 'Auto', 'elementor' ),
'1' => '1',
'2' => '2',
'3' => '3',
'4' => '4',
'5' => '5',
'6' => '6',
],
'prefix_class' => 'elementor-grid%s-',
'selectors' => [
'{{WRAPPER}}' => '--grid-template-columns: repeat({{VALUE}}, auto);',
],
]
);
$start = is_rtl() ? 'end' : 'start';
$end = is_rtl() ? 'start' : 'end';
$this->add_responsive_control(
'align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
],
'prefix_class' => 'e-grid-align%s-',
'default' => 'center',
'selectors' => [
'{{WRAPPER}} .elementor-widget-container' => 'text-align: {{VALUE}}',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_social_style',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'icon_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'default',
'options' => [
'default' => esc_html__( 'Official Color', 'elementor' ),
'custom' => esc_html__( 'Custom', 'elementor' ),
],
]
);
$this->add_control(
'icon_primary_color',
[
'label' => esc_html__( 'Primary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'condition' => [
'icon_color' => 'custom',
],
'selectors' => [
'{{WRAPPER}} .elementor-social-icon' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'icon_secondary_color',
[
'label' => esc_html__( 'Secondary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'condition' => [
'icon_color' => 'custom',
],
'selectors' => [
'{{WRAPPER}} .elementor-social-icon i' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-social-icon svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'icon_size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SLIDER,
// The `%' and `em` units are not supported as the widget implements icons differently then other icons.
'size_units' => [ 'px', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'min' => 6,
'max' => 300,
],
],
'selectors' => [
'{{WRAPPER}}' => '--icon-size: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_responsive_control(
'icon_padding',
[
'label' => esc_html__( 'Padding', 'elementor' ),
'type' => Controls_Manager::SLIDER,
// The `%' unit is not supported.
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-social-icon' => '--icon-padding: {{SIZE}}{{UNIT}}',
],
'default' => [
'unit' => 'em',
],
'tablet_default' => [
'unit' => 'em',
],
'mobile_default' => [
'unit' => 'em',
],
'range' => [
'px' => [
'max' => 50,
],
'em' => [
'min' => 0,
'max' => 5,
],
'rem' => [
'min' => 0,
'max' => 5,
],
],
]
);
$this->add_responsive_control(
'icon_spacing',
[
'label' => esc_html__( 'Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'min' => 0,
'max' => 10,
],
'rem' => [
'min' => 0,
'max' => 10,
],
],
'default' => [
'size' => 5,
],
'selectors' => [
'{{WRAPPER}}' => '--grid-column-gap: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_responsive_control(
'row_gap',
[
'label' => esc_html__( 'Rows Gap', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'default' => [
'size' => 0,
],
'selectors' => [
'{{WRAPPER}}' => '--grid-row-gap: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_group_control(
Group_Control_Border::get_type(),
[
'name' => 'image_border', // We know this mistake - TODO: 'icon_border' (for hover control condition also)
'selector' => '{{WRAPPER}} .elementor-social-icon',
'separator' => 'before',
]
);
$this->add_responsive_control(
'border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-icon' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_social_hover',
[
'label' => esc_html__( 'Icon Hover', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'hover_primary_color',
[
'label' => esc_html__( 'Primary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'condition' => [
'icon_color' => 'custom',
],
'selectors' => [
'{{WRAPPER}} .elementor-social-icon:hover' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'hover_secondary_color',
[
'label' => esc_html__( 'Secondary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'condition' => [
'icon_color' => 'custom',
],
'selectors' => [
'{{WRAPPER}} .elementor-social-icon:hover i' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-social-icon:hover svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_control(
'hover_border_color',
[
'label' => esc_html__( 'Border Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'condition' => [
'image_border_border!' => '',
],
'selectors' => [
'{{WRAPPER}} .elementor-social-icon:hover' => 'border-color: {{VALUE}};',
],
]
);
$this->add_control(
'hover_animation',
[
'label' => esc_html__( 'Hover Animation', 'elementor' ),
'type' => Controls_Manager::HOVER_ANIMATION,
]
);
$this->end_controls_section();
}
/**
* Render social icons 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-facebook',
'fa fa-twitter',
'fa fa-google-plus',
];
$class_animation = '';
if ( ! empty( $settings['hover_animation'] ) ) {
$class_animation = ' elementor-animation-' . $settings['hover_animation'];
}
$migration_allowed = Icons_Manager::is_migration_allowed();
?>
<div class="elementor-social-icons-wrapper elementor-grid">
<?php
foreach ( $settings['social_icon_list'] as $index => $item ) {
$migrated = isset( $item['__fa4_migrated']['social_icon'] );
$is_new = empty( $item['social'] ) && $migration_allowed;
$social = '';
// add old default
if ( empty( $item['social'] ) && ! $migration_allowed ) {
$item['social'] = isset( $fallback_defaults[ $index ] ) ? $fallback_defaults[ $index ] : 'fa fa-wordpress';
}
if ( ! empty( $item['social'] ) ) {
$social = str_replace( 'fa fa-', '', $item['social'] );
}
if ( ( $is_new || $migrated ) && 'svg' !== $item['social_icon']['library'] ) {
$social = explode( ' ', $item['social_icon']['value'], 2 );
if ( empty( $social[1] ) ) {
$social = '';
} else {
$social = str_replace( 'fa-', '', $social[1] );
}
}
if ( 'svg' === $item['social_icon']['library'] ) {
$social = get_post_meta( $item['social_icon']['value']['id'], '_wp_attachment_image_alt', true );
}
$link_key = 'link_' . $index;
$this->add_render_attribute( $link_key, 'class', [
'elementor-icon',
'elementor-social-icon',
'elementor-social-icon-' . $social . $class_animation,
'elementor-repeater-item-' . $item['_id'],
] );
$this->add_link_attributes( $link_key, $item['link'] );
?>
<span class="elementor-grid-item">
<a <?php $this->print_render_attribute_string( $link_key ); ?>>
<span class="elementor-screen-only"><?php echo esc_html( ucwords( $social ) ); ?></span>
<?php
if ( $is_new || $migrated ) {
Icons_Manager::render_icon( $item['social_icon'] );
} else { ?>
<i class="<?php echo esc_attr( $item['social'] ); ?>"></i>
<?php } ?>
</a>
</span>
<?php } ?>
</div>
<?php
}
/**
* Render social icons 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() {
?>
<# var iconsHTML = {}; #>
<div class="elementor-social-icons-wrapper elementor-grid">
<# _.each( settings.social_icon_list, function( item, index ) {
var link = item.link ? item.link.url : '',
migrated = elementor.helpers.isIconMigrated( item, 'social_icon' );
social = elementor.helpers.getSocialNetworkNameFromIcon( item.social_icon, item.social, false, migrated );
#>
<span class="elementor-grid-item">
<a class="elementor-icon elementor-social-icon elementor-social-icon-{{ social }} elementor-animation-{{ settings.hover_animation }} elementor-repeater-item-{{item._id}}" href="{{ elementor.helpers.sanitizeUrl( link ) }}">
<span class="elementor-screen-only">{{{ social }}}</span>
<#
iconsHTML[ index ] = elementor.helpers.renderIcon( view, item.social_icon, {}, 'i', 'object' );
if ( ( ! item.social || migrated ) && iconsHTML[ index ] && iconsHTML[ index ].rendered ) { #>
{{{ iconsHTML[ index ].value }}}
<# } else { #>
<i class="{{ item.social }}"></i>
<# }
#>
</a>
</span>
<# } ); #>
</div>
<?php
}
}

View File

@@ -0,0 +1,177 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor spacer widget.
*
* Elementor widget that inserts a space that divides various elements.
*
* @since 1.0.0
*/
class Widget_Spacer extends Widget_Base {
/**
* Get widget name.
*
* Retrieve spacer widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'spacer';
}
/**
* Get widget title.
*
* Retrieve spacer widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Spacer', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve spacer widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-spacer';
}
/**
* Get widget categories.
*
* Retrieve the list of categories the spacer widget belongs to.
*
* Used to determine where to display the widget in the editor.
*
* @since 1.0.0
* @access public
*
* @return array Widget categories.
*/
public function get_categories() {
return [ 'basic' ];
}
/**
* 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 [ 'space' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register spacer 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_spacer',
[
'label' => esc_html__( 'Spacer', 'elementor' ),
]
);
$this->add_responsive_control(
'space',
[
'label' => esc_html__( 'Space', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 50,
],
'size_units' => [ 'px', 'em', 'rem', 'vh', 'custom' ],
'range' => [
'px' => [
'max' => 600,
],
'em' => [
'max' => 20,
],
],
'render_type' => 'template',
'selectors' => [
'{{WRAPPER}}' => '--spacer-size: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
}
/**
* Render spacer 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();
if ( empty( $settings['space'] ) || empty( $settings['space']['size'] ) || 0 === $settings['space']['size'] ) {
return;
}
?>
<div class="elementor-spacer">
<div class="elementor-spacer-inner"></div>
</div>
<?php
}
/**
* Render spacer 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() {
?>
<#
if ( '' === settings.space || '' === settings.space.size || 0 === settings.space.size ) {
return;
}
#>
<div class="elementor-spacer">
<div class="elementor-spacer-inner"></div>
</div>
<?php
}
}

View File

@@ -0,0 +1,535 @@
<?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 star rating widget.
*
* Elementor widget that displays star rating.
*
* @since 2.3.0
*/
class Widget_Star_Rating extends Widget_Base {
/**
* Get widget name.
*
* Retrieve star rating widget name.
*
* @since 2.3.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'star-rating';
}
/**
* Get widget title.
*
* Retrieve star rating widget title.
*
* @since 2.3.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Star Rating', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve star rating widget icon.
*
* @since 2.3.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-rating';
}
/**
* Get widget keywords.
*
* Retrieve the list of keywords the widget belongs to.
*
* @since 2.3.0
* @access public
*
* @return array Widget keywords.
*/
public function get_keywords() {
return [ 'star', 'rating', 'rate', 'review' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Hide widget from panel.
*
* Hide the star rating widget from the panel.
*
* @since 3.17.0
* @return bool
*/
public function show_in_panel(): bool {
return false;
}
/**
* Register star rating 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_rating',
[
'label' => esc_html__( 'Star Rating', 'elementor' ),
]
);
if ( Plugin::$instance->widgets_manager->get_widget_types( 'rating' ) ) {
$this->add_deprecation_message(
'3.17.0',
esc_html__(
'You are currently editing a Star Rating widget in its old version. Drag a new Rating widget onto your page to use a newer version, providing better capabilities.',
'elementor'
),
'rating'
);
}
$this->add_control(
'rating_scale',
[
'label' => esc_html__( 'Rating Scale', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'5' => '0-5',
'10' => '0-10',
],
'default' => '5',
]
);
$this->add_control(
'rating',
[
'label' => esc_html__( 'Rating', 'elementor' ),
'type' => Controls_Manager::NUMBER,
'min' => 0,
'max' => 10,
'step' => 0.1,
'default' => 5,
'dynamic' => [
'active' => true,
],
]
);
$this->add_control(
'star_style',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'star_fontawesome' => 'Font Awesome',
'star_unicode' => 'Unicode',
],
'default' => 'star_fontawesome',
'render_type' => 'template',
'prefix_class' => 'elementor--star-style-',
'separator' => 'before',
]
);
$this->add_control(
'unmarked_star_style',
[
'label' => esc_html__( 'Unmarked Style', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'solid' => [
'title' => esc_html__( 'Solid', 'elementor' ),
'icon' => 'eicon-star',
],
'outline' => [
'title' => esc_html__( 'Outline', 'elementor' ),
'icon' => 'eicon-star-o',
],
],
'default' => 'solid',
]
);
$this->add_control(
'title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'separator' => 'before',
'dynamic' => [
'active' => true,
],
]
);
$this->add_responsive_control(
'align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
'title' => esc_html__( 'Justified', 'elementor' ),
'icon' => 'eicon-text-align-justify',
],
],
'prefix_class' => 'elementor-star-rating%s--align-',
'selectors' => [
'{{WRAPPER}}' => 'text-align: {{VALUE}}',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_title_style',
[
'label' => esc_html__( 'Title', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'title!' => '',
],
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
'selectors' => [
'{{WRAPPER}} .elementor-star-rating__title' => 'color: {{VALUE}}',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'title_typography',
'selector' => '{{WRAPPER}} .elementor-star-rating__title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-star-rating__title',
]
);
$this->add_responsive_control(
'title_gap',
[
'label' => esc_html__( 'Gap', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 50,
],
'em' => [
'min' => 0,
'max' => 5,
],
'rem' => [
'min' => 0,
'max' => 5,
],
],
'selectors' => [
'body:not(.rtl) {{WRAPPER}}:not(.elementor-star-rating--align-justify) .elementor-star-rating__title' => 'margin-right: {{SIZE}}{{UNIT}}',
'body.rtl {{WRAPPER}}:not(.elementor-star-rating--align-justify) .elementor-star-rating__title' => 'margin-left: {{SIZE}}{{UNIT}}',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_stars_style',
[
'label' => esc_html__( 'Stars', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'icon_size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'min' => 0,
'max' => 10,
],
'rem' => [
'min' => 0,
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-star-rating' => 'font-size: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_responsive_control(
'icon_space',
[
'label' => esc_html__( 'Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 50,
],
'em' => [
'min' => 0,
'max' => 5,
],
'rem' => [
'min' => 0,
'max' => 5,
],
],
'selectors' => [
'body:not(.rtl) {{WRAPPER}} .elementor-star-rating i:not(:last-of-type)' => 'margin-right: {{SIZE}}{{UNIT}}',
'body.rtl {{WRAPPER}} .elementor-star-rating i:not(:last-of-type)' => 'margin-left: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_control(
'stars_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-star-rating i:before' => 'color: {{VALUE}}',
],
'separator' => 'before',
]
);
$this->add_control(
'stars_unmarked_color',
[
'label' => esc_html__( 'Unmarked Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-star-rating i' => 'color: {{VALUE}}',
],
]
);
$this->end_controls_section();
}
/**
* @since 2.3.0
* @access protected
*/
protected function get_rating() {
$settings = $this->get_settings_for_display();
$rating_scale = (int) $settings['rating_scale'];
$rating = (float) $settings['rating'] > $rating_scale ? $rating_scale : $settings['rating'];
return [ $rating, $rating_scale ];
}
/**
* Print the actual stars and calculate their filling.
*
* Rating type is float to allow stars-count to be a fraction.
* Floored-rating type is int, to represent the rounded-down stars count.
* In the `for` loop, the index type is float to allow comparing with the rating value.
*
* @since 2.3.0
* @access protected
*/
protected function render_stars( $icon ) {
$rating_data = $this->get_rating();
$rating = (float) $rating_data[0];
$floored_rating = floor( $rating );
$stars_html = '';
for ( $stars = 1.0; $stars <= $rating_data[1]; $stars++ ) {
if ( $stars <= $floored_rating ) {
$stars_html .= '<i class="elementor-star-full">' . $icon . '</i>';
} elseif ( $floored_rating + 1 === $stars && $rating !== $floored_rating ) {
$stars_html .= '<i class="elementor-star-' . ( $rating - $floored_rating ) * 10 . '">' . $icon . '</i>';
} else {
$stars_html .= '<i class="elementor-star-empty">' . $icon . '</i>';
}
}
return $stars_html;
}
/**
* @since 2.3.0
* @access protected
*/
protected function render() {
$settings = $this->get_settings_for_display();
$rating_data = $this->get_rating();
$textual_rating = $rating_data[0] . '/' . $rating_data[1];
$icon = '&#xE934;';
if ( 'star_fontawesome' === $settings['star_style'] ) {
if ( 'outline' === $settings['unmarked_star_style'] ) {
$icon = '&#xE933;';
}
} elseif ( 'star_unicode' === $settings['star_style'] ) {
$icon = '&#9733;';
if ( 'outline' === $settings['unmarked_star_style'] ) {
$icon = '&#9734;';
}
}
$this->add_render_attribute( 'icon_wrapper', [
'class' => 'elementor-star-rating',
'title' => $textual_rating,
'itemtype' => 'http://schema.org/Rating',
'itemscope' => '',
'itemprop' => 'reviewRating',
] );
$schema_rating = '<span itemprop="ratingValue" class="elementor-screen-only">' . $textual_rating . '</span>';
$stars_element = '<div ' . $this->get_render_attribute_string( 'icon_wrapper' ) . '>' . $this->render_stars( $icon ) . ' ' . $schema_rating . '</div>';
?>
<div class="elementor-star-rating__wrapper">
<?php if ( ! Utils::is_empty( $settings['title'] ) ) : ?>
<div class="elementor-star-rating__title"><?php echo esc_html( $settings['title'] ); ?></div>
<?php endif;
// PHPCS - $stars_element contains an HTML string that cannot be escaped. ?>
<?php echo $stars_element; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php
}
/**
* @since 2.9.0
* @access protected
*/
protected function content_template() {
?>
<#
var getRating = function() {
var ratingScale = parseInt( settings.rating_scale, 10 ),
rating = settings.rating > ratingScale ? ratingScale : settings.rating;
return [ rating, ratingScale ];
},
ratingData = getRating(),
rating = ratingData[0],
textualRating = ratingData[0] + '/' + ratingData[1],
renderStars = function( icon ) {
var starsHtml = '',
flooredRating = Math.floor( rating );
for ( var stars = 1; stars <= ratingData[1]; stars++ ) {
if ( stars <= flooredRating ) {
starsHtml += '<i class="elementor-star-full">' + icon + '</i>';
} else if ( flooredRating + 1 === stars && rating !== flooredRating ) {
starsHtml += '<i class="elementor-star-' + ( rating - flooredRating ).toFixed( 1 ) * 10 + '">' + icon + '</i>';
} else {
starsHtml += '<i class="elementor-star-empty">' + icon + '</i>';
}
}
return starsHtml;
},
icon = '&#xE934;';
if ( 'star_fontawesome' === settings.star_style ) {
if ( 'outline' === settings.unmarked_star_style ) {
icon = '&#xE933;';
}
} else if ( 'star_unicode' === settings.star_style ) {
icon = '&#9733;';
if ( 'outline' === settings.unmarked_star_style ) {
icon = '&#9734;';
}
}
view.addRenderAttribute( 'iconWrapper', 'class', 'elementor-star-rating' );
view.addRenderAttribute( 'iconWrapper', 'itemtype', 'http://schema.org/Rating' );
view.addRenderAttribute( 'iconWrapper', 'title', textualRating );
view.addRenderAttribute( 'iconWrapper', 'itemscope', '' );
view.addRenderAttribute( 'iconWrapper', 'itemprop', 'reviewRating' );
var stars = renderStars( icon );
#>
<div class="elementor-star-rating__wrapper">
<# if ( ! _.isEmpty( settings.title ) ) { #>
<div class="elementor-star-rating__title">{{ settings.title }}</div>
<# } #>
<div {{{ view.getRenderAttributeString( 'iconWrapper' ) }}} >
{{{ stars }}}
<span itemprop="ratingValue" class="elementor-screen-only">{{ textualRating }}</span>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,611 @@
<?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 tabs widget.
*
* Elementor widget that displays vertical or horizontal tabs with different
* pieces of content.
*
* @since 1.0.0
*/
class Widget_Tabs extends Widget_Base {
/**
* Get widget name.
*
* Retrieve tabs widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'tabs';
}
/**
* Get widget title.
*
* Retrieve tabs widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Tabs', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve tabs widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-tabs';
}
/**
* 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 [ 'tabs', 'accordion', 'toggle' ];
}
protected function is_dynamic_content(): bool {
return false;
}
public function show_in_panel(): bool {
return ! Plugin::$instance->experiments->is_feature_active( 'nested-elements' );
}
/**
* Register tabs 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() {
$start = is_rtl() ? 'end' : 'start';
$end = is_rtl() ? 'start' : 'end';
$this->start_controls_section(
'section_tabs',
[
'label' => esc_html__( 'Tabs', 'elementor' ),
]
);
$repeater = new Repeater();
$repeater->add_control(
'tab_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'default' => esc_html__( 'Tab Title', 'elementor' ),
'placeholder' => esc_html__( 'Tab Title', 'elementor' ),
'label_block' => true,
'dynamic' => [
'active' => true,
],
]
);
$repeater->add_control(
'tab_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'default' => esc_html__( 'Tab Content', 'elementor' ),
'placeholder' => esc_html__( 'Tab Content', 'elementor' ),
'type' => Controls_Manager::WYSIWYG,
]
);
$is_nested_tabs_active = Plugin::$instance->widgets_manager->get_widget_types( 'nested-tabs' );
if ( $is_nested_tabs_active ) {
$this->add_deprecation_message(
'3.8.0',
esc_html__(
'You are currently editing a Tabs Widget in its old version. Any new tabs widget dragged into the canvas will be the new Tab widget, with the improved Nested capabilities.',
'elementor'
),
'nested-tabs'
);
}
$this->add_control(
'tabs',
[
'label' => esc_html__( 'Tabs Items', 'elementor' ),
'type' => Controls_Manager::REPEATER,
'fields' => $repeater->get_controls(),
'default' => [
[
'tab_title' => esc_html__( 'Tab #1', 'elementor' ),
'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
],
[
'tab_title' => esc_html__( 'Tab #2', 'elementor' ),
'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
],
],
'title_field' => '{{{ tab_title }}}',
]
);
$this->add_control(
'type',
[
'label' => esc_html__( 'Position', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'default' => 'horizontal',
'options' => [
'vertical' => [
'title' => esc_html__( 'Vertical', 'elementor' ),
'icon' => 'eicon-h-align-' . ( is_rtl() ? 'right' : 'left' ),
],
'horizontal' => [
'title' => esc_html__( 'Horizontal', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
],
'prefix_class' => 'elementor-tabs-view-',
'separator' => 'before',
]
);
$this->add_control(
'tabs_align_horizontal',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => "eicon-align-$start-h",
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-align-center-h',
],
'end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => "eicon-align-$end-h",
],
'stretch' => [
'title' => esc_html__( 'Stretch', 'elementor' ),
'icon' => 'eicon-align-stretch-h',
],
],
'prefix_class' => 'elementor-tabs-alignment-',
'condition' => [
'type' => 'horizontal',
],
]
);
$this->add_control(
'tabs_align_vertical',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => 'eicon-align-start-v',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-align-center-v',
],
'end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => 'eicon-align-end-v',
],
'stretch' => [
'title' => esc_html__( 'Stretch', 'elementor' ),
'icon' => 'eicon-align-stretch-v',
],
],
'prefix_class' => 'elementor-tabs-alignment-',
'condition' => [
'type' => 'vertical',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_tabs_style',
[
'label' => esc_html__( 'Tabs', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'navigation_width',
[
'label' => esc_html__( 'Navigation Width', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'default' => [
'unit' => '%',
],
'range' => [
'px' => [
'min' => 10,
'max' => 500,
],
'%' => [
'min' => 10,
'max' => 50,
],
'em' => [
'min' => 1,
'max' => 50,
],
'rem' => [
'min' => 1,
'max' => 50,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-tabs-wrapper' => 'width: {{SIZE}}{{UNIT}}',
],
'condition' => [
'type' => 'vertical',
],
]
);
$this->add_control(
'border_width',
[
'label' => esc_html__( 'Border Width', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'default' => [
'size' => 1,
],
'range' => [
'px' => [
'max' => 20,
],
'em' => [
'max' => 2,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-tab-title, {{WRAPPER}} .elementor-tab-title:before, {{WRAPPER}} .elementor-tab-title:after, {{WRAPPER}} .elementor-tab-content, {{WRAPPER}} .elementor-tabs-content-wrapper' => 'border-width: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_control(
'border_color',
[
'label' => esc_html__( 'Border Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-mobile-title, {{WRAPPER}} .elementor-tab-desktop-title.elementor-active, {{WRAPPER}} .elementor-tab-title:before, {{WRAPPER}} .elementor-tab-title:after, {{WRAPPER}} .elementor-tab-content, {{WRAPPER}} .elementor-tabs-content-wrapper' => 'border-color: {{VALUE}};',
],
]
);
$this->add_control(
'background_color',
[
'label' => esc_html__( 'Background Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-desktop-title.elementor-active' => 'background-color: {{VALUE}};',
'{{WRAPPER}} .elementor-tabs-content-wrapper' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'heading_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->add_control(
'tab_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title, {{WRAPPER}} .elementor-tab-title a' => 'color: {{VALUE}}',
],
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
]
);
$this->add_control(
'tab_active_color',
[
'label' => esc_html__( 'Active Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title.elementor-active,
{{WRAPPER}} .elementor-tab-title.elementor-active a' => 'color: {{VALUE}}',
],
'global' => [
'default' => Global_Colors::COLOR_ACCENT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'tab_typography',
'selector' => '{{WRAPPER}} .elementor-tab-title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Text_Stroke::get_type(),
[
'name' => 'text_stroke',
'selector' => '{{WRAPPER}} .elementor-tab-title',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-tab-title',
]
);
$this->add_control(
'title_align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
],
'selectors' => [
'{{WRAPPER}} .elementor-tab-title' => 'text-align: {{VALUE}};',
],
'condition' => [
'tabs_align' => 'stretch',
],
]
);
$this->add_control(
'heading_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->add_control(
'content_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-content' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'content_typography',
'selector' => '{{WRAPPER}} .elementor-tab-content',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'content_shadow',
'selector' => '{{WRAPPER}} .elementor-tab-content',
]
);
$this->end_controls_section();
}
/**
* Render tabs widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$tabs = $this->get_settings_for_display( 'tabs' );
$id_int = substr( $this->get_id_int(), 0, 3 );
$this->add_render_attribute( 'elementor-tabs', 'class', 'elementor-tabs' );
?>
<div <?php $this->print_render_attribute_string( 'elementor-tabs' ); ?>>
<div class="elementor-tabs-wrapper" role="tablist" >
<?php
foreach ( $tabs as $index => $item ) :
$tab_count = $index + 1;
$tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
$this->add_render_attribute( $tab_title_setting_key, [
'id' => 'elementor-tab-title-' . $id_int . $tab_count,
'class' => [ 'elementor-tab-title', 'elementor-tab-desktop-title' ],
'aria-selected' => 1 === $tab_count ? 'true' : 'false',
'data-tab' => $tab_count,
'role' => 'tab',
'tabindex' => 1 === $tab_count ? '0' : '-1',
'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
'aria-expanded' => 'false',
] );
?>
<div <?php $this->print_render_attribute_string( $tab_title_setting_key ); ?>><?php
// PHPCS - the main text of a widget should not be escaped.
echo $item['tab_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?></div>
<?php endforeach; ?>
</div>
<div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
<?php
foreach ( $tabs as $index => $item ) :
$tab_count = $index + 1;
$hidden = 1 === $tab_count ? 'false' : 'hidden';
$tab_content_setting_key = $this->get_repeater_setting_key( 'tab_content', 'tabs', $index );
$tab_title_mobile_setting_key = $this->get_repeater_setting_key( 'tab_title_mobile', 'tabs', $tab_count );
$this->add_render_attribute( $tab_content_setting_key, [
'id' => 'elementor-tab-content-' . $id_int . $tab_count,
'class' => [ 'elementor-tab-content', 'elementor-clearfix' ],
'data-tab' => $tab_count,
'role' => 'tabpanel',
'aria-labelledby' => 'elementor-tab-title-' . $id_int . $tab_count,
'tabindex' => '0',
'hidden' => $hidden,
] );
$this->add_render_attribute( $tab_title_mobile_setting_key, [
'class' => [ 'elementor-tab-title', 'elementor-tab-mobile-title' ],
'aria-selected' => 1 === $tab_count ? 'true' : 'false',
'data-tab' => $tab_count,
'role' => 'tab',
'tabindex' => 1 === $tab_count ? '0' : '-1',
'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
'aria-expanded' => 'false',
] );
$this->add_inline_editing_attributes( $tab_content_setting_key, 'advanced' );
?>
<div <?php $this->print_render_attribute_string( $tab_title_mobile_setting_key ); ?>><?php
$this->print_unescaped_setting( 'tab_title', 'tabs', $index );
?></div>
<div <?php $this->print_render_attribute_string( $tab_content_setting_key ); ?>><?php
$this->print_text_editor( $item['tab_content'] );
?></div>
<?php endforeach; ?>
</div>
</div>
<?php
}
/**
* Render tabs 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() {
?>
<div class="elementor-tabs" role="tablist" aria-orientation="vertical">
<# if ( settings.tabs ) {
var elementUid = view.getIDInt().toString().substr( 0, 3 ); #>
<div class="elementor-tabs-wrapper" role="tablist">
<# _.each( settings.tabs, function( item, index ) {
var tabCount = index + 1,
tabUid = elementUid + tabCount,
tabTitleKey = 'tab-title-' + tabUid;
view.addRenderAttribute( tabTitleKey, {
'id': 'elementor-tab-title-' + tabUid,
'class': [ 'elementor-tab-title','elementor-tab-desktop-title' ],
'data-tab': tabCount,
'role': 'tab',
'tabindex': 1 === tabCount ? '0' : '-1',
'aria-controls': 'elementor-tab-content-' + tabUid,
'aria-expanded': 'false',
} );
#>
<div {{{ view.getRenderAttributeString( tabTitleKey ) }}}>{{{ item.tab_title }}}</div>
<# } ); #>
</div>
<div class="elementor-tabs-content-wrapper">
<# _.each( settings.tabs, function( item, index ) {
var tabCount = index + 1,
tabContentKey = view.getRepeaterSettingKey( 'tab_content', 'tabs',index );
view.addRenderAttribute( tabContentKey, {
'id': 'elementor-tab-content-' + elementUid + tabCount,
'class': [ 'elementor-tab-content', 'elementor-clearfix', 'elementor-repeater-item-' + item._id ],
'data-tab': tabCount,
'role' : 'tabpanel',
'aria-labelledby' : 'elementor-tab-title-' + elementUid + tabCount
} );
view.addInlineEditingAttributes( tabContentKey, 'advanced' ); #>
<div class="elementor-tab-title elementor-tab-mobile-title" data-tab="{{ tabCount }}" role="tab">{{{ item.tab_title }}}</div>
<div {{{ view.getRenderAttributeString( tabContentKey ) }}}>{{{ item.tab_content }}}</div>
<# } ); #>
</div>
<# } #>
</div>
<?php
}
}

View File

@@ -0,0 +1,639 @@
<?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 testimonial widget.
*
* Elementor widget that displays customer testimonials that show social proof.
*
* @since 1.0.0
*/
class Widget_Testimonial extends Widget_Base {
/**
* Get widget name.
*
* Retrieve testimonial widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'testimonial';
}
/**
* Get widget title.
*
* Retrieve testimonial widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Testimonial', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve testimonial widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-testimonial';
}
/**
* 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 [ 'testimonial', 'blockquote' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Get widget upsale data.
*
* Retrieve the widget promotion data.
*
* @since 3.18.0
* @access protected
*
* @return array Widget promotion data.
*/
protected function get_upsale_data() {
return [
'condition' => ! Utils::has_pro(),
'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ),
'image_alt' => esc_attr__( 'Upgrade', 'elementor' ),
'description' => esc_html__( 'Use interesting masonry layouts and other overlay features with Elementor\'s Pro Gallery widget.', 'elementor' ),
'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-testimonial-widget/' ),
'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ),
];
}
/**
* Register testimonial 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_testimonial',
[
'label' => esc_html__( 'Testimonial', 'elementor' ),
]
);
$this->add_control(
'testimonial_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'type' => Controls_Manager::TEXTAREA,
'dynamic' => [
'active' => true,
],
'rows' => '10',
'default' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
]
);
$this->add_control(
'testimonial_image',
[
'label' => esc_html__( 'Choose Image', 'elementor' ),
'type' => Controls_Manager::MEDIA,
'dynamic' => [
'active' => true,
],
'default' => [
'url' => Utils::get_placeholder_image_src(),
],
]
);
$this->add_group_control(
Group_Control_Image_Size::get_type(),
[
'name' => 'testimonial_image', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `testimonial_image_size` and `testimonial_image_custom_dimension`.
'default' => 'full',
]
);
$this->add_control(
'testimonial_name',
[
'label' => esc_html__( 'Name', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'ai' => [
'active' => false,
],
'default' => esc_html__( 'John Doe', 'elementor' ),
]
);
$this->add_control(
'testimonial_job',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'ai' => [
'active' => false,
],
'default' => esc_html__( 'Designer', 'elementor' ),
]
);
$this->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'dynamic' => [
'active' => true,
],
]
);
$aside = is_rtl() ? 'right' : 'left';
$this->add_control(
'testimonial_image_position',
[
'label' => esc_html__( 'Image Position', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'default' => 'aside',
'options' => [
'aside' => [
'title' => esc_html__( 'Aside', 'elementor' ),
'icon' => 'eicon-h-align-' . $aside,
],
'top' => [
'title' => esc_html__( 'Top', 'elementor' ),
'icon' => 'eicon-v-align-top',
],
],
'toggle' => false,
'condition' => [
'testimonial_image[url]!' => '',
],
'separator' => 'before',
'style_transfer' => true,
]
);
$this->add_responsive_control(
'testimonial_alignment',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'default' => 'center',
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
],
'selectors' => [
'{{WRAPPER}} .elementor-testimonial-wrapper' => 'text-align: {{VALUE}}',
],
'style_transfer' => true,
]
);
$this->end_controls_section();
// Content.
$this->start_controls_section(
'section_style_testimonial_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'content_content_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-testimonial-content' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'content_typography',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
'selector' => '{{WRAPPER}} .elementor-testimonial-content',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'content_shadow',
'selector' => '{{WRAPPER}} .elementor-testimonial-content',
]
);
$this->end_controls_section();
// Image.
$this->start_controls_section(
'section_style_testimonial_image',
[
'label' => esc_html__( 'Image', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'testimonial_image[url]!' => '',
],
]
);
$this->add_responsive_control(
'image_size',
[
'label' => esc_html__( 'Image Resolution', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'min' => 20,
'max' => 200,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-testimonial-wrapper .elementor-testimonial-image img' => 'width: {{SIZE}}{{UNIT}};height: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_group_control(
Group_Control_Border::get_type(),
[
'name' => 'image_border',
'selector' => '{{WRAPPER}} .elementor-testimonial-wrapper .elementor-testimonial-image img',
'separator' => 'before',
]
);
$this->add_responsive_control(
'image_border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-testimonial-wrapper .elementor-testimonial-image img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
// Name.
$this->start_controls_section(
'section_style_testimonial_name',
[
'label' => esc_html__( 'Name', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'name_text_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-testimonial-name' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'name_typography',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
'selector' => '{{WRAPPER}} .elementor-testimonial-name',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'name_shadow',
'selector' => '{{WRAPPER}} .elementor-testimonial-name',
]
);
$this->end_controls_section();
// Job.
$this->start_controls_section(
'section_style_testimonial_job',
[
'label' => esc_html__( 'Title', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'job_text_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_SECONDARY,
],
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-testimonial-job' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'job_typography',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_SECONDARY,
],
'selector' => '{{WRAPPER}} .elementor-testimonial-job',
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'job_shadow',
'selector' => '{{WRAPPER}} .elementor-testimonial-job',
]
);
$this->end_controls_section();
}
/**
* Render testimonial 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();
$has_content = ! empty( $settings['testimonial_content'] );
$has_image = ! empty( $settings['testimonial_image']['url'] );
$has_name = ! empty( $settings['testimonial_name'] );
$has_job = ! empty( $settings['testimonial_job'] );
if ( ! $has_content && ! $has_image && ! $has_name && ! $has_job ) {
return;
}
$this->add_render_attribute( 'wrapper', 'class', 'elementor-testimonial-wrapper' );
$this->add_render_attribute( 'meta', 'class', 'elementor-testimonial-meta' );
if ( $settings['testimonial_image']['url'] ) {
$this->add_render_attribute( 'meta', 'class', 'elementor-has-image' );
}
if ( $settings['testimonial_image_position'] ) {
$this->add_render_attribute( 'meta', 'class', 'elementor-testimonial-image-position-' . $settings['testimonial_image_position'] );
}
if ( ! empty( $settings['link']['url'] ) ) {
$this->add_link_attributes( 'link', $settings['link'] );
}
?>
<div <?php $this->print_render_attribute_string( 'wrapper' ); ?>>
<?php
if ( $has_content ) :
$this->add_render_attribute( 'testimonial_content', 'class', 'elementor-testimonial-content' );
$this->add_inline_editing_attributes( 'testimonial_content' );
?>
<div <?php $this->print_render_attribute_string( 'testimonial_content' ); ?>><?php $this->print_unescaped_setting( 'testimonial_content' ); ?></div>
<?php endif; ?>
<?php if ( $has_image || $has_name || $has_job ) : ?>
<div <?php $this->print_render_attribute_string( 'meta' ); ?>>
<div class="elementor-testimonial-meta-inner">
<?php if ( $has_image ) : ?>
<div class="elementor-testimonial-image">
<?php
$image_html = Group_Control_Image_Size::get_attachment_image_html( $settings, 'testimonial_image' );
if ( ! empty( $settings['link']['url'] ) ) :
$image_html = '<a ' . $this->get_render_attribute_string( 'link' ) . '>' . $image_html . '</a>';
endif;
echo wp_kses_post( $image_html );
?>
</div>
<?php endif; ?>
<?php if ( $has_name || $has_job ) : ?>
<div class="elementor-testimonial-details">
<?php
if ( $has_name ) :
$this->add_render_attribute( 'testimonial_name', 'class', 'elementor-testimonial-name' );
$this->add_inline_editing_attributes( 'testimonial_name', 'none' );
if ( ! empty( $settings['link']['url'] ) ) :
?>
<a <?php $this->print_render_attribute_string( 'testimonial_name' ); ?> <?php $this->print_render_attribute_string( 'link' ); ?>><?php $this->print_unescaped_setting( 'testimonial_name' ); ?></a>
<?php
else :
?>
<div <?php $this->print_render_attribute_string( 'testimonial_name' ); ?>><?php $this->print_unescaped_setting( 'testimonial_name' ); ?></div>
<?php
endif;
endif; ?>
<?php
if ( $has_job ) :
$this->add_render_attribute( 'testimonial_job', 'class', 'elementor-testimonial-job' );
$this->add_inline_editing_attributes( 'testimonial_job', 'none' );
if ( ! empty( $settings['link']['url'] ) ) :
?>
<a <?php $this->print_render_attribute_string( 'testimonial_job' ); ?> <?php $this->print_render_attribute_string( 'link' ); ?>><?php $this->print_unescaped_setting( 'testimonial_job' ); ?></a>
<?php
else :
?>
<div <?php $this->print_render_attribute_string( 'testimonial_job' ); ?>><?php $this->print_unescaped_setting( 'testimonial_job' ); ?></div>
<?php
endif;
endif; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>
<?php
}
/**
* Render testimonial 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() {
?>
<#
if ( '' === settings.testimonial_content && '' === settings.testimonial_image.url && '' === settings.testimonial_name && '' === settings.testimonial_job ) {
return;
}
var image = {
id: settings.testimonial_image.id,
url: settings.testimonial_image.url,
size: settings.testimonial_image_size,
dimension: settings.testimonial_image_custom_dimension,
model: view.getEditModel()
};
var imageUrl = false, hasImage = '';
if ( '' !== settings.testimonial_image.url ) {
imageUrl = elementor.imagesManager.getImageUrl( image );
hasImage = ' elementor-has-image';
var imageHtml = '<img src="' + _.escape( imageUrl ) + '" alt="testimonial" />';
if ( settings.link.url ) {
imageHtml = '<a href="' + elementor.helpers.sanitizeUrl( settings.link.url ) + '">' + imageHtml + '</a>';
}
}
var testimonial_image_position = settings.testimonial_image_position ? ' elementor-testimonial-image-position-' + settings.testimonial_image_position : '';
#>
<div class="elementor-testimonial-wrapper">
<# if ( '' !== settings.testimonial_content ) {
view.addRenderAttribute( 'testimonial_content', {
'data-binding-type': 'content',
'data-binding-setting': 'testimonial_content',
} );
view.addRenderAttribute( 'testimonial_content', 'class', 'elementor-testimonial-content' );
view.addInlineEditingAttributes( 'testimonial_content' );
#>
<div {{{ view.getRenderAttributeString( 'testimonial_content' ) }}}>{{{ settings.testimonial_content }}}</div>
<# } #>
<div class="elementor-testimonial-meta{{ hasImage }}{{ testimonial_image_position }}">
<div class="elementor-testimonial-meta-inner">
<# if ( imageUrl ) { #>
<div class="elementor-testimonial-image">{{{ imageHtml }}}</div>
<# } #>
<div class="elementor-testimonial-details">
<?php $this->render_testimonial_description(); ?>
</div>
</div>
</div>
</div>
<?php
}
protected function render_testimonial_description() {
?>
<#
if ( '' !== settings.testimonial_name ) {
view.addRenderAttribute( 'testimonial_name', 'class', 'elementor-testimonial-name' );
view.addInlineEditingAttributes( 'testimonial_name', 'none' );
if ( settings.link.url ) {
#>
<a href="{{ settings.link.url }}" {{{ view.getRenderAttributeString( 'testimonial_name' ) }}}>{{{ settings.testimonial_name }}}</a>
<#
} else {
#>
<div {{{ view.getRenderAttributeString( 'testimonial_name' ) }}}>{{{ settings.testimonial_name }}}</div>
<#
}
}
if ( '' !== settings.testimonial_job ) {
view.addRenderAttribute( 'testimonial_job', 'class', 'elementor-testimonial-job' );
view.addInlineEditingAttributes( 'testimonial_job', 'none' );
if ( settings.link.url ) {
#>
<a href="{{ settings.link.url }}" {{{ view.getRenderAttributeString( 'testimonial_job' ) }}}>{{{ settings.testimonial_job }}}</a>
<#
} else {
#>
<div {{{ view.getRenderAttributeString( 'testimonial_job' ) }}}>{{{ settings.testimonial_job }}}</div>
<#
}
}
#>
<?php
}
}

View File

@@ -0,0 +1,531 @@
<?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 text editor widget.
*
* Elementor widget that displays a WYSIWYG text editor, just like the WordPress
* editor.
*
* @since 1.0.0
*/
class Widget_Text_Editor extends Widget_Base {
/**
* Get widget name.
*
* Retrieve text editor widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'text-editor';
}
/**
* Get widget title.
*
* Retrieve text editor widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Text Editor', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve text editor widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-text';
}
/**
* Get widget categories.
*
* Retrieve the list of categories the text editor widget belongs to.
*
* Used to determine where to display the widget in the editor.
*
* @since 2.0.0
* @access public
*
* @return array Widget categories.
*/
public function get_categories() {
return [ 'basic' ];
}
/**
* 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 [ 'text', 'editor' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Register text editor 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_editor',
[
'label' => esc_html__( 'Text Editor', 'elementor' ),
]
);
$this->add_control(
'editor',
[
'label' => '',
'type' => Controls_Manager::WYSIWYG,
'default' => '<p>' . esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ) . '</p>',
]
);
$this->add_control(
'drop_cap', [
'label' => esc_html__( 'Drop Cap', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => esc_html__( 'Off', 'elementor' ),
'label_on' => esc_html__( 'On', 'elementor' ),
'prefix_class' => 'elementor-drop-cap-',
'frontend_available' => true,
]
);
$this->add_responsive_control(
'text_columns',
[
'label' => esc_html__( 'Columns', 'elementor' ),
'type' => Controls_Manager::SELECT,
'separator' => 'before',
'options' => [
'' => esc_html__( 'Default', 'elementor' ),
'1' => esc_html__( '1', 'elementor' ),
'2' => esc_html__( '2', 'elementor' ),
'3' => esc_html__( '3', 'elementor' ),
'4' => esc_html__( '4', 'elementor' ),
'5' => esc_html__( '5', 'elementor' ),
'6' => esc_html__( '6', 'elementor' ),
'7' => esc_html__( '7', 'elementor' ),
'8' => esc_html__( '8', 'elementor' ),
'9' => esc_html__( '9', 'elementor' ),
'10' => esc_html__( '10', 'elementor' ),
],
'selectors' => [
'{{WRAPPER}}' => 'columns: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'column_gap',
[
'label' => esc_html__( 'Columns Gap', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'%' => [
'max' => 10,
'step' => 0.1,
],
'vw' => [
'max' => 10,
'step' => 0.1,
],
'em' => [
'max' => 10,
],
'rem' => [
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}}' => 'column-gap: {{SIZE}}{{UNIT}};',
],
'conditions' => [
'relation' => 'or',
'terms' => [
[
'name' => 'text_columns',
'operator' => '>',
'value' => 1,
],
[
'name' => 'text_columns',
'operator' => '===',
'value' => '',
],
],
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style',
[
'label' => esc_html__( 'Text Editor', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_responsive_control(
'align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
'title' => esc_html__( 'Justified', 'elementor' ),
'icon' => 'eicon-text-align-justify',
],
],
'selectors' => [
'{{WRAPPER}}' => 'text-align: {{VALUE}};',
],
]
);
$this->add_control(
'text_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}}' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'text_shadow',
'selector' => '{{WRAPPER}}',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_drop_cap',
[
'label' => esc_html__( 'Drop Cap', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'drop_cap' => 'yes',
],
]
);
$this->add_control(
'drop_cap_view',
[
'label' => esc_html__( 'View', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'default' => esc_html__( 'Default', 'elementor' ),
'stacked' => esc_html__( 'Stacked', 'elementor' ),
'framed' => esc_html__( 'Framed', 'elementor' ),
],
'default' => 'default',
'prefix_class' => 'elementor-drop-cap-view-',
]
);
$this->add_control(
'drop_cap_primary_color',
[
'label' => esc_html__( 'Primary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}}.elementor-drop-cap-view-stacked .elementor-drop-cap' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-drop-cap-view-framed .elementor-drop-cap, {{WRAPPER}}.elementor-drop-cap-view-default .elementor-drop-cap' => 'color: {{VALUE}}; border-color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
]
);
$this->add_control(
'drop_cap_secondary_color',
[
'label' => esc_html__( 'Secondary Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}}.elementor-drop-cap-view-framed .elementor-drop-cap' => 'background-color: {{VALUE}};',
'{{WRAPPER}}.elementor-drop-cap-view-stacked .elementor-drop-cap' => 'color: {{VALUE}};',
],
'condition' => [
'drop_cap_view!' => 'default',
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'drop_cap_shadow',
'selector' => '{{WRAPPER}} .elementor-drop-cap',
]
);
$this->add_control(
'drop_cap_size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'default' => [
'size' => 5,
],
'range' => [
'px' => [
'max' => 30,
],
'em' => [
'max' => 3,
],
'rem' => [
'max' => 3,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-drop-cap' => 'padding: {{SIZE}}{{UNIT}};',
],
'condition' => [
'drop_cap_view!' => 'default',
],
]
);
$this->add_control(
'drop_cap_space',
[
'label' => esc_html__( 'Space', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'default' => [
'size' => 10,
],
'range' => [
'px' => [
'max' => 50,
],
'em' => [
'max' => 5,
],
'rem' => [
'max' => 5,
],
],
'selectors' => [
'body:not(.rtl) {{WRAPPER}} .elementor-drop-cap' => 'margin-right: {{SIZE}}{{UNIT}};',
'body.rtl {{WRAPPER}} .elementor-drop-cap' => 'margin-left: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_control(
'drop_cap_border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'default' => [
'unit' => '%',
],
'range' => [
'%' => [
'max' => 50,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-drop-cap' => 'border-radius: {{SIZE}}{{UNIT}};',
],
'condition' => [
'drop_cap_view!' => 'default',
],
]
);
$this->add_control(
'drop_cap_border_width', [
'label' => esc_html__( 'Border Width', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-drop-cap' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
'condition' => [
'drop_cap_view' => 'framed',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'drop_cap_typography',
'selector' => '{{WRAPPER}} .elementor-drop-cap-letter',
'exclude' => [
'letter_spacing',
],
]
);
$this->end_controls_section();
}
/**
* Render text editor widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$should_render_inline_editing = Plugin::$instance->editor->is_edit_mode();
$editor_content = $this->get_settings_for_display( 'editor' );
$editor_content = $this->parse_text_editor( $editor_content );
if ( empty( $editor_content ) ) {
return;
}
if ( $should_render_inline_editing ) {
$this->add_render_attribute( 'editor', 'class', [ 'elementor-text-editor', 'elementor-clearfix' ] );
}
$this->add_inline_editing_attributes( 'editor', 'advanced' );
?>
<?php if ( $should_render_inline_editing ) { ?>
<div <?php $this->print_render_attribute_string( 'editor' ); ?>>
<?php } ?>
<?php // PHPCS - the main text of a widget should not be escaped.
echo $editor_content; // phpcs:ignore WordPress.Security.EscapeOutput ?>
<?php if ( $should_render_inline_editing ) { ?>
</div>
<?php } ?>
<?php
}
/**
* Render text editor widget as plain content.
*
* Override the default behavior by printing the content without rendering it.
*
* @since 1.0.0
* @access public
*/
public function render_plain_content() {
// In plain mode, render without shortcode
$this->print_unescaped_setting( 'editor' );
}
/**
* Render text editor 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() {
?>
<#
if ( '' === settings.editor ) {
return;
}
const shouldRenderInlineEditing = elementorFrontend.isEditMode();
if ( shouldRenderInlineEditing ) {
view.addRenderAttribute( 'editor', 'class', [ 'elementor-text-editor', 'elementor-clearfix' ] );
}
view.addInlineEditingAttributes( 'editor', 'advanced' );
if ( shouldRenderInlineEditing ) { #>
<div {{{ view.getRenderAttributeString( 'editor' ) }}}>
<# } #>
{{{ settings.editor }}}
<# if ( shouldRenderInlineEditing ) { #>
</div>
<# } #>
<?php
}
}

View File

@@ -0,0 +1,725 @@
<?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 toggle widget.
*
* Elementor widget that displays a collapsible display of content in an toggle
* style, allowing the user to open multiple items.
*
* @since 1.0.0
*/
class Widget_Toggle extends Widget_Base {
/**
* Get widget name.
*
* Retrieve toggle widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'toggle';
}
/**
* Get widget title.
*
* Retrieve toggle widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return esc_html__( 'Toggle', 'elementor' );
}
/**
* Get widget icon.
*
* Retrieve toggle widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function get_icon() {
return 'eicon-toggle';
}
/**
* 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 [ 'tabs', 'accordion', 'toggle' ];
}
protected function is_dynamic_content(): bool {
return false;
}
/**
* Hide widget from panel.
*
* Hide the toggle widget from the panel if nested-accordion experiment is active.
*
* @since 3.15.0
* @return bool
*/
public function show_in_panel(): bool {
return ! Plugin::$instance->experiments->is_feature_active( 'nested-elements' );
}
/**
* Register toggle 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_toggle',
[
'label' => esc_html__( 'Toggle', 'elementor' ),
]
);
$repeater = new Repeater();
$repeater->add_control(
'tab_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'default' => esc_html__( 'Toggle Title', 'elementor' ),
'label_block' => true,
'dynamic' => [
'active' => true,
],
]
);
$repeater->add_control(
'tab_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'type' => Controls_Manager::WYSIWYG,
'default' => esc_html__( 'Toggle Content', 'elementor' ),
'dynamic' => [
'active' => true,
],
]
);
if ( Plugin::$instance->widgets_manager->get_widget_types( 'nested-accordion' ) ) {
$this->add_deprecation_message(
'3.15.0',
esc_html__(
'You are currently editing a Toggle widget in its old version. Drag a new Accordion widget onto your page to use a newer version, providing nested capabilities.',
'elementor'
),
'nested-accordion'
);
}
$this->add_control(
'tabs',
[
'label' => esc_html__( 'Toggle Items', 'elementor' ),
'type' => Controls_Manager::REPEATER,
'fields' => $repeater->get_controls(),
'default' => [
[
'tab_title' => esc_html__( 'Toggle #1', 'elementor' ),
'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
],
[
'tab_title' => esc_html__( 'Toggle #2', 'elementor' ),
'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
],
],
'title_field' => '{{{ tab_title }}}',
]
);
$this->add_control(
'selected_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'separator' => 'before',
'fa4compatibility' => 'icon',
'default' => [
'value' => 'fas fa-caret' . ( is_rtl() ? '-left' : '-right' ),
'library' => 'fa-solid',
],
'recommended' => [
'fa-solid' => [
'chevron-down',
'angle-down',
'angle-double-down',
'caret-down',
'caret-square-down',
],
'fa-regular' => [
'caret-square-down',
],
],
'label_block' => false,
'skin' => 'inline',
]
);
$this->add_control(
'selected_active_icon',
[
'label' => esc_html__( 'Active Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'fa4compatibility' => 'icon_active',
'default' => [
'value' => 'fas fa-caret-up',
'library' => 'fa-solid',
],
'recommended' => [
'fa-solid' => [
'chevron-up',
'angle-up',
'angle-double-up',
'caret-up',
'caret-square-up',
],
'fa-regular' => [
'caret-square-up',
],
],
'skin' => 'inline',
'label_block' => false,
'condition' => [
'selected_icon[value]!' => '',
],
]
);
$this->add_control(
'title_html_tag',
[
'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'div',
],
'default' => 'div',
'separator' => 'before',
]
);
$this->add_control(
'faq_schema',
[
'label' => esc_html__( 'FAQ Schema', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'separator' => 'before',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_toggle_style',
[
'label' => esc_html__( 'Toggle', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'border_width',
[
'label' => esc_html__( 'Border Width', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'range' => [
'px' => [
'max' => 20,
],
'em' => [
'max' => 2,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-tab-title' => 'border-width: {{SIZE}}{{UNIT}};',
'{{WRAPPER}} .elementor-tab-content' => 'border-width: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_control(
'border_color',
[
'label' => esc_html__( 'Border Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-content' => 'border-bottom-color: {{VALUE}};',
'{{WRAPPER}} .elementor-tab-title' => 'border-color: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'space_between',
[
'label' => esc_html__( 'Space Between', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'max' => 10,
],
'rem' => [
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-toggle-item:not(:last-child)' => 'margin-bottom: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_group_control(
Group_Control_Box_Shadow::get_type(),
[
'name' => 'box_shadow',
'selector' => '{{WRAPPER}} .elementor-toggle-item',
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_toggle_style_title',
[
'label' => esc_html__( 'Title', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'title_background',
[
'label' => esc_html__( 'Background', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title' => 'background-color: {{VALUE}};',
],
]
);
// The title selector specificity is to override Theme Style
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-toggle-title, {{WRAPPER}} .elementor-toggle-icon' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-toggle-icon svg' => 'fill: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
]
);
$this->add_control(
'tab_active_color',
[
'label' => esc_html__( 'Active Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title.elementor-active a, {{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_ACCENT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'title_typography',
'selector' => '{{WRAPPER}} .elementor-toggle-title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'title_shadow',
'selector' => '{{WRAPPER}} .elementor-toggle-title',
]
);
$this->add_responsive_control(
'title_padding',
[
'label' => esc_html__( 'Padding', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-tab-title' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_toggle_style_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'selected_icon[value]!' => '',
],
]
);
$this->add_control(
'icon_align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => 'eicon-h-align-left',
],
'right' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => 'eicon-h-align-right',
],
],
'default' => is_rtl() ? 'right' : 'left',
'toggle' => false,
]
);
$this->add_control(
'icon_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title .elementor-toggle-icon i:before' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-tab-title .elementor-toggle-icon svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_control(
'icon_active_color',
[
'label' => esc_html__( 'Active Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon i:before' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon svg' => 'fill: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'icon_space',
[
'label' => esc_html__( 'Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 100,
],
'em' => [
'max' => 10,
],
'rem' => [
'max' => 10,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-toggle-icon.elementor-toggle-icon-left' => 'margin-right: {{SIZE}}{{UNIT}};',
'{{WRAPPER}} .elementor-toggle-icon.elementor-toggle-icon-right' => 'margin-left: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_toggle_style_content',
[
'label' => esc_html__( 'Content', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'content_background_color',
[
'label' => esc_html__( 'Background', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-content' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'content_color',
[
'label' => esc_html__( 'Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-tab-content' => 'color: {{VALUE}};',
],
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'content_typography',
'selector' => '{{WRAPPER}} .elementor-tab-content',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_TEXT,
],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'content_shadow',
'selector' => '{{WRAPPER}} .elementor-tab-content',
]
);
$this->add_responsive_control(
'content_padding',
[
'label' => esc_html__( 'Padding', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-tab-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
}
/**
* Render toggle 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();
$id_int = substr( $this->get_id_int(), 0, 3 );
$migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
if ( ! isset( $settings['icon'] ) && ! Icons_Manager::is_migration_allowed() ) {
// @todo: remove when deprecated
// added as bc in 2.6
// add old default
$settings['icon'] = 'fa fa-caret' . ( is_rtl() ? '-left' : '-right' );
$settings['icon_active'] = 'fa fa-caret-up';
$settings['icon_align'] = $this->get_settings( 'icon_align' );
}
$is_new = empty( $settings['icon'] ) && Icons_Manager::is_migration_allowed();
$has_icon = ( ! $is_new || ! empty( $settings['selected_icon']['value'] ) );
?>
<div class="elementor-toggle">
<?php
foreach ( $settings['tabs'] as $index => $item ) :
$tab_count = $index + 1;
$tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
$tab_content_setting_key = $this->get_repeater_setting_key( 'tab_content', 'tabs', $index );
$this->add_render_attribute( $tab_title_setting_key, [
'id' => 'elementor-tab-title-' . $id_int . $tab_count,
'class' => [ 'elementor-tab-title' ],
'data-tab' => $tab_count,
'role' => 'button',
'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
'aria-expanded' => 'false',
] );
$this->add_render_attribute( $tab_content_setting_key, [
'id' => 'elementor-tab-content-' . $id_int . $tab_count,
'class' => [ 'elementor-tab-content', 'elementor-clearfix' ],
'data-tab' => $tab_count,
'role' => 'region',
'aria-labelledby' => 'elementor-tab-title-' . $id_int . $tab_count,
] );
$this->add_inline_editing_attributes( $tab_content_setting_key, 'advanced' );
?>
<div class="elementor-toggle-item">
<<?php Utils::print_validated_html_tag( $settings['title_html_tag'] ); ?> <?php $this->print_render_attribute_string( $tab_title_setting_key ); ?>>
<?php if ( $has_icon ) : ?>
<span class="elementor-toggle-icon elementor-toggle-icon-<?php echo esc_attr( $settings['icon_align'] ); ?>" aria-hidden="true">
<?php
if ( $is_new || $migrated ) { ?>
<span class="elementor-toggle-icon-closed"><?php Icons_Manager::render_icon( $settings['selected_icon'] ); ?></span>
<span class="elementor-toggle-icon-opened"><?php Icons_Manager::render_icon( $settings['selected_active_icon'], [ 'class' => 'elementor-toggle-icon-opened' ] ); ?></span>
<?php } else { ?>
<i class="elementor-toggle-icon-closed <?php echo esc_attr( $settings['icon'] ); ?>"></i>
<i class="elementor-toggle-icon-opened <?php echo esc_attr( $settings['icon_active'] ); ?>"></i>
<?php } ?>
</span>
<?php endif; ?>
<a class="elementor-toggle-title" tabindex="0"><?php $this->print_unescaped_setting( 'tab_title', 'tabs', $index ); ?></a>
</<?php Utils::print_validated_html_tag( $settings['title_html_tag'] ); ?>>
<div <?php $this->print_render_attribute_string( $tab_content_setting_key ); ?>><?php Utils::print_unescaped_internal_string( $this->parse_text_editor( $item['tab_content'] ) ); ?></div>
</div>
<?php endforeach; ?>
<?php
if ( isset( $settings['faq_schema'] ) && 'yes' === $settings['faq_schema'] ) {
$json = [
'@context' => 'https://schema.org',
'@type' => 'FAQPage',
'mainEntity' => [],
];
foreach ( $settings['tabs'] as $index => $item ) {
$json['mainEntity'][] = [
'@type' => 'Question',
'name' => wp_strip_all_tags( $item['tab_title'] ),
'acceptedAnswer' => [
'@type' => 'Answer',
'text' => $this->parse_text_editor( $item['tab_content'] ),
],
];
}
?>
<script type="application/ld+json"><?php echo wp_json_encode( $json ); ?></script>
<?php } ?>
</div>
<?php
}
/**
* Render toggle 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() {
?>
<div class="elementor-toggle">
<#
if ( settings.tabs ) {
var tabindex = view.getIDInt().toString().substr( 0, 3 ),
iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, {}, 'i' , 'object' ),
iconActiveHTML = elementor.helpers.renderIcon( view, settings.selected_active_icon, {}, 'i' , 'object' ),
migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' ),
titleHTMLTag = elementor.helpers.validateHTMLTag( settings.title_html_tag );
_.each( settings.tabs, function( item, index ) {
var tabCount = index + 1,
tabTitleKey = view.getRepeaterSettingKey( 'tab_title', 'tabs', index ),
tabContentKey = view.getRepeaterSettingKey( 'tab_content', 'tabs', index );
view.addRenderAttribute( tabTitleKey, {
'id': 'elementor-tab-title-' + tabindex + tabCount,
'class': [ 'elementor-tab-title' ],
'data-tab': tabCount,
'role': 'button',
'aria-controls': 'elementor-tab-content-' + tabindex + tabCount,
'aria-expanded': 'false',
} );
view.addRenderAttribute( tabContentKey, {
'id': 'elementor-tab-content-' + tabindex + tabCount,
'class': [ 'elementor-tab-content', 'elementor-clearfix' ],
'data-tab': tabCount,
'role': 'region',
'aria-labelledby': 'elementor-tab-title-' + tabindex + tabCount
} );
view.addInlineEditingAttributes( tabContentKey, 'advanced' );
#>
<div class="elementor-toggle-item">
<{{{ titleHTMLTag }}} {{{ view.getRenderAttributeString( tabTitleKey ) }}}>
<# if ( settings.icon || settings.selected_icon ) { #>
<span class="elementor-toggle-icon elementor-toggle-icon-{{ settings.icon_align }}" aria-hidden="true">
<# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
<span class="elementor-toggle-icon-closed">{{{ iconHTML.value }}}</span>
<span class="elementor-toggle-icon-opened">{{{ iconActiveHTML.value }}}</span>
<# } else { #>
<i class="elementor-toggle-icon-closed {{ settings.icon }}"></i>
<i class="elementor-toggle-icon-opened {{ settings.icon_active }}"></i>
<# } #>
</span>
<# } #>
<a class="elementor-toggle-title" tabindex="0">{{{ item.tab_title }}}</a>
</{{{ titleHTMLTag }}}>
<div {{{ view.getRenderAttributeString( tabContentKey ) }}}>{{{ item.tab_content }}}</div>
</div>
<#
} );
} #>
</div>
<?php
}
}

View File

@@ -0,0 +1,681 @@
<?php
namespace Elementor\Includes\Widgets\Traits;
use Elementor\Controls_Manager;
use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
use Elementor\Group_Control_Background;
use Elementor\Group_Control_Border;
use Elementor\Group_Control_Box_Shadow;
use Elementor\Group_Control_Text_Shadow;
use Elementor\Group_Control_Typography;
use Elementor\Icons_Manager;
use Elementor\Widget_Base;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
trait Button_Trait {
/**
* Get button sizes.
*
* Retrieve an array of button sizes for the button widget.
*
* @since 3.4.0
* @access public
* @static
*
* @return array An array containing button sizes.
*/
public static function get_button_sizes() {
return [
'xs' => esc_html__( 'Extra Small', 'elementor' ),
'sm' => esc_html__( 'Small', 'elementor' ),
'md' => esc_html__( 'Medium', 'elementor' ),
'lg' => esc_html__( 'Large', 'elementor' ),
'xl' => esc_html__( 'Extra Large', 'elementor' ),
];
}
/**
* @since 3.4.0
*
* @param array $args {
* An array of values for the button adjustments.
*
* @type array $section_condition Set of conditions to hide the controls.
* @type string $button_text Text contained in button.
* @type string $text_control_label Name for the label of the text control.
* @type array $icon_exclude_inline_options Set of icon types to exclude from icon controls.
* }
*/
protected function register_button_content_controls( $args = [] ) {
$default_args = [
'section_condition' => [],
'button_default_text' => esc_html__( 'Click here', 'elementor' ),
'text_control_label' => esc_html__( 'Text', 'elementor' ),
'icon_exclude_inline_options' => [],
];
$args = wp_parse_args( $args, $default_args );
$this->add_control(
'button_type',
[
'label' => esc_html__( 'Type', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => '',
'options' => [
'' => esc_html__( 'Default', 'elementor' ),
'info' => esc_html__( 'Info', 'elementor' ),
'success' => esc_html__( 'Success', 'elementor' ),
'warning' => esc_html__( 'Warning', 'elementor' ),
'danger' => esc_html__( 'Danger', 'elementor' ),
],
'prefix_class' => 'elementor-button-',
'condition' => $args['section_condition'],
]
);
$this->add_control(
'text',
[
'label' => $args['text_control_label'],
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'default' => $args['button_default_text'],
'placeholder' => $args['button_default_text'],
'condition' => $args['section_condition'],
]
);
$this->add_control(
'link',
[
'label' => esc_html__( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'dynamic' => [
'active' => true,
],
'default' => [
'url' => '#',
],
'condition' => $args['section_condition'],
]
);
$this->add_control(
'size',
[
'label' => esc_html__( 'Size', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'sm',
'options' => self::get_button_sizes(),
'style_transfer' => true,
'condition' => array_merge( $args['section_condition'], [ 'size[value]!' => 'sm' ] ), // a workaround to hide the control, unless it's in use (not default).
]
);
$this->add_control(
'selected_icon',
[
'label' => esc_html__( 'Icon', 'elementor' ),
'type' => Controls_Manager::ICONS,
'fa4compatibility' => 'icon',
'skin' => 'inline',
'label_block' => false,
'condition' => $args['section_condition'],
'icon_exclude_inline_options' => $args['icon_exclude_inline_options'],
]
);
$start = is_rtl() ? 'right' : 'left';
$end = is_rtl() ? 'left' : 'right';
$this->add_control(
'icon_align',
[
'label' => esc_html__( 'Icon Position', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'default' => is_rtl() ? 'row-reverse' : 'row',
'options' => [
'row' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => "eicon-h-align-{$start}",
],
'row-reverse' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => "eicon-h-align-{$end}",
],
],
'selectors_dictionary' => [
'left' => is_rtl() ? 'row-reverse' : 'row',
'right' => is_rtl() ? 'row' : 'row-reverse',
],
'selectors' => [
'{{WRAPPER}} .elementor-button-content-wrapper' => 'flex-direction: {{VALUE}};',
],
'condition' => array_merge(
$args['section_condition'],
[
'text!' => '',
'selected_icon[value]!' => '',
]
),
]
);
$this->add_control(
'icon_indent',
[
'label' => esc_html__( 'Icon Spacing', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 'px', 'em', 'rem', 'custom' ],
'range' => [
'px' => [
'max' => 50,
],
'em' => [
'max' => 5,
],
'rem' => [
'max' => 5,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-button .elementor-button-content-wrapper' => 'gap: {{SIZE}}{{UNIT}};',
],
'condition' => array_merge(
$args['section_condition'],
[
'text!' => '',
'selected_icon[value]!' => '',
]
),
]
);
$this->add_control(
'button_css_id',
[
'label' => esc_html__( 'Button ID', 'elementor' ),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'ai' => [
'active' => false,
],
'default' => '',
'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
'description' => sprintf(
esc_html__( 'Please make sure the ID is unique and not used elsewhere on the page this form is displayed. This field allows %1$sA-z 0-9%2$s & underscore chars without spaces.', 'elementor' ),
'<code>',
'</code>'
),
'separator' => 'before',
'condition' => $args['section_condition'],
]
);
}
/**
* @since 3.4.0
*
* @param array $args {
* An array of values for the button adjustments.
*
* @type array $section_condition Set of conditions to hide the controls.
* @type string $alignment_default Default position for the button.
* @type string $alignment_control_prefix_class Prefix class name for the button position control.
* @type string $content_alignment_default Default alignment for the button content.
* }
*/
protected function register_button_style_controls( $args = [] ) {
$default_args = [
'section_condition' => [],
'alignment_default' => '',
'alignment_control_prefix_class' => 'elementor%s-align-',
'content_alignment_default' => '',
];
$args = wp_parse_args( $args, $default_args );
$this->add_responsive_control(
'align',
[
'label' => esc_html__( 'Position', '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',
],
'justify' => [
'title' => esc_html__( 'Stretch', 'elementor' ),
'icon' => 'eicon-h-align-stretch',
],
],
'prefix_class' => $args['alignment_control_prefix_class'],
'default' => $args['alignment_default'],
'condition' => $args['section_condition'],
]
);
$start = is_rtl() ? 'right' : 'left';
$end = is_rtl() ? 'left' : 'right';
$this->add_responsive_control(
'content_align',
[
'label' => esc_html__( 'Alignment', 'elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'start' => [
'title' => esc_html__( 'Start', 'elementor' ),
'icon' => "eicon-text-align-{$start}",
],
'center' => [
'title' => esc_html__( 'Center', 'elementor' ),
'icon' => 'eicon-text-align-center',
],
'end' => [
'title' => esc_html__( 'End', 'elementor' ),
'icon' => "eicon-text-align-{$end}",
],
'space-between' => [
'title' => esc_html__( 'Space between', 'elementor' ),
'icon' => 'eicon-text-align-justify',
],
],
'default' => $args['content_alignment_default'],
'selectors' => [
'{{WRAPPER}} .elementor-button .elementor-button-content-wrapper' => 'justify-content: {{VALUE}};',
],
'condition' => array_merge( $args['section_condition'], [ 'align' => 'justify' ] ),
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_ACCENT,
],
'selector' => '{{WRAPPER}} .elementor-button',
'condition' => $args['section_condition'],
]
);
$this->add_group_control(
Group_Control_Text_Shadow::get_type(),
[
'name' => 'text_shadow',
'selector' => '{{WRAPPER}} .elementor-button',
'condition' => $args['section_condition'],
]
);
$this->start_controls_tabs( 'tabs_button_style', [
'condition' => $args['section_condition'],
] );
$this->start_controls_tab(
'tab_button_normal',
[
'label' => esc_html__( 'Normal', 'elementor' ),
'condition' => $args['section_condition'],
]
);
$this->add_control(
'button_text_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'default' => '',
'selectors' => [
'{{WRAPPER}} .elementor-button' => 'fill: {{VALUE}}; color: {{VALUE}};',
],
'condition' => $args['section_condition'],
]
);
$this->add_group_control(
Group_Control_Background::get_type(),
[
'name' => 'background',
'types' => [ 'classic', 'gradient' ],
'exclude' => [ 'image' ],
'selector' => '{{WRAPPER}} .elementor-button',
'fields_options' => [
'background' => [
'default' => 'classic',
],
'color' => [
'global' => [
'default' => Global_Colors::COLOR_ACCENT,
],
],
],
'condition' => $args['section_condition'],
]
);
$this->end_controls_tab();
$this->start_controls_tab(
'tab_button_hover',
[
'label' => esc_html__( 'Hover', 'elementor' ),
'condition' => $args['section_condition'],
]
);
$this->add_control(
'hover_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-button:hover, {{WRAPPER}} .elementor-button:focus' => 'color: {{VALUE}};',
'{{WRAPPER}} .elementor-button:hover svg, {{WRAPPER}} .elementor-button:focus svg' => 'fill: {{VALUE}};',
],
'condition' => $args['section_condition'],
]
);
$this->add_group_control(
Group_Control_Background::get_type(),
[
'name' => 'button_background_hover',
'types' => [ 'classic', 'gradient' ],
'exclude' => [ 'image' ],
'selector' => '{{WRAPPER}} .elementor-button:hover, {{WRAPPER}} .elementor-button:focus',
'fields_options' => [
'background' => [
'default' => 'classic',
],
],
'condition' => $args['section_condition'],
]
);
$this->add_control(
'button_hover_border_color',
[
'label' => esc_html__( 'Border Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'condition' => [
'border_border!' => '',
],
'selectors' => [
'{{WRAPPER}} .elementor-button:hover, {{WRAPPER}} .elementor-button:focus' => 'border-color: {{VALUE}};',
],
'condition' => $args['section_condition'],
]
);
$this->add_control(
'button_hover_transition_duration',
[
'label' => esc_html__( 'Transition Duration', 'elementor' ),
'type' => Controls_Manager::SLIDER,
'size_units' => [ 's', 'ms', 'custom' ],
'default' => [
'unit' => 's',
],
'selectors' => [
'{{WRAPPER}} .elementor-button' => 'transition-duration: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_control(
'hover_animation',
[
'label' => esc_html__( 'Hover Animation', 'elementor' ),
'type' => Controls_Manager::HOVER_ANIMATION,
'condition' => $args['section_condition'],
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_group_control(
Group_Control_Border::get_type(),
[
'name' => 'border',
'selector' => '{{WRAPPER}} .elementor-button',
'separator' => 'before',
'condition' => $args['section_condition'],
]
);
$this->add_responsive_control(
'border_radius',
[
'label' => esc_html__( 'Border Radius', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
'condition' => $args['section_condition'],
]
);
$this->add_group_control(
Group_Control_Box_Shadow::get_type(),
[
'name' => 'button_box_shadow',
'selector' => '{{WRAPPER}} .elementor-button',
'condition' => $args['section_condition'],
]
);
$this->add_responsive_control(
'text_padding',
[
'label' => esc_html__( 'Padding', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .elementor-button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
'separator' => 'before',
'condition' => $args['section_condition'],
]
);
}
/**
* Render button widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @param \Elementor\Widget_Base|null $instance
*
* @since 3.4.0
* @access protected
*/
protected function render_button( Widget_Base $instance = null ) {
if ( empty( $instance ) ) {
$instance = $this;
}
$settings = $instance->get_settings_for_display();
if ( empty( $settings['text'] ) && empty( $settings['selected_icon']['value'] ) ) {
return;
}
$instance->add_render_attribute( 'wrapper', 'class', 'elementor-button-wrapper' );
$instance->add_render_attribute( 'button', 'class', 'elementor-button' );
if ( ! empty( $settings['link']['url'] ) ) {
$instance->add_link_attributes( 'button', $settings['link'] );
$instance->add_render_attribute( 'button', 'class', 'elementor-button-link' );
} else {
$instance->add_render_attribute( 'button', 'role', 'button' );
}
if ( ! empty( $settings['button_css_id'] ) ) {
$instance->add_render_attribute( 'button', 'id', $settings['button_css_id'] );
}
if ( ! empty( $settings['size'] ) ) {
$instance->add_render_attribute( 'button', 'class', 'elementor-size-' . $settings['size'] );
} else {
$instance->add_render_attribute( 'button', 'class', 'elementor-size-sm' ); // BC, to make sure the class is always present
}
if ( ! empty( $settings['hover_animation'] ) ) {
$instance->add_render_attribute( 'button', 'class', 'elementor-animation-' . $settings['hover_animation'] );
}
?>
<div <?php $instance->print_render_attribute_string( 'wrapper' ); ?>>
<a <?php $instance->print_render_attribute_string( 'button' ); ?>>
<?php $this->render_text( $instance ); ?>
</a>
</div>
<?php
}
/**
* Render button widget output in the editor.
*
* Written as a Backbone JavaScript template and used to generate the live preview.
*
* @since 3.4.0
* @access protected
*/
protected function content_template() {
?>
<#
if ( '' === settings.text && '' === settings.selected_icon.value ) {
return;
}
view.addRenderAttribute( 'wrapper', 'class', 'elementor-button-wrapper' );
view.addRenderAttribute( 'button', 'class', 'elementor-button' );
if ( '' !== settings.link.url ) {
view.addRenderAttribute( 'button', 'href', elementor.helpers.sanitizeUrl( settings.link.url ) );
view.addRenderAttribute( 'button', 'class', 'elementor-button-link' );
} else {
view.addRenderAttribute( 'button', 'role', 'button' );
}
if ( '' !== settings.button_css_id ) {
view.addRenderAttribute( 'button', 'id', settings.button_css_id );
}
if ( '' !== settings.size ) {
view.addRenderAttribute( 'button', 'class', 'elementor-size-' + settings.size );
}
if ( '' !== settings.hover_animation ) {
view.addRenderAttribute( 'button', 'class', 'elementor-animation-' + settings.hover_animation );
}
view.addRenderAttribute( 'icon', 'class', 'elementor-button-icon' );
view.addRenderAttribute( 'text', 'class', 'elementor-button-text' );
view.addInlineEditingAttributes( 'text', 'none' );
var iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, { 'aria-hidden': true }, 'i' , 'object' ),
migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' );
#>
<div {{{ view.getRenderAttributeString( 'wrapper' ) }}}>
<a {{{ view.getRenderAttributeString( 'button' ) }}}>
<span class="elementor-button-content-wrapper">
<# if ( settings.icon || settings.selected_icon ) { #>
<span {{{ view.getRenderAttributeString( 'icon' ) }}}>
<# if ( ( migrated || ! settings.icon ) && iconHTML.rendered ) { #>
{{{ iconHTML.value }}}
<# } else { #>
<i class="{{ settings.icon }}" aria-hidden="true"></i>
<# } #>
</span>
<# } #>
<# if ( settings.text ) { #>
<span {{{ view.getRenderAttributeString( 'text' ) }}}>{{{ settings.text }}}</span>
<# } #>
</span>
</a>
</div>
<?php
}
/**
* Render button text.
*
* Render button widget text.
*
* @param \Elementor\Widget_Base|null $instance
*
* @since 3.4.0
* @access protected
*/
protected function render_text( Widget_Base $instance = null ) {
// The default instance should be `$this` (a Button widget), unless the Trait is being used from outside of a widget (e.g. `Skin_Base`) which should pass an `$instance`.
if ( empty( $instance ) ) {
$instance = $this;
}
$settings = $instance->get_settings_for_display();
$migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
$is_new = empty( $settings['icon'] ) && Icons_Manager::is_migration_allowed();
$instance->add_render_attribute( [
'content-wrapper' => [
'class' => 'elementor-button-content-wrapper',
],
'icon' => [
'class' => 'elementor-button-icon',
],
'text' => [
'class' => 'elementor-button-text',
],
] );
// TODO: replace the protected with public
//$instance->add_inline_editing_attributes( 'text', 'none' );
?>
<span <?php $instance->print_render_attribute_string( 'content-wrapper' ); ?>>
<?php if ( ! empty( $settings['icon'] ) || ! empty( $settings['selected_icon']['value'] ) ) : ?>
<span <?php $instance->print_render_attribute_string( 'icon' ); ?>>
<?php if ( $is_new || $migrated ) :
Icons_Manager::render_icon( $settings['selected_icon'], [ 'aria-hidden' => 'true' ] );
else : ?>
<i class="<?php echo esc_attr( $settings['icon'] ); ?>" aria-hidden="true"></i>
<?php endif; ?>
</span>
<?php endif; ?>
<?php if ( ! empty( $settings['text'] ) ) : ?>
<span <?php $instance->print_render_attribute_string( 'text' ); ?>><?php $this->print_unescaped_setting( 'text' ); ?></span>
<?php endif; ?>
</span>
<?php
}
public function on_import( $element ) {
return Icons_Manager::on_import_migration( $element, 'icon', 'selected_icon' );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,301 @@
<?php
namespace Elementor;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Elementor WordPress widget.
*
* Elementor widget that displays all the WordPress widgets.
*
* @since 1.0.0
*/
class Widget_WordPress extends Widget_Base {
/**
* WordPress widget name.
*
* @access private
*
* @var string
*/
private $_widget_name = null;
/**
* WordPress widget instance.
*
* @access private
*
* @var \WP_Widget
*/
private $_widget_instance = null;
public function hide_on_search() {
return true;
}
/**
* Get widget name.
*
* Retrieve WordPress widget name.
*
* @since 1.0.0
* @access public
*
* @return string Widget name.
*/
public function get_name() {
return 'wp-widget-' . $this->get_widget_instance()->id_base;
}
/**
* Get widget title.
*
* Retrieve WordPress widget title.
*
* @since 1.0.0
* @access public
*
* @return string Widget title.
*/
public function get_title() {
return $this->get_widget_instance()->name;
}
/**
* Get widget categories.
*
* Retrieve the list of categories the WordPress widget belongs to.
*
* Used to determine where to display the widget in the editor.
*
* @since 1.0.0
* @access public
*
* @return array Widget categories. Returns either a WordPress category.
*/
public function get_categories() {
return [ 'wordpress' ];
}
/**
* Get widget icon.
*
* Retrieve WordPress widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon. Returns either a WordPress icon.
*/
public function get_icon() {
return 'eicon-wordpress';
}
/**
* 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 [ 'wordpress', 'widget' ];
}
public function get_help_url() {
return '';
}
/**
* Whether the reload preview is required or not.
*
* Used to determine whether the reload preview is required.
*
* @since 1.0.0
* @access public
*
* @return bool Whether the reload preview is required.
*/
public function is_reload_preview_required() {
return true;
}
/**
* Retrieve WordPress widget form.
*
* Returns the WordPress widget form, to be used in Elementor.
*
* @since 1.0.0
* @access public
*
* @return string Widget form.
*/
public function get_form() {
$instance = $this->get_widget_instance();
ob_start();
echo '<div class="widget-inside media-widget-control"><div class="form wp-core-ui">';
echo '<input type="hidden" class="id_base" value="' . esc_attr( $instance->id_base ) . '" />';
echo '<input type="hidden" class="widget-id" value="widget-' . esc_attr( $this->get_id() ) . '" />';
echo '<div class="widget-content">';
$widget_data = $this->get_settings( 'wp' );
$instance->form( $widget_data );
do_action( 'in_widget_form', $instance, null, $widget_data );
echo '</div></div></div>';
return ob_get_clean();
}
/**
* Retrieve WordPress widget instance.
*
* Returns an instance of WordPress widget, to be used in Elementor.
*
* @since 1.0.0
* @access public
*
* @return \WP_Widget
*/
public function get_widget_instance() {
if ( is_null( $this->_widget_instance ) ) {
global $wp_widget_factory;
if ( isset( $wp_widget_factory->widgets[ $this->_widget_name ] ) ) {
$this->_widget_instance = $wp_widget_factory->widgets[ $this->_widget_name ];
$this->_widget_instance->_set( 'REPLACE_TO_ID' );
} elseif ( class_exists( $this->_widget_name ) ) {
$this->_widget_instance = new $this->_widget_name();
$this->_widget_instance->_set( 'REPLACE_TO_ID' );
}
}
return $this->_widget_instance;
}
/**
* Retrieve WordPress widget parsed settings.
*
* Returns the WordPress widget settings, to be used in Elementor.
*
* @access protected
* @since 2.3.0
*
* @return array Parsed settings.
*/
protected function get_init_settings() {
$settings = parent::get_init_settings();
if ( ! empty( $settings['wp'] ) ) {
$widget = $this->get_widget_instance();
$instance = $widget->update( $settings['wp'], [] );
/** This filter is documented in wp-includes/class-wp-widget.php */
$settings['wp'] = apply_filters( 'widget_update_callback', $instance, $settings['wp'], [], $widget );
}
return $settings;
}
/**
* Register WordPress 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->add_control(
'wp',
[
'label' => esc_html__( 'Form', 'elementor' ),
'type' => Controls_Manager::WP_WIDGET,
'widget' => $this->get_name(),
'id_base' => $this->get_widget_instance()->id_base,
]
);
}
/**
* Render WordPress widget output on the frontend.
*
* Written in PHP and used to generate the final HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$default_widget_args = [
'widget_id' => $this->get_name(),
'before_widget' => '',
'after_widget' => '',
'before_title' => '<h5>',
'after_title' => '</h5>',
];
/**
* WordPress widget args.
*
* Filters the WordPress widget arguments when they are rendered in Elementor panel.
*
* @since 1.0.0
*
* @param array $default_widget_args Default widget arguments.
* @param Widget_WordPress $this The WordPress widget.
*/
$default_widget_args = apply_filters( 'elementor/widgets/wordpress/widget_args', $default_widget_args, $this );
$is_gallery_widget = 'wp-widget-media_gallery' === $this->get_name();
if ( $is_gallery_widget ) {
add_filter( 'wp_get_attachment_link', [ $this, 'add_lightbox_data_to_image_link' ], 10, 2 );
}
$this->get_widget_instance()->widget( $default_widget_args, $this->get_settings( 'wp' ) );
if ( $is_gallery_widget ) {
remove_filter( 'wp_get_attachment_link', [ $this, 'add_lightbox_data_to_image_link' ] );
}
}
/**
* Render WordPress 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() {}
/**
* WordPress widget constructor.
*
* Used to run WordPress widget constructor.
*
* @since 1.0.0
* @access public
*
* @param array $data Widget data. Default is an empty array.
* @param array $args Widget arguments. Default is null.
*/
public function __construct( $data = [], $args = null ) {
$this->_widget_name = $args['widget_name'];
parent::__construct( $data, $args );
}
/**
* Render WordPress widget as plain content.
*
* Override the default render behavior, don't render widget content.
*
* @since 1.0.0
* @access public
*
* @param array $instance Widget instance. Default is empty array.
*/
public function render_plain_content( $instance = [] ) {}
}