PluginProbe
Elementor Website Builder – more than just a page builder / 3.0.7
Elementor Website Builder – more than just a page builder v3.0.7
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.0.7, at includes/widgets/accordion.php

614 lines 17.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 1.0.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->end_controls_section();
224
225 $this->start_controls_section(
226 'section_title_style',
227 [
228 'label' => __( 'Accordion', 'elementor' ),
229 'tab' => Controls_Manager::TAB_STYLE,
230 ]
231 );
232
233 $this->add_control(
234 'border_width',
235 [
236 'label' => __( 'Border Width', 'elementor' ),
237 'type' => Controls_Manager::SLIDER,
238 'range' => [
239 'px' => [
240 'min' => 0,
241 'max' => 10,
242 ],
243 ],
244 'selectors' => [
245 '{{WRAPPER}} .elementor-accordion .elementor-accordion-item' => 'border-width: {{SIZE}}{{UNIT}};',
246 '{{WRAPPER}} .elementor-accordion .elementor-accordion-item .elementor-tab-content' => 'border-width: {{SIZE}}{{UNIT}};',
247 '{{WRAPPER}} .elementor-accordion .elementor-accordion-item .elementor-tab-title.elementor-active' => 'border-width: {{SIZE}}{{UNIT}};',
248 ],
249 ]
250 );
251
252 $this->add_control(
253 'border_color',
254 [
255 'label' => __( 'Border Color', 'elementor' ),
256 'type' => Controls_Manager::COLOR,
257 'selectors' => [
258 '{{WRAPPER}} .elementor-accordion .elementor-accordion-item' => 'border-color: {{VALUE}};',
259 '{{WRAPPER}} .elementor-accordion .elementor-accordion-item .elementor-tab-content' => 'border-top-color: {{VALUE}};',
260 '{{WRAPPER}} .elementor-accordion .elementor-accordion-item .elementor-tab-title.elementor-active' => 'border-bottom-color: {{VALUE}};',
261 ],
262 ]
263 );
264
265 $this->end_controls_section();
266
267 $this->start_controls_section(
268 'section_toggle_style_title',
269 [
270 'label' => __( 'Title', 'elementor' ),
271 'tab' => Controls_Manager::TAB_STYLE,
272 ]
273 );
274
275 $this->add_control(
276 'title_background',
277 [
278 'label' => __( 'Background', 'elementor' ),
279 'type' => Controls_Manager::COLOR,
280 'selectors' => [
281 '{{WRAPPER}} .elementor-accordion .elementor-tab-title' => 'background-color: {{VALUE}};',
282 ],
283 ]
284 );
285
286 $this->add_control(
287 'title_color',
288 [
289 'label' => __( 'Color', 'elementor' ),
290 'type' => Controls_Manager::COLOR,
291 'selectors' => [
292 '{{WRAPPER}} .elementor-accordion-icon, {{WRAPPER}} .elementor-accordion-title' => 'color: {{VALUE}};',
293 ],
294 'global' => [
295 'default' => Global_Colors::COLOR_PRIMARY,
296 ],
297 ]
298 );
299
300 $this->add_control(
301 'tab_active_color',
302 [
303 'label' => __( 'Active Color', 'elementor' ),
304 'type' => Controls_Manager::COLOR,
305 'selectors' => [
306 '{{WRAPPER}} .elementor-active .elementor-accordion-icon, {{WRAPPER}} .elementor-active .elementor-accordion-title' => 'color: {{VALUE}};',
307 ],
308 'global' => [
309 'default' => Global_Colors::COLOR_ACCENT,
310 ],
311 ]
312 );
313
314 $this->add_group_control(
315 Group_Control_Typography::get_type(),
316 [
317 'name' => 'title_typography',
318 'selector' => '{{WRAPPER}} .elementor-accordion .elementor-accordion-title',
319 'global' => [
320 'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
321 ],
322 ]
323 );
324
325 $this->add_responsive_control(
326 'title_padding',
327 [
328 'label' => __( 'Padding', 'elementor' ),
329 'type' => Controls_Manager::DIMENSIONS,
330 'size_units' => [ 'px', 'em', '%' ],
331 'selectors' => [
332 '{{WRAPPER}} .elementor-accordion .elementor-tab-title' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
333 ],
334 ]
335 );
336
337 $this->end_controls_section();
338
339 $this->start_controls_section(
340 'section_toggle_style_icon',
341 [
342 'label' => __( 'Icon', 'elementor' ),
343 'tab' => Controls_Manager::TAB_STYLE,
344 'condition' => [
345 'selected_icon[value]!' => '',
346 ],
347 ]
348 );
349
350 $this->add_control(
351 'icon_align',
352 [
353 'label' => __( 'Alignment', 'elementor' ),
354 'type' => Controls_Manager::CHOOSE,
355 'options' => [
356 'left' => [
357 'title' => __( 'Start', 'elementor' ),
358 'icon' => 'eicon-h-align-left',
359 ],
360 'right' => [
361 'title' => __( 'End', 'elementor' ),
362 'icon' => 'eicon-h-align-right',
363 ],
364 ],
365 'default' => is_rtl() ? 'right' : 'left',
366 'toggle' => false,
367 ]
368 );
369
370 $this->add_control(
371 'icon_color',
372 [
373 'label' => __( 'Color', 'elementor' ),
374 'type' => Controls_Manager::COLOR,
375 'selectors' => [
376 '{{WRAPPER}} .elementor-accordion .elementor-tab-title .elementor-accordion-icon i:before' => 'color: {{VALUE}};',
377 '{{WRAPPER}} .elementor-accordion .elementor-tab-title .elementor-accordion-icon svg' => 'fill: {{VALUE}};',
378 ],
379 ]
380 );
381
382 $this->add_control(
383 'icon_active_color',
384 [
385 'label' => __( 'Active Color', 'elementor' ),
386 'type' => Controls_Manager::COLOR,
387 'selectors' => [
388 '{{WRAPPER}} .elementor-accordion .elementor-tab-title.elementor-active .elementor-accordion-icon i:before' => 'color: {{VALUE}};',
389 '{{WRAPPER}} .elementor-accordion .elementor-tab-title.elementor-active .elementor-accordion-icon svg' => 'fill: {{VALUE}};',
390 ],
391 ]
392 );
393
394 $this->add_responsive_control(
395 'icon_space',
396 [
397 'label' => __( 'Spacing', 'elementor' ),
398 'type' => Controls_Manager::SLIDER,
399 'range' => [
400 'px' => [
401 'min' => 0,
402 'max' => 100,
403 ],
404 ],
405 'selectors' => [
406 '{{WRAPPER}} .elementor-accordion .elementor-accordion-icon.elementor-accordion-icon-left' => 'margin-right: {{SIZE}}{{UNIT}};',
407 '{{WRAPPER}} .elementor-accordion .elementor-accordion-icon.elementor-accordion-icon-right' => 'margin-left: {{SIZE}}{{UNIT}};',
408 ],
409 ]
410 );
411
412 $this->end_controls_section();
413
414 $this->start_controls_section(
415 'section_toggle_style_content',
416 [
417 'label' => __( 'Content', 'elementor' ),
418 'tab' => Controls_Manager::TAB_STYLE,
419 ]
420 );
421
422 $this->add_control(
423 'content_background_color',
424 [
425 'label' => __( 'Background', 'elementor' ),
426 'type' => Controls_Manager::COLOR,
427 'selectors' => [
428 '{{WRAPPER}} .elementor-accordion .elementor-tab-content' => 'background-color: {{VALUE}};',
429 ],
430 ]
431 );
432
433 $this->add_control(
434 'content_color',
435 [
436 'label' => __( 'Color', 'elementor' ),
437 'type' => Controls_Manager::COLOR,
438 'selectors' => [
439 '{{WRAPPER}} .elementor-accordion .elementor-tab-content' => 'color: {{VALUE}};',
440 ],
441 'global' => [
442 'default' => Global_Colors::COLOR_TEXT,
443 ],
444 ]
445 );
446
447 $this->add_group_control(
448 Group_Control_Typography::get_type(),
449 [
450 'name' => 'content_typography',
451 'selector' => '{{WRAPPER}} .elementor-accordion .elementor-tab-content',
452 'global' => [
453 'default' => Global_Typography::TYPOGRAPHY_TEXT,
454 ],
455 ]
456 );
457
458 $this->add_responsive_control(
459 'content_padding',
460 [
461 'label' => __( 'Padding', 'elementor' ),
462 'type' => Controls_Manager::DIMENSIONS,
463 'size_units' => [ 'px', 'em', '%' ],
464 'selectors' => [
465 '{{WRAPPER}} .elementor-accordion .elementor-tab-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
466 ],
467 ]
468 );
469
470 $this->end_controls_section();
471 }
472
473 /**
474 * Render accordion widget output on the frontend.
475 *
476 * Written in PHP and used to generate the final HTML.
477 *
478 * @since 1.0.0
479 * @access protected
480 */
481 protected function render() {
482 $settings = $this->get_settings_for_display();
483 $migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
484
485 if ( ! isset( $settings['icon'] ) && ! Icons_Manager::is_migration_allowed() ) {
486 // @todo: remove when deprecated
487 // added as bc in 2.6
488 // add old default
489 $settings['icon'] = 'fa fa-plus';
490 $settings['icon_active'] = 'fa fa-minus';
491 $settings['icon_align'] = $this->get_settings( 'icon_align' );
492 }
493
494 $is_new = empty( $settings['icon'] ) && Icons_Manager::is_migration_allowed();
495 $has_icon = ( ! $is_new || ! empty( $settings['selected_icon']['value'] ) );
496 $id_int = substr( $this->get_id_int(), 0, 3 );
497 ?>
498 <div class="elementor-accordion" role="tablist">
499 <?php
500 foreach ( $settings['tabs'] as $index => $item ) :
501 $tab_count = $index + 1;
502
503 $tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
504
505 $tab_content_setting_key = $this->get_repeater_setting_key( 'tab_content', 'tabs', $index );
506
507 $this->add_render_attribute( $tab_title_setting_key, [
508 'id' => 'elementor-tab-title-' . $id_int . $tab_count,
509 'class' => [ 'elementor-tab-title' ],
510 'data-tab' => $tab_count,
511 'role' => 'tab',
512 'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
513 ] );
514
515 $this->add_render_attribute( $tab_content_setting_key, [
516 'id' => 'elementor-tab-content-' . $id_int . $tab_count,
517 'class' => [ 'elementor-tab-content', 'elementor-clearfix' ],
518 'data-tab' => $tab_count,
519 'role' => 'tabpanel',
520 'aria-labelledby' => 'elementor-tab-title-' . $id_int . $tab_count,
521 ] );
522
523 $this->add_inline_editing_attributes( $tab_content_setting_key, 'advanced' );
524 ?>
525 <div class="elementor-accordion-item">
526 <<?php echo $settings['title_html_tag']; ?> <?php echo $this->get_render_attribute_string( $tab_title_setting_key ); ?>>
527 <?php if ( $has_icon ) : ?>
528 <span class="elementor-accordion-icon elementor-accordion-icon-<?php echo esc_attr( $settings['icon_align'] ); ?>" aria-hidden="true">
529 <?php
530 if ( $is_new || $migrated ) { ?>
531 <span class="elementor-accordion-icon-closed"><?php Icons_Manager::render_icon( $settings['selected_icon'] ); ?></span>
532 <span class="elementor-accordion-icon-opened"><?php Icons_Manager::render_icon( $settings['selected_active_icon'] ); ?></span>
533 <?php } else { ?>
534 <i class="elementor-accordion-icon-closed <?php echo esc_attr( $settings['icon'] ); ?>"></i>
535 <i class="elementor-accordion-icon-opened <?php echo esc_attr( $settings['icon_active'] ); ?>"></i>
536 <?php } ?>
537 </span>
538 <?php endif; ?>
539 <a class="elementor-accordion-title" href=""><?php echo $item['tab_title']; ?></a>
540 </<?php echo $settings['title_html_tag']; ?>>
541 <div <?php echo $this->get_render_attribute_string( $tab_content_setting_key ); ?>><?php echo $this->parse_text_editor( $item['tab_content'] ); ?></div>
542 </div>
543 <?php endforeach; ?>
544 </div>
545 <?php
546 }
547
548 /**
549 * Render accordion widget output in the editor.
550 *
551 * Written as a Backbone JavaScript template and used to generate the live preview.
552 *
553 * @since 2.9.0
554 * @access protected
555 */
556 protected function content_template() {
557 ?>
558 <div class="elementor-accordion" role="tablist">
559 <#
560 if ( settings.tabs ) {
561 var tabindex = view.getIDInt().toString().substr( 0, 3 ),
562 iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, {}, 'i' , 'object' ),
563 iconActiveHTML = elementor.helpers.renderIcon( view, settings.selected_active_icon, {}, 'i' , 'object' ),
564 migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' );
565
566 _.each( settings.tabs, function( item, index ) {
567 var tabCount = index + 1,
568 tabTitleKey = view.getRepeaterSettingKey( 'tab_title', 'tabs', index ),
569 tabContentKey = view.getRepeaterSettingKey( 'tab_content', 'tabs', index );
570
571 view.addRenderAttribute( tabTitleKey, {
572 'id': 'elementor-tab-title-' + tabindex + tabCount,
573 'class': [ 'elementor-tab-title' ],
574 'tabindex': tabindex + tabCount,
575 'data-tab': tabCount,
576 'role': 'tab',
577 'aria-controls': 'elementor-tab-content-' + tabindex + tabCount
578 } );
579
580 view.addRenderAttribute( tabContentKey, {
581 'id': 'elementor-tab-content-' + tabindex + tabCount,
582 'class': [ 'elementor-tab-content', 'elementor-clearfix' ],
583 'data-tab': tabCount,
584 'role': 'tabpanel',
585 'aria-labelledby': 'elementor-tab-title-' + tabindex + tabCount
586 } );
587
588 view.addInlineEditingAttributes( tabContentKey, 'advanced' );
589 #>
590 <div class="elementor-accordion-item">
591 <{{{ settings.title_html_tag }}} {{{ view.getRenderAttributeString( tabTitleKey ) }}}>
592 <# if ( settings.icon || settings.selected_icon ) { #>
593 <span class="elementor-accordion-icon elementor-accordion-icon-{{ settings.icon_align }}" aria-hidden="true">
594 <# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
595 <span class="elementor-accordion-icon-closed">{{{ iconHTML.value }}}</span>
596 <span class="elementor-accordion-icon-opened">{{{ iconActiveHTML.value }}}</span>
597 <# } else { #>
598 <i class="elementor-accordion-icon-closed {{ settings.icon }}"></i>
599 <i class="elementor-accordion-icon-opened {{ settings.icon_active }}"></i>
600 <# } #>
601 </span>
602 <# } #>
603 <a class="elementor-accordion-title" href="">{{{ item.tab_title }}}</a>
604 </{{{ settings.title_html_tag }}}>
605 <div {{{ view.getRenderAttributeString( tabContentKey ) }}}>{{{ item.tab_content }}}</div>
606 </div>
607 <#
608 } );
609 } #>
610 </div>
611 <?php
612 }
613 }
614