PluginProbe
Elementor Website Builder – more than just a page builder / 3.2.5
Elementor Website Builder – more than just a page builder v3.2.5
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / includes / widgets / toggle.php

toggle.php in Elementor Website Builder – more than just a page builder 3.2.5, at includes/widgets/toggle.php

692 lines 18.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit; // Exit if accessed directly.
6 }
7
8 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
9 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
10
11 /**
12 * Elementor toggle widget.
13 *
14 * Elementor widget that displays a collapsible display of content in an toggle
15 * style, allowing the user to open multiple items.
16 *
17 * @since 1.0.0
18 */
19 class Widget_Toggle extends Widget_Base {
20
21 /**
22 * Get widget name.
23 *
24 * Retrieve toggle widget name.
25 *
26 * @since 1.0.0
27 * @access public
28 *
29 * @return string Widget name.
30 */
31 public function get_name() {
32 return 'toggle';
33 }
34
35 /**
36 * Get widget title.
37 *
38 * Retrieve toggle widget title.
39 *
40 * @since 1.0.0
41 * @access public
42 *
43 * @return string Widget title.
44 */
45 public function get_title() {
46 return __( 'Toggle', 'elementor' );
47 }
48
49 /**
50 * Get widget icon.
51 *
52 * Retrieve toggle widget icon.
53 *
54 * @since 1.0.0
55 * @access public
56 *
57 * @return string Widget icon.
58 */
59 public function get_icon() {
60 return 'eicon-toggle';
61 }
62
63 /**
64 * Get widget keywords.
65 *
66 * Retrieve the list of keywords the widget belongs to.
67 *
68 * @since 2.1.0
69 * @access public
70 *
71 * @return array Widget keywords.
72 */
73 public function get_keywords() {
74 return [ 'tabs', 'accordion', 'toggle' ];
75 }
76
77 /**
78 * Register toggle widget controls.
79 *
80 * Adds different input fields to allow the user to change and customize the widget settings.
81 *
82 * @since 3.1.0
83 * @access protected
84 */
85 protected function register_controls() {
86 $this->start_controls_section(
87 'section_toggle',
88 [
89 'label' => __( 'Toggle', 'elementor' ),
90 ]
91 );
92
93 $repeater = new Repeater();
94
95 $repeater->add_control(
96 'tab_title',
97 [
98 'label' => __( 'Title & Description', 'elementor' ),
99 'type' => Controls_Manager::TEXT,
100 'default' => __( 'Toggle Title', 'elementor' ),
101 'label_block' => true,
102 'dynamic' => [
103 'active' => true,
104 ],
105 ]
106 );
107
108 $repeater->add_control(
109 'tab_content',
110 [
111 'label' => __( 'Content', 'elementor' ),
112 'type' => Controls_Manager::WYSIWYG,
113 'default' => __( 'Toggle Content', 'elementor' ),
114 'show_label' => false,
115 'dynamic' => [
116 'active' => true,
117 ],
118 ]
119 );
120
121 $this->add_control(
122 'tabs',
123 [
124 'label' => __( 'Toggle Items', 'elementor' ),
125 'type' => Controls_Manager::REPEATER,
126 'fields' => $repeater->get_controls(),
127 'default' => [
128 [
129 'tab_title' => __( 'Toggle #1', 'elementor' ),
130 'tab_content' => __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
131 ],
132 [
133 'tab_title' => __( 'Toggle #2', 'elementor' ),
134 'tab_content' => __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
135 ],
136 ],
137 'title_field' => '{{{ tab_title }}}',
138 ]
139 );
140
141 $this->add_control(
142 'view',
143 [
144 'label' => __( 'View', 'elementor' ),
145 'type' => Controls_Manager::HIDDEN,
146 'default' => 'traditional',
147 ]
148 );
149
150 $this->add_control(
151 'selected_icon',
152 [
153 'label' => __( 'Icon', 'elementor' ),
154 'type' => Controls_Manager::ICONS,
155 'separator' => 'before',
156 'fa4compatibility' => 'icon',
157 'default' => [
158 'value' => 'fas fa-caret' . ( is_rtl() ? '-left' : '-right' ),
159 'library' => 'fa-solid',
160 ],
161 'recommended' => [
162 'fa-solid' => [
163 'chevron-down',
164 'angle-down',
165 'angle-double-down',
166 'caret-down',
167 'caret-square-down',
168 ],
169 'fa-regular' => [
170 'caret-square-down',
171 ],
172 ],
173 'label_block' => false,
174 'skin' => 'inline',
175 ]
176 );
177
178 $this->add_control(
179 'selected_active_icon',
180 [
181 'label' => __( 'Active Icon', 'elementor' ),
182 'type' => Controls_Manager::ICONS,
183 'fa4compatibility' => 'icon_active',
184 'default' => [
185 'value' => 'fas fa-caret-up',
186 'library' => 'fa-solid',
187 ],
188 'recommended' => [
189 'fa-solid' => [
190 'chevron-up',
191 'angle-up',
192 'angle-double-up',
193 'caret-up',
194 'caret-square-up',
195 ],
196 'fa-regular' => [
197 'caret-square-up',
198 ],
199 ],
200 'skin' => 'inline',
201 'label_block' => false,
202 'condition' => [
203 'selected_icon[value]!' => '',
204 ],
205 ]
206 );
207
208 $this->add_control(
209 'title_html_tag',
210 [
211 'label' => __( 'Title HTML Tag', 'elementor' ),
212 'type' => Controls_Manager::SELECT,
213 'options' => [
214 'h1' => 'H1',
215 'h2' => 'H2',
216 'h3' => 'H3',
217 'h4' => 'H4',
218 'h5' => 'H5',
219 'h6' => 'H6',
220 'div' => 'div',
221 ],
222 'default' => 'div',
223 'separator' => 'before',
224 ]
225 );
226
227 $this->add_control(
228 'faq_schema',
229 [
230 'label' => __( 'FAQ Schema', 'elementor' ),
231 'type' => Controls_Manager::SWITCHER,
232 'separator' => 'before',
233 ]
234 );
235
236 $this->end_controls_section();
237
238 $this->start_controls_section(
239 'section_toggle_style',
240 [
241 'label' => __( 'Toggle', 'elementor' ),
242 'tab' => Controls_Manager::TAB_STYLE,
243 ]
244 );
245
246 $this->add_control(
247 'border_width',
248 [
249 'label' => __( 'Border Width', 'elementor' ),
250 'type' => Controls_Manager::SLIDER,
251 'range' => [
252 'px' => [
253 'min' => 0,
254 'max' => 10,
255 ],
256 ],
257 'selectors' => [
258 '{{WRAPPER}} .elementor-tab-title' => 'border-width: {{SIZE}}{{UNIT}};',
259 '{{WRAPPER}} .elementor-tab-content' => 'border-width: {{SIZE}}{{UNIT}};',
260 ],
261 ]
262 );
263
264 $this->add_control(
265 'border_color',
266 [
267 'label' => __( 'Border Color', 'elementor' ),
268 'type' => Controls_Manager::COLOR,
269 'selectors' => [
270 '{{WRAPPER}} .elementor-tab-content' => 'border-bottom-color: {{VALUE}};',
271 '{{WRAPPER}} .elementor-tab-title' => 'border-color: {{VALUE}};',
272 ],
273 ]
274 );
275
276 $this->add_responsive_control(
277 'space_between',
278 [
279 'label' => __( 'Space Between', 'elementor' ),
280 'type' => Controls_Manager::SLIDER,
281 'range' => [
282 'px' => [
283 'min' => 0,
284 'max' => 100,
285 ],
286 ],
287 'selectors' => [
288 '{{WRAPPER}} .elementor-toggle-item:not(:last-child)' => 'margin-bottom: {{SIZE}}{{UNIT}}',
289 ],
290 ]
291 );
292
293 $this->add_group_control(
294 Group_Control_Box_Shadow::get_type(),
295 [
296 'name' => 'box_shadow',
297 'selector' => '{{WRAPPER}} .elementor-toggle-item',
298 ]
299 );
300
301 $this->end_controls_section();
302
303 $this->start_controls_section(
304 'section_toggle_style_title',
305 [
306 'label' => __( 'Title', 'elementor' ),
307 'tab' => Controls_Manager::TAB_STYLE,
308 ]
309 );
310
311 $this->add_control(
312 'title_background',
313 [
314 'label' => __( 'Background', 'elementor' ),
315 'type' => Controls_Manager::COLOR,
316 'selectors' => [
317 '{{WRAPPER}} .elementor-tab-title' => 'background-color: {{VALUE}};',
318 ],
319 ]
320 );
321
322 // The title selector specificity is to override Theme Style
323 $this->add_control(
324 'title_color',
325 [
326 'label' => __( 'Color', 'elementor' ),
327 'type' => Controls_Manager::COLOR,
328 'selectors' => [
329 '{{WRAPPER}} .elementor-toggle-title, {{WRAPPER}} .elementor-toggle-icon' => 'color: {{VALUE}};',
330 ],
331 'global' => [
332 'default' => Global_Colors::COLOR_PRIMARY,
333 ],
334 ]
335 );
336
337 $this->add_control(
338 'tab_active_color',
339 [
340 'label' => __( 'Active Color', 'elementor' ),
341 'type' => Controls_Manager::COLOR,
342 'selectors' => [
343 '{{WRAPPER}} .elementor-tab-title.elementor-active a, {{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon' => 'color: {{VALUE}};',
344 ],
345 'global' => [
346 'default' => Global_Colors::COLOR_ACCENT,
347 ],
348 ]
349 );
350
351 $this->add_group_control(
352 Group_Control_Typography::get_type(),
353 [
354 'name' => 'title_typography',
355 'selector' => '{{WRAPPER}} .elementor-toggle-title',
356 'global' => [
357 'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
358 ],
359 ]
360 );
361
362 $this->add_group_control(
363 Group_Control_Text_Shadow::get_type(),
364 [
365 'name' => 'title_shadow',
366 'selector' => '{{WRAPPER}} .elementor-toggle-title',
367 ]
368 );
369
370 $this->add_responsive_control(
371 'title_padding',
372 [
373 'label' => __( 'Padding', 'elementor' ),
374 'type' => Controls_Manager::DIMENSIONS,
375 'size_units' => [ 'px', 'em', '%' ],
376 'selectors' => [
377 '{{WRAPPER}} .elementor-tab-title' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
378 ],
379 ]
380 );
381
382 $this->end_controls_section();
383
384 $this->start_controls_section(
385 'section_toggle_style_icon',
386 [
387 'label' => __( 'Icon', 'elementor' ),
388 'tab' => Controls_Manager::TAB_STYLE,
389 'condition' => [
390 'selected_icon[value]!' => '',
391 ],
392 ]
393 );
394
395 $this->add_control(
396 'icon_align',
397 [
398 'label' => __( 'Alignment', 'elementor' ),
399 'type' => Controls_Manager::CHOOSE,
400 'options' => [
401 'left' => [
402 'title' => __( 'Start', 'elementor' ),
403 'icon' => 'eicon-h-align-left',
404 ],
405 'right' => [
406 'title' => __( 'End', 'elementor' ),
407 'icon' => 'eicon-h-align-right',
408 ],
409 ],
410 'default' => is_rtl() ? 'right' : 'left',
411 'toggle' => false,
412 ]
413 );
414
415 $this->add_control(
416 'icon_color',
417 [
418 'label' => __( 'Color', 'elementor' ),
419 'type' => Controls_Manager::COLOR,
420 'selectors' => [
421 '{{WRAPPER}} .elementor-tab-title .elementor-toggle-icon i:before' => 'color: {{VALUE}};',
422 '{{WRAPPER}} .elementor-tab-title .elementor-toggle-icon svg' => 'fill: {{VALUE}};',
423 ],
424 ]
425 );
426
427 $this->add_control(
428 'icon_active_color',
429 [
430 'label' => __( 'Active Color', 'elementor' ),
431 'type' => Controls_Manager::COLOR,
432 'selectors' => [
433 '{{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon i:before' => 'color: {{VALUE}};',
434 '{{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon svg' => 'fill: {{VALUE}};',
435 ],
436 ]
437 );
438
439 $this->add_responsive_control(
440 'icon_space',
441 [
442 'label' => __( 'Spacing', 'elementor' ),
443 'type' => Controls_Manager::SLIDER,
444 'range' => [
445 'px' => [
446 'min' => 0,
447 'max' => 100,
448 ],
449 ],
450 'selectors' => [
451 '{{WRAPPER}} .elementor-toggle-icon.elementor-toggle-icon-left' => 'margin-right: {{SIZE}}{{UNIT}};',
452 '{{WRAPPER}} .elementor-toggle-icon.elementor-toggle-icon-right' => 'margin-left: {{SIZE}}{{UNIT}};',
453 ],
454 ]
455 );
456
457 $this->end_controls_section();
458
459 $this->start_controls_section(
460 'section_toggle_style_content',
461 [
462 'label' => __( 'Content', 'elementor' ),
463 'tab' => Controls_Manager::TAB_STYLE,
464 ]
465 );
466
467 $this->add_control(
468 'content_background_color',
469 [
470 'label' => __( 'Background', 'elementor' ),
471 'type' => Controls_Manager::COLOR,
472 'selectors' => [
473 '{{WRAPPER}} .elementor-tab-content' => 'background-color: {{VALUE}};',
474 ],
475 ]
476 );
477
478 $this->add_control(
479 'content_color',
480 [
481 'label' => __( 'Color', 'elementor' ),
482 'type' => Controls_Manager::COLOR,
483 'selectors' => [
484 '{{WRAPPER}} .elementor-tab-content' => 'color: {{VALUE}};',
485 ],
486 'global' => [
487 'default' => Global_Colors::COLOR_TEXT,
488 ],
489 ]
490 );
491
492 $this->add_group_control(
493 Group_Control_Typography::get_type(),
494 [
495 'name' => 'content_typography',
496 'selector' => '{{WRAPPER}} .elementor-tab-content',
497 'global' => [
498 'default' => Global_Typography::TYPOGRAPHY_TEXT,
499 ],
500 ]
501 );
502
503 $this->add_group_control(
504 Group_Control_Text_Shadow::get_type(),
505 [
506 'name' => 'content_shadow',
507 'selector' => '{{WRAPPER}} .elementor-tab-content',
508 ]
509 );
510
511 $this->add_responsive_control(
512 'content_padding',
513 [
514 'label' => __( 'Padding', 'elementor' ),
515 'type' => Controls_Manager::DIMENSIONS,
516 'size_units' => [ 'px', 'em', '%' ],
517 'selectors' => [
518 '{{WRAPPER}} .elementor-tab-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
519 ],
520 ]
521 );
522
523 $this->end_controls_section();
524 }
525
526 /**
527 * Render toggle widget output on the frontend.
528 *
529 * Written in PHP and used to generate the final HTML.
530 *
531 * @since 1.0.0
532 * @access protected
533 */
534 protected function render() {
535 $settings = $this->get_settings_for_display();
536
537 $id_int = substr( $this->get_id_int(), 0, 3 );
538 $migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
539
540 if ( ! isset( $settings['icon'] ) && ! Icons_Manager::is_migration_allowed() ) {
541 // @todo: remove when deprecated
542 // added as bc in 2.6
543 // add old default
544 $settings['icon'] = 'fa fa-caret' . ( is_rtl() ? '-left' : '-right' );
545 $settings['icon_active'] = 'fa fa-caret-up';
546 $settings['icon_align'] = $this->get_settings( 'icon_align' );
547 }
548
549 $is_new = empty( $settings['icon'] ) && Icons_Manager::is_migration_allowed();
550 $has_icon = ( ! $is_new || ! empty( $settings['selected_icon']['value'] ) );
551
552 ?>
553 <div class="elementor-toggle" role="tablist">
554 <?php
555 foreach ( $settings['tabs'] as $index => $item ) :
556 $tab_count = $index + 1;
557
558 $tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
559
560 $tab_content_setting_key = $this->get_repeater_setting_key( 'tab_content', 'tabs', $index );
561
562 $this->add_render_attribute( $tab_title_setting_key, [
563 'id' => 'elementor-tab-title-' . $id_int . $tab_count,
564 'class' => [ 'elementor-tab-title' ],
565 'data-tab' => $tab_count,
566 'role' => 'tab',
567 'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
568 'aria-expanded' => 'false',
569 ] );
570
571 $this->add_render_attribute( $tab_content_setting_key, [
572 'id' => 'elementor-tab-content-' . $id_int . $tab_count,
573 'class' => [ 'elementor-tab-content', 'elementor-clearfix' ],
574 'data-tab' => $tab_count,
575 'role' => 'tabpanel',
576 'aria-labelledby' => 'elementor-tab-title-' . $id_int . $tab_count,
577 ] );
578
579 $this->add_inline_editing_attributes( $tab_content_setting_key, 'advanced' );
580 ?>
581 <div class="elementor-toggle-item">
582 <<?php echo Utils::validate_html_tag( $settings['title_html_tag'] ); ?> <?php echo $this->get_render_attribute_string( $tab_title_setting_key ); ?>>
583 <?php if ( $has_icon ) : ?>
584 <span class="elementor-toggle-icon elementor-toggle-icon-<?php echo esc_attr( $settings['icon_align'] ); ?>" aria-hidden="true">
585 <?php
586 if ( $is_new || $migrated ) { ?>
587 <span class="elementor-toggle-icon-closed"><?php Icons_Manager::render_icon( $settings['selected_icon'] ); ?></span>
588 <span class="elementor-toggle-icon-opened"><?php Icons_Manager::render_icon( $settings['selected_active_icon'], [ 'class' => 'elementor-toggle-icon-opened' ] ); ?></span>
589 <?php } else { ?>
590 <i class="elementor-toggle-icon-closed <?php echo esc_attr( $settings['icon'] ); ?>"></i>
591 <i class="elementor-toggle-icon-opened <?php echo esc_attr( $settings['icon_active'] ); ?>"></i>
592 <?php } ?>
593 </span>
594 <?php endif; ?>
595 <a href="" class="elementor-toggle-title"><?php echo $item['tab_title']; ?></a>
596 </<?php echo Utils::validate_html_tag( $settings['title_html_tag'] ); ?>>
597 <div <?php echo $this->get_render_attribute_string( $tab_content_setting_key ); ?>><?php echo $this->parse_text_editor( $item['tab_content'] ); ?></div>
598 </div>
599 <?php endforeach; ?>
600 <?php
601 if ( isset( $settings['faq_schema'] ) && 'yes' === $settings['faq_schema'] ) {
602 $json = [
603 '@context' => 'https://schema.org',
604 '@type' => 'FAQPage',
605 'mainEntity' => [],
606 ];
607
608 foreach ( $settings['tabs'] as $index => $item ) {
609 $json['mainEntity'][] = [
610 '@type' => 'Question',
611 'name' => wp_strip_all_tags( $item['tab_title'] ),
612 'acceptedAnswer' => [
613 '@type' => 'Answer',
614 'text' => $this->parse_text_editor( $item['tab_content'] ),
615 ],
616 ];
617 }
618 ?>
619 <script type="application/ld+json"><?php echo wp_json_encode( $json ); ?></script>
620 <?php } ?>
621 </div>
622 <?php
623 }
624
625 /**
626 * Render toggle widget output in the editor.
627 *
628 * Written as a Backbone JavaScript template and used to generate the live preview.
629 *
630 * @since 2.9.0
631 * @access protected
632 */
633 protected function content_template() {
634 ?>
635 <div class="elementor-toggle" role="tablist">
636 <#
637 if ( settings.tabs ) {
638 var tabindex = view.getIDInt().toString().substr( 0, 3 ),
639 iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, {}, 'i' , 'object' ),
640 iconActiveHTML = elementor.helpers.renderIcon( view, settings.selected_active_icon, {}, 'i' , 'object' ),
641 migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' ),
642 titleHTMLTag = elementor.helpers.validateHTMLTag( settings.title_html_tag );
643
644 _.each( settings.tabs, function( item, index ) {
645 var tabCount = index + 1,
646 tabTitleKey = view.getRepeaterSettingKey( 'tab_title', 'tabs', index ),
647 tabContentKey = view.getRepeaterSettingKey( 'tab_content', 'tabs', index );
648
649 view.addRenderAttribute( tabTitleKey, {
650 'id': 'elementor-tab-title-' + tabindex + tabCount,
651 'class': [ 'elementor-tab-title' ],
652 'data-tab': tabCount,
653 'role': 'tab',
654 'aria-controls': 'elementor-tab-content-' + tabindex + tabCount,
655 'aria-expanded': 'false',
656 } );
657
658 view.addRenderAttribute( tabContentKey, {
659 'id': 'elementor-tab-content-' + tabindex + tabCount,
660 'class': [ 'elementor-tab-content', 'elementor-clearfix' ],
661 'data-tab': tabCount,
662 'role': 'tabpanel',
663 'aria-labelledby': 'elementor-tab-title-' + tabindex + tabCount
664 } );
665
666 view.addInlineEditingAttributes( tabContentKey, 'advanced' );
667 #>
668 <div class="elementor-toggle-item">
669 <{{{ titleHTMLTag }}} {{{ view.getRenderAttributeString( tabTitleKey ) }}}>
670 <# if ( settings.icon || settings.selected_icon ) { #>
671 <span class="elementor-toggle-icon elementor-toggle-icon-{{ settings.icon_align }}" aria-hidden="true">
672 <# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
673 <span class="elementor-toggle-icon-closed">{{{ iconHTML.value }}}</span>
674 <span class="elementor-toggle-icon-opened">{{{ iconActiveHTML.value }}}</span>
675 <# } else { #>
676 <i class="elementor-toggle-icon-closed {{ settings.icon }}"></i>
677 <i class="elementor-toggle-icon-opened {{ settings.icon_active }}"></i>
678 <# } #>
679 </span>
680 <# } #>
681 <a href="" class="elementor-toggle-title">{{{ item.tab_title }}}</a>
682 </{{{ titleHTMLTag }}}>
683 <div {{{ view.getRenderAttributeString( tabContentKey ) }}}>{{{ item.tab_content }}}</div>
684 </div>
685 <#
686 } );
687 } #>
688 </div>
689 <?php
690 }
691 }
692