PluginProbe
Elementor Website Builder – more than just a page builder / 3.2.3
Elementor Website Builder – more than just a page builder v3.2.3
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 / accordion.php

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

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