PluginProbe
Elementor Website Builder – more than just a page builder / 3.14.0-beta4
Elementor Website Builder – more than just a page builder v3.14.0-beta4
4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.3.0-beta3 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 All 457 releases
← All changes | modules/nested-accordion/widgets/nested-accordion.php +61 -913 4.2.0-dev2 → 3.14.0-beta4 View file →
@@ -1,22 +1,15 @@
1 1 <?php
2 2 namespace Elementor\Modules\NestedAccordion\Widgets;
3 3
4 4 use Elementor\Controls_Manager;
5 -use Elementor\Group_Control_Background;
6 -use Elementor\Group_Control_Border;
7 -use Elementor\Group_Control_Text_Shadow;
8 -use Elementor\Group_Control_Typography;
9 -use Elementor\Icons_Manager;
10 5 use Elementor\Modules\NestedElements\Base\Widget_Nested_Base;
11 6 use Elementor\Modules\NestedElements\Controls\Control_Nested_Repeater;
12 7 use Elementor\Plugin;
13 8 use Elementor\Repeater;
14 -use Elementor\Utils;
15 -use Elementor\Group_Control_Text_Stroke;
16 9
17 10 if ( ! defined( 'ABSPATH' ) ) {
18 - exit; // Exit if accessed directly.
11 + exit; // Exit if accessed directly
19 12 }
20 13
21 14 /**
22 15 * Elementor Nested Accordion widget.
@@ -27,17 +20,12 @@
27 20 * @since 3.15.0
28 21 */
29 22 class Nested_Accordion extends Widget_Nested_Base {
30 23
31 - private $optimized_markup = null;
32 - private $widget_container_selector = '';
24 + const NESTED_ACCORDION = 'nested-accordion';
33 25
34 - protected function is_dynamic_content(): bool {
35 - return true;
36 - }
37 -
38 26 public function get_name() {
39 - return 'nested-accordion';
27 + return static::NESTED_ACCORDION;
40 28 }
41 29
42 30 public function get_title() {
43 31 return esc_html__( 'Accordion', 'elementor' );
@@ -50,29 +38,17 @@
50 38 public function get_keywords() {
51 39 return [ 'nested', 'tabs', 'accordion', 'toggle' ];
52 40 }
53 41
54 - public function get_style_depends(): array {
55 - return [ 'widget-nested-accordion' ];
56 - }
57 -
58 42 public function show_in_panel(): bool {
59 - return Plugin::$instance->experiments->is_feature_active( 'nested-elements', true );
43 + return Plugin::$instance->experiments->is_feature_active( static::NESTED_ACCORDION );
60 44 }
61 45
62 - public function has_widget_inner_wrapper(): bool {
63 - return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' );
64 - }
65 -
66 46 protected function item_content_container( int $index ) {
67 47 return [
68 48 'elType' => 'container',
69 49 'settings' => [
70 - '_title' => sprintf(
71 - /* translators: %d: Item index. */
72 - __( 'item #%d', 'elementor' ),
73 - $index
74 - ),
50 + '_title' => sprintf( __( 'item #%s', 'elementor' ), $index ),
75 51 'content_width' => 'full',
76 52 ],
77 53 ];
78 54 }
@@ -89,9 +65,8 @@
89 65 return 'item_title';
90 66 }
91 67
92 68 protected function get_default_children_title() {
93 - /* translators: %d: Item index. */
94 69 return esc_html__( 'Item #%d', 'elementor' );
95 70 }
96 71
97 72 protected function get_default_children_placeholder_selector() {
@@ -97,41 +72,29 @@
97 72 protected function get_default_children_placeholder_selector() {
98 73 return '.e-n-accordion';
99 74 }
100 75
101 - protected function get_default_children_container_placeholder_selector() {
102 - return '.e-n-accordion-item';
103 - }
104 -
105 76 protected function get_html_wrapper_class() {
106 77 return 'elementor-widget-n-accordion';
107 78 }
108 79
109 80 protected function register_controls() {
110 - if ( null === $this->optimized_markup ) {
111 - $this->optimized_markup = Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' ) && ! $this->has_widget_inner_wrapper();
112 - $this->widget_container_selector = $this->optimized_markup ? '' : ' > .elementor-widget-container';
113 - }
114 -
115 81 $this->start_controls_section( 'section_items', [
116 - 'label' => esc_html__( 'Layout', 'elementor' ),
82 + 'label' => esc_html__( 'Accordion', 'elementor' ),
117 83 ] );
118 84
119 85 $repeater = new Repeater();
120 86
121 - $repeater->add_control(
122 - 'item_title',
123 - [
124 - 'label' => esc_html__( 'Title', 'elementor' ),
125 - 'type' => Controls_Manager::TEXT,
126 - 'default' => esc_html__( 'Item Title', 'elementor' ),
127 - 'placeholder' => esc_html__( 'Item Title', 'elementor' ),
128 - 'label_block' => true,
129 - 'dynamic' => [
130 - 'active' => true,
131 - ],
132 - ]
133 - );
87 + $repeater->add_control( 'item_title', [
88 + 'label' => esc_html__( 'Title', 'elementor' ),
89 + 'type' => Controls_Manager::TEXT,
90 + 'default' => esc_html__( 'Item Title', 'elementor' ),
91 + 'placeholder' => esc_html__( 'Item Title', 'elementor' ),
92 + 'label_block' => true,
93 + 'dynamic' => [
94 + 'active' => true,
95 + ],
96 + ] );
134 97
135 98 $repeater->add_control(
136 99 'element_css_id',
137 100 [
@@ -140,683 +103,47 @@
140 103 'default' => '',
141 104 'dynamic' => [
142 105 'active' => true,
143 106 ],
144 - 'ai' => [
145 - 'active' => false,
146 - ],
147 107 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
148 108 'style_transfer' => false,
149 109 ]
150 110 );
151 111
152 - $this->add_control(
153 - 'items',
154 - [
155 - 'label' => esc_html__( 'Items', 'elementor' ),
156 - 'type' => Control_Nested_Repeater::CONTROL_TYPE,
157 - 'fields' => $repeater->get_controls(),
158 - 'default' => [
159 - [
160 - 'item_title' => esc_html__( 'Item #1', 'elementor' ),
161 - ],
162 - [
163 - 'item_title' => esc_html__( 'Item #2', 'elementor' ),
164 - ],
165 - [
166 - 'item_title' => esc_html__( 'Item #3', 'elementor' ),
167 - ],
112 + $this->add_control( 'items', [
113 + 'label' => esc_html__( 'Items', 'elementor' ),
114 + 'type' => Control_Nested_Repeater::CONTROL_TYPE,
115 + 'fields' => $repeater->get_controls(),
116 + 'default' => [
117 + [
118 + 'item_title' => esc_html__( 'Item #1', 'elementor' ),
168 119 ],
169 - 'title_field' => '{{{ item_title }}}',
170 - 'button_text' => esc_html__( 'Add Item', 'elementor' ),
171 - ]
172 - );
173 -
174 - $this->add_responsive_control(
175 - 'accordion_item_title_position_horizontal',
176 - [
177 - 'label' => esc_html__( 'Item Position', 'elementor' ),
178 - 'type' => Controls_Manager::CHOOSE,
179 - 'separator' => 'before',
180 - 'options' => [
181 - 'start' => [
182 - 'title' => esc_html__( 'Start', 'elementor' ),
183 - 'icon' => 'eicon-flex eicon-align-start-h',
184 - ],
185 - 'center' => [
186 - 'title' => esc_html__( 'Center', 'elementor' ),
187 - 'icon' => 'eicon-h-align-center',
188 - ],
189 - 'end' => [
190 - 'title' => esc_html__( 'End', 'elementor' ),
191 - 'icon' => 'eicon-flex eicon-align-end-h',
192 - ],
193 - 'stretch' => [
194 - 'title' => esc_html__( 'Stretch', 'elementor' ),
195 - 'icon' => 'eicon-h-align-stretch',
196 - ],
120 + [
121 + 'item_title' => esc_html__( 'Item #2', 'elementor' ),
197 122 ],
198 - 'selectors_dictionary' => [
199 - 'start' => '--n-accordion-title-justify-content: initial; --n-accordion-title-flex-grow: initial;',
200 - 'center' => '--n-accordion-title-justify-content: center; --n-accordion-title-flex-grow: initial;',
201 - 'end' => '--n-accordion-title-justify-content: flex-end; --n-accordion-title-flex-grow: initial;',
202 - 'stretch' => '--n-accordion-title-justify-content: space-between; --n-accordion-title-flex-grow: 1;',
123 + [
124 + 'item_title' => esc_html__( 'Item #3', 'elementor' ),
203 125 ],
204 - 'selectors' => [
205 - '{{WRAPPER}}' => '{{VALUE}}',
206 - ],
207 - ]
208 - );
126 + ],
127 + 'title_field' => '{{{ item_title }}}',
128 + 'button_text' => 'Add Item',
129 + ] );
209 130
210 - $this->add_control(
211 - 'heading_accordion_item_title_icon',
212 - [
213 - 'type' => Controls_Manager::HEADING,
214 - 'label' => esc_html__( 'Icon', 'elementor' ),
215 - 'separator' => 'before',
216 - ]
217 - );
218 -
219 - $this->add_responsive_control(
220 - 'accordion_item_title_icon_position',
221 - [
222 - 'label' => esc_html__( 'Position', 'elementor' ),
223 - 'type' => Controls_Manager::CHOOSE,
224 - 'options' => [
225 - 'start' => [
226 - 'title' => esc_html__( 'Start', 'elementor' ),
227 - 'icon' => 'eicon-h-align-left',
228 - ],
229 - 'end' => [
230 - 'title' => esc_html__( 'End', 'elementor' ),
231 - 'icon' => 'eicon-h-align-right',
232 - ],
233 - ],
234 - 'selectors_dictionary' => [
235 - 'start' => '--n-accordion-title-icon-order: -1;',
236 - 'end' => '--n-accordion-title-icon-order: initial;',
237 - ],
238 - 'selectors' => [
239 - '{{WRAPPER}}' => '{{VALUE}}',
240 - ],
241 - ]
242 - );
243 -
244 - $this->add_control(
245 - 'accordion_item_title_icon',
246 - [
247 - 'label' => esc_html__( 'Expand', 'elementor' ),
248 - 'type' => Controls_Manager::ICONS,
249 - 'default' => [
250 - 'value' => 'fas fa-plus',
251 - 'library' => 'fa-solid',
252 - ],
253 - 'skin' => 'inline',
254 - 'label_block' => false,
255 - ]
256 - );
257 -
258 - $this->add_control(
259 - 'accordion_item_title_icon_active',
260 - [
261 - 'label' => esc_html__( 'Collapse', 'elementor' ),
262 - 'type' => Controls_Manager::ICONS,
263 - 'fa4compatibility' => 'icon_active',
264 - 'default' => [
265 - 'value' => 'fas fa-minus',
266 - 'library' => 'fa-solid',
267 - ],
268 - 'condition' => [
269 - 'accordion_item_title_icon[value]!' => '',
270 - ],
271 - 'skin' => 'inline',
272 - 'label_block' => false,
273 - ]
274 - );
275 -
276 - $this->add_control(
277 - 'title_tag',
278 - [
279 - 'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
280 - 'type' => Controls_Manager::SELECT,
281 - 'options' => [
282 - 'h1' => 'H1',
283 - 'h2' => 'H2',
284 - 'h3' => 'H3',
285 - 'h4' => 'H4',
286 - 'h5' => 'H5',
287 - 'h6' => 'H6',
288 - 'div' => 'div',
289 - 'span' => 'span',
290 - 'p' => 'p',
291 - ],
292 - 'selectors_dictionary' => [
293 - 'h1' => '--n-accordion-title-font-size: 2.5rem;',
294 - 'h2' => '--n-accordion-title-font-size: 2rem;',
295 - 'h3' => '--n-accordion-title-font-size: 1,75rem;',
296 - 'h4' => '--n-accordion-title-font-size: 1.5rem;',
297 - 'h5' => '--n-accordion-title-font-size: 1rem;',
298 - 'h6' => '--n-accordion-title-font-size: 1rem; ',
299 - 'div' => '--n-accordion-title-font-size: 1rem;',
300 - 'span' => '--n-accordion-title-font-size: 1rem; ',
301 - 'p' => '--n-accordion-title-font-size: 1rem;',
302 - ],
303 - 'selectors' => [
304 - '{{WRAPPER}}' => '{{VALUE}}',
305 - ],
306 - 'default' => 'div',
307 - 'separator' => 'before',
308 - 'render_type' => 'template',
309 -
310 - ]
311 - );
312 -
313 - $this->add_control(
314 - 'faq_schema',
315 - [
316 - 'label' => esc_html__( 'FAQ Schema', 'elementor' ),
317 - 'type' => Controls_Manager::SWITCHER,
318 - 'label_on' => esc_html__( 'Yes', 'elementor' ),
319 - 'label_off' => esc_html__( 'No', 'elementor' ),
320 - 'default' => 'no',
321 - ]
322 - );
323 -
324 - $this->add_control(
325 - 'faq_schema_message',
326 - [
327 - 'type' => Controls_Manager::ALERT,
328 - 'alert_type' => 'info',
329 - 'content' => esc_html__( 'Google no longer supports the FAQ schema; however, it may still hold secondary value for AI and LLMs.', 'elementor' ),
330 - 'condition' => [
331 - 'faq_schema[value]' => 'yes',
332 - ],
333 - ]
334 - );
335 -
336 131 $this->end_controls_section();
337 -
338 - $this->start_controls_section(
339 - 'section_interactions',
340 - [
341 - 'label' => esc_html__( 'Interactions', 'elementor' ),
342 - ]
343 - );
344 -
345 - $this->add_control(
346 - 'default_state',
347 - [
348 - 'label' => esc_html__( 'Default State', 'elementor' ),
349 - 'type' => Controls_Manager::SELECT,
350 - 'options' => [
351 - 'expanded' => esc_html__( 'First expanded', 'elementor' ),
352 - 'all_collapsed' => esc_html__( 'All collapsed', 'elementor' ),
353 - ],
354 - 'default' => 'expanded',
355 - 'frontend_available' => true,
356 - ]
357 - );
358 -
359 - $this->add_control(
360 - 'max_items_expended',
361 - [
362 - 'label' => esc_html__( 'Max Items Expanded', 'elementor' ),
363 - 'type' => Controls_Manager::SELECT,
364 - 'options' => [
365 - 'one' => esc_html__( 'One', 'elementor' ),
366 - 'multiple' => esc_html__( 'Multiple', 'elementor' ),
367 - ],
368 - 'default' => 'one',
369 - 'frontend_available' => true,
370 - ]
371 - );
372 -
373 - $this->add_control(
374 - 'n_accordion_animation_duration',
375 - [
376 - 'label' => esc_html__( 'Animation Duration', 'elementor' ),
377 - 'type' => Controls_Manager::SLIDER,
378 - 'size_units' => [ 's', 'ms' ],
379 - 'default' => [
380 - 'unit' => 'ms',
381 - 'size' => 400,
382 - ],
383 - 'frontend_available' => true,
384 - ]
385 - );
386 -
387 - $this->end_controls_section();
388 -
389 - $this->add_style_tab();
390 132 }
391 133
392 - private function add_style_tab() {
393 - $this->add_accordion_style_section();
394 - $this->add_header_style_section();
395 - $this->add_content_style_section();
396 - }
397 -
398 - private function add_accordion_style_section() {
399 - $this->start_controls_section(
400 - 'section_accordion_style',
401 - [
402 - 'label' => esc_html__( 'Accordion', 'elementor' ),
403 - 'tab' => Controls_Manager::TAB_STYLE,
404 - ]
405 - );
406 -
407 - $this->add_responsive_control(
408 - 'accordion_item_title_space_between',
409 - [
410 - 'label' => esc_html__( 'Space between Items', 'elementor' ),
411 - 'type' => Controls_Manager::SLIDER,
412 - 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
413 - 'range' => [
414 - 'px' => [
415 - 'max' => 200,
416 - ],
417 - 'em' => [
418 - 'max' => 20,
419 - ],
420 - 'rem' => [
421 - 'max' => 20,
422 - ],
423 - ],
424 - 'default' => [
425 - 'size' => 0,
426 - ],
427 - 'selectors' => [
428 - '{{WRAPPER}}' => '--n-accordion-item-title-space-between: {{SIZE}}{{UNIT}}',
429 - ],
430 - ]
431 - );
432 -
433 - $this->add_responsive_control(
434 - 'accordion_item_title_distance_from_content',
435 - [
436 - 'label' => esc_html__( 'Distance from content', 'elementor' ),
437 - 'type' => Controls_Manager::SLIDER,
438 - 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
439 - 'range' => [
440 - 'px' => [
441 - 'max' => 200,
442 - ],
443 - 'em' => [
444 - 'max' => 20,
445 - ],
446 - 'rem' => [
447 - 'max' => 20,
448 - ],
449 - ],
450 - 'default' => [
451 - 'size' => 0,
452 - ],
453 - 'selectors' => [
454 - '{{WRAPPER}}' => '--n-accordion-item-title-distance-from-content: {{SIZE}}{{UNIT}}',
455 - ],
456 - ]
457 - );
458 -
459 - $this->start_controls_tabs( 'accordion_border_and_background' );
460 -
461 - foreach ( [ 'normal', 'hover', 'active' ] as $state ) {
462 - $this->add_border_and_radius_style( $state );
463 - }
464 -
465 - $this->end_controls_tabs();
466 -
467 - $this->add_responsive_control(
468 - 'accordion_border_radius',
469 - [
470 - 'label' => esc_html__( 'Border Radius', 'elementor' ),
471 - 'type' => Controls_Manager::DIMENSIONS,
472 - 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
473 - 'selectors' => [
474 - '{{WRAPPER}}' => '--n-accordion-border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
475 - ],
476 - 'separator' => 'before',
477 - ]
478 - );
479 -
480 - $this->add_responsive_control(
481 - 'accordion_padding',
482 - [
483 - 'label' => esc_html__( 'Padding', 'elementor' ),
484 - 'type' => Controls_Manager::DIMENSIONS,
485 - 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
486 - 'selectors' => [
487 - '{{WRAPPER}} ' => '--n-accordion-padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
488 - ],
489 - ]
490 - );
491 -
492 - $this->end_controls_section();
493 - }
494 -
495 - private function add_content_style_section() {
496 - $low_specificity_accordion_item_selector = ":where( {{WRAPPER}}{$this->widget_container_selector} > .e-n-accordion > .e-n-accordion-item ) > .e-con";
497 -
498 - $this->start_controls_section(
499 - 'section_content_style',
500 - [
501 - 'label' => esc_html__( 'Content', 'elementor' ),
502 - 'tab' => Controls_Manager::TAB_STYLE,
503 - ]
504 - );
505 -
506 - $this->add_group_control(
507 - Group_Control_Background::get_type(),
508 - [
509 - 'name' => 'content_background',
510 - 'types' => [ 'classic', 'gradient' ],
511 - 'exclude' => [ 'image' ],
512 - 'selector' => $low_specificity_accordion_item_selector,
513 - ]
514 - );
515 -
516 - $this->add_group_control(
517 - Group_Control_Border::get_type(),
518 - [
519 - 'name' => 'content_border',
520 - 'selector' => $low_specificity_accordion_item_selector,
521 - 'fields_options' => [
522 - 'color' => [
523 - 'label' => esc_html__( 'Border Color', 'elementor' ),
524 - ],
525 - 'width' => [
526 - 'label' => esc_html__( 'Border Width', 'elementor' ),
527 - ],
528 - ],
529 - ]
530 - );
531 -
532 - $this->add_responsive_control(
533 - 'content_border_radius',
534 - [
535 - 'label' => esc_html__( 'Border Radius', 'elementor' ),
536 - 'type' => Controls_Manager::DIMENSIONS,
537 - 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
538 - 'selectors' => [
539 - $low_specificity_accordion_item_selector => '--border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
540 - ],
541 - ]
542 - );
543 -
544 - $this->add_responsive_control(
545 - 'content_padding',
546 - [
547 - 'label' => esc_html__( 'Padding', 'elementor' ),
548 - 'type' => Controls_Manager::DIMENSIONS,
549 - 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
550 - 'selectors' => [
551 - $low_specificity_accordion_item_selector => '--padding-top: {{TOP}}{{UNIT}}; --padding-right: {{RIGHT}}{{UNIT}}; --padding-bottom: {{BOTTOM}}{{UNIT}}; --padding-left: {{LEFT}}{{UNIT}};',
552 - ],
553 - ]
554 - );
555 -
556 - $this->end_controls_section();
557 - }
558 -
559 - private function add_header_style_section() {
560 - $this->start_controls_section(
561 - 'section_header_style',
562 - [
563 - 'label' => esc_html__( 'Header', 'elementor' ),
564 - 'tab' => Controls_Manager::TAB_STYLE,
565 - ]
566 - );
567 -
568 - $this->add_control(
569 - 'heading_header_style_title',
570 - [
571 - 'type' => Controls_Manager::HEADING,
572 - 'label' => esc_html__( 'Title', 'elementor' ),
573 -
574 - ]
575 - );
576 -
577 - $this->add_group_control(
578 - Group_Control_Typography::get_type(),
579 - [
580 - 'name' => 'title_typography',
581 - 'selector' => ":where( {{WRAPPER}}{$this->widget_container_selector} > .e-n-accordion > .e-n-accordion-item > .e-n-accordion-item-title > .e-n-accordion-item-title-header ) > .e-n-accordion-item-title-text",
582 - 'fields_options' => [
583 - 'font_size' => [
584 - 'selectors' => [
585 - '{{WRAPPER}}' => '--n-accordion-title-font-size: {{SIZE}}{{UNIT}}',
586 - ],
587 - ],
588 - ],
589 - ]
590 - );
591 -
592 - $this->start_controls_tabs( 'header_title_color_style' );
593 -
594 - foreach ( [ 'normal', 'hover', 'active' ] as $state ) {
595 - $this->add_header_style( $state, 'title' );
596 - }
597 -
598 - $this->end_controls_tabs();
599 -
600 - $this->add_control(
601 - 'heading_icon_style_title',
602 - [
603 - 'type' => Controls_Manager::HEADING,
604 - 'label' => esc_html__( 'Icon', 'elementor' ),
605 - 'separator' => 'before',
606 - ]
607 - );
608 -
609 - $this->add_responsive_control(
610 - 'icon_size',
611 - [
612 - 'label' => esc_html__( 'Size', 'elementor' ),
613 - 'type' => Controls_Manager::SLIDER,
614 - 'range' => [
615 - 'em' => [
616 - 'max' => 10,
617 - ],
618 - 'rem' => [
619 - 'max' => 10,
620 - ],
621 - ],
622 - 'default' => [
623 - 'unit' => 'px',
624 - 'size' => 15,
625 - ],
626 - 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
627 - 'selectors' => [
628 - '{{WRAPPER}}' => '--n-accordion-icon-size: {{SIZE}}{{UNIT}}',
629 - ],
630 - ]
631 - );
632 -
633 - $this->add_responsive_control(
634 - 'icon_spacing',
635 - [
636 - 'label' => esc_html__( 'Spacing', 'elementor' ),
637 - 'type' => Controls_Manager::SLIDER,
638 - 'range' => [
639 - 'px' => [
640 - 'max' => 400,
641 - ],
642 - 'vw' => [
643 - 'max' => 50,
644 - 'step' => 0.1,
645 - ],
646 - ],
647 - 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
648 - 'selectors' => [
649 - '{{WRAPPER}}' => '--n-accordion-icon-gap: {{SIZE}}{{UNIT}}',
650 - ],
651 - 'condition' => [
652 - 'accordion_item_title_position_horizontal!' => 'stretch',
653 - ],
654 - ]
655 - );
656 -
657 - $this->start_controls_tabs( 'header_icon_color_style' );
658 -
659 - foreach ( [ 'normal', 'hover', 'active' ] as $state ) {
660 - $this->add_header_style( $state, 'icon' );
661 - }
662 -
663 - $this->end_controls_tabs();
664 - $this->end_controls_section();
665 - }
666 -
667 - private function add_header_style( $state, $context ) {
668 - $variable = '--n-accordion-' . $context . '-' . $state . '-color';
669 -
670 - switch ( $state ) {
671 - case 'hover':
672 - $translated_tab_text = esc_html__( 'Hover', 'elementor' );
673 - $translated_tab_css_selector = ":where( {{WRAPPER}}{$this->widget_container_selector} > .e-n-accordion > .e-n-accordion-item:not([open]) > .e-n-accordion-item-title:hover > .e-n-accordion-item-title-header ) > .e-n-accordion-item-title-text";
674 - break;
675 - case 'active':
676 - $translated_tab_text = esc_html__( 'Active', 'elementor' );
677 - $translated_tab_css_selector = ":where( {{WRAPPER}}{$this->widget_container_selector} > .e-n-accordion > .e-n-accordion-item[open] > .e-n-accordion-item-title > .e-n-accordion-item-title-header ) > .e-n-accordion-item-title-text";
678 - break;
679 - default:
680 - $translated_tab_text = esc_html__( 'Normal', 'elementor' );
681 - $translated_tab_css_selector = ":where( {{WRAPPER}}{$this->widget_container_selector} > .e-n-accordion > .e-n-accordion-item:not([open]) > .e-n-accordion-item-title:not(hover) > .e-n-accordion-item-title-header ) > .e-n-accordion-item-title-text";
682 - break;
683 - }
684 -
685 - $this->start_controls_tab(
686 - 'header_' . $state . '_' . $context,
687 - [
688 - 'label' => $translated_tab_text,
689 - ]
690 - );
691 -
692 - $this->add_control(
693 - $state . '_' . $context . '_color',
694 - [
695 - 'label' => esc_html__( 'Color', 'elementor' ),
696 - 'type' => Controls_Manager::COLOR,
697 - 'selectors' => [
698 - '{{WRAPPER}}' => $variable . ': {{VALUE}};',
699 - ],
700 - ]
701 - );
702 -
703 - if ( 'title' === $context ) {
704 - $this->add_group_control(
705 - Group_Control_Text_Shadow::get_type(),
706 - [
707 - 'name' => $context . '_' . $state . '_text_shadow',
708 - 'selector' => '{{WRAPPER}} ' . $translated_tab_css_selector,
709 - ]
710 - );
711 -
712 - $this->add_group_control(
713 - Group_Control_Text_Stroke::get_type(),
714 - [
715 - 'name' => $context . '_' . $state . '_stroke',
716 - 'selector' => '{{WRAPPER}} ' . $translated_tab_css_selector,
717 - ]
718 - );
719 - }
720 -
721 - $this->end_controls_tab();
722 - }
723 -
724 - /**
725 - * @string $state
726 - */
727 - private function add_border_and_radius_style( $state ) {
728 - $selector = "{{WRAPPER}}{$this->widget_container_selector} > .e-n-accordion > .e-n-accordion-item > .e-n-accordion-item-title";
729 -
730 - $translated_tab_text = esc_html__( 'Normal', 'elementor' );
731 -
732 - switch ( $state ) {
733 - case 'hover':
734 - $selector .= ':hover';
735 - $translated_tab_text = esc_html__( 'Hover', 'elementor' );
736 - break;
737 - case 'active':
738 - $selector = "{{WRAPPER}}{$this->widget_container_selector} > .e-n-accordion > .e-n-accordion-item[open] > .e-n-accordion-item-title";
739 - $translated_tab_text = esc_html__( 'Active', 'elementor' );
740 - break;
741 - }
742 -
743 - $this->start_controls_tab(
744 - 'accordion_' . $state . '_border_and_background',
745 - [
746 - 'label' => $translated_tab_text,
747 - ]
748 - );
749 -
750 - $this->add_group_control(
751 - Group_Control_Background::get_type(),
752 - [
753 - 'name' => 'accordion_background_' . $state,
754 - 'types' => [ 'classic', 'gradient' ],
755 - 'exclude' => [ 'image' ],
756 - 'fields_options' => [
757 - 'color' => [
758 - 'label' => esc_html__( 'Color', 'elementor' ),
759 - ],
760 - ],
761 - 'selector' => $selector,
762 - ]
763 - );
764 -
765 - $this->add_group_control(
766 - Group_Control_Border::get_type(),
767 - [
768 - 'name' => 'accordion_border_' . $state,
769 - 'selector' => $selector,
770 - ]
771 - );
772 -
773 - $this->end_controls_tab();
774 - }
775 -
776 - private function is_active_icon_exist( $settings ): bool {
777 - return array_key_exists( 'accordion_item_title_icon_active', $settings ) && ! empty( $settings['accordion_item_title_icon_active'] ) && ! empty( $settings['accordion_item_title_icon_active']['value'] );
778 - }
779 -
780 - private function render_accordion_icons( $settings ) {
781 - $icon_html = Icons_Manager::try_get_icon_html( $settings['accordion_item_title_icon'], [ 'aria-hidden' => 'true' ] );
782 - $icon_active_html = $this->is_active_icon_exist( $settings )
783 - ? Icons_Manager::try_get_icon_html( $settings['accordion_item_title_icon_active'], [ 'aria-hidden' => 'true' ] )
784 - : $icon_html;
785 -
786 - ob_start();
787 - ?>
788 - <span class='e-n-accordion-item-title-icon'>
789 - <span class='e-opened' ><?php echo $icon_active_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
790 - <span class='e-closed'><?php echo $icon_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
791 - </span>
792 -
793 - <?php
794 - return ob_get_clean();
795 - }
796 -
797 134 protected function render() {
798 135 $settings = $this->get_settings_for_display();
799 136 $items = $settings['items'];
800 137 $id_int = substr( $this->get_id_int(), 0, 3 );
801 138 $items_title_html = '';
802 - $icons_content = $this->render_accordion_icons( $settings );
803 139 $this->add_render_attribute( 'elementor-accordion', 'class', 'e-n-accordion' );
804 - $this->add_render_attribute( 'elementor-accordion', 'aria-label', 'Accordion. Open links with Enter or Space, close with Escape, and navigate with Arrow Keys' );
805 - $default_state = $settings['default_state'];
806 - $title_html_tag = Utils::validate_html_tag( $settings['title_tag'] );
807 140
808 - $faq_schema = [];
809 -
810 141 foreach ( $items as $index => $item ) {
811 - $accordion_count = $index + 1;
812 142 $item_setting_key = $this->get_repeater_setting_key( 'item_title', 'items', $index );
813 - $item_summary_key = $this->get_repeater_setting_key( 'item_summary', 'items', $index );
814 - $item_classes = [ 'e-n-accordion-item' ];
815 - $item_id = empty( $item['element_css_id'] ) ? 'e-n-accordion-item-' . $id_int . $index : $item['element_css_id'];
143 + $item_classes = [ 'e-n-accordion-item', 'e-normal' ];
144 + $item_id = empty( $item['element_css_id'] ) ? 'e-n-accordion-item-' . $id_int : $item['element_css_id'];
816 145 $item_title = $item['item_title'];
817 - $is_open = 'expanded' === $default_state && 0 === $index ? 'open' : '';
818 - $aria_expanded = 'expanded' === $default_state && 0 === $index;
819 146
820 147 $this->add_render_attribute( $item_setting_key, [
821 148 'id' => $item_id,
822 149 'class' => $item_classes,
@@ -821,241 +148,62 @@
821 148 'id' => $item_id,
822 149 'class' => $item_classes,
823 150 ] );
824 151
825 - $this->add_render_attribute( $item_summary_key, [
826 - 'class' => [ 'e-n-accordion-item-title' ],
827 - 'data-accordion-index' => $accordion_count,
828 - 'tabindex' => 0 === $index ? 0 : -1,
829 - 'aria-expanded' => $aria_expanded ? 'true' : 'false',
830 - 'aria-controls' => $item_id,
831 - ] );
832 -
833 152 $title_render_attributes = $this->get_render_attribute_string( $item_setting_key );
834 - $title_render_attributes = $title_render_attributes . ' ' . $is_open;
835 153
836 - $summary_render_attributes = $this->get_render_attribute_string( $item_summary_key );
837 -
838 154 // items content.
839 155 ob_start();
840 - $this->print_child( $index, $item_id );
156 + $this->print_child( $index );
841 157 $item_content = ob_get_clean();
842 158
843 - $faq_schema[ $item_title ] = $item_content;
844 -
845 - ob_start();
846 - ?>
847 - <details <?php echo wp_kses_post( $title_render_attributes ); ?>>
848 - <summary <?php echo wp_kses_post( $summary_render_attributes ); ?> >
849 - <span class='e-n-accordion-item-title-header'><?php echo wp_kses_post( "<$title_html_tag class=\"e-n-accordion-item-title-text\"> $item_title </$title_html_tag>" ); ?></span>
850 - <?php if ( ! empty( $settings['accordion_item_title_icon']['value'] ) ) {
851 - echo $icons_content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
852 - } ?>
853 - </summary>
854 - <?php echo $item_content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
855 - </details>
856 - <?php
857 - $items_title_html .= ob_get_clean();
159 + $items_title_html .= "\t<details {$title_render_attributes}>";
160 + $items_title_html .= "\t\t<summary class='e-n-accordion-item-title'>{$item_title}</summary>";
161 + $items_title_html .= "\t\t{$item_content}";
162 + $items_title_html .= "\t</details>";
858 163 }
859 164
860 165 ?>
861 166 <div <?php $this->print_render_attribute_string( 'elementor-accordion' ); ?>>
862 - <?php echo $items_title_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
167 + <?php echo $items_title_html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
863 168 </div>
864 169 <?php
865 - if ( isset( $settings['faq_schema'] ) && 'yes' === $settings['faq_schema'] ) {
866 - $json = [
867 - '@context' => 'https://schema.org',
868 - '@type' => 'FAQPage',
869 - 'mainEntity' => [],
870 - ];
871 -
872 - foreach ( $faq_schema as $name => $text ) {
873 - $json['mainEntity'][] = [
874 - '@type' => 'Question',
875 - 'name' => wp_strip_all_tags( $name ),
876 - 'acceptedAnswer' => [
877 - '@type' => 'Answer',
878 - 'text' => wp_strip_all_tags( $text ),
879 - ],
880 - ];
881 - }
882 - ?>
883 - <script type="application/ld+json"><?php echo wp_json_encode( $json ); ?></script>
884 - <?php
885 - }
886 170 }
887 171
888 - public function print_child( $index, $item_id = null ) {
889 - $children = $this->get_children();
890 -
891 - if ( ! empty( $children[ $index ] ) ) {
892 - // Add data-tab-index attribute to the content area.
893 - $add_attribute_to_container = function ( $should_render, $container ) use ( $item_id ) {
894 - $this->add_attributes_to_container( $container, $item_id );
895 -
896 - return $should_render;
897 - };
898 -
899 - add_filter( 'elementor/frontend/container/should_render', $add_attribute_to_container, 10, 3 );
900 - $children[ $index ]->print_element();
901 - remove_filter( 'elementor/frontend/container/should_render', $add_attribute_to_container );
902 - }
903 - }
904 -
905 - protected function add_attributes_to_container( $container, $item_id ) {
906 - $container->add_render_attribute( '_wrapper', [
907 - 'role' => 'region',
908 - 'aria-labelledby' => $item_id,
909 - ] );
910 - }
911 -
912 - protected function get_initial_config(): array {
913 - return array_merge( parent::get_initial_config(), [
914 - 'support_improved_repeaters' => true,
915 - 'target_container' => [ '.e-n-accordion' ],
916 - 'node' => 'details',
917 - 'is_interlaced' => true,
918 - ] );
919 - }
920 -
921 - protected function content_template_single_repeater_item() {
922 - ?>
923 - <#
924 - const elementUid = view.getIDInt().toString().substring( 0, 3 ) + view.collection.length;
925 -
926 - const itemWrapperAttributes = {
927 - 'id': 'e-n-accordion-item-' + elementUid,
928 - 'class': [ 'e-n-accordion-item', 'e-normal' ],
929 - };
930 -
931 - const itemTitleAttributes = {
932 - 'class': [ 'e-n-accordion-item-title' ],
933 - 'data-accordion-index': view.collection.length + 1,
934 - 'tabindex': -1,
935 - 'aria-expanded': 'false',
936 - 'aria-controls': 'e-n-accordion-item-' + elementUid,
937 - };
938 -
939 - const itemTitleTextAttributes = {
940 - 'class': [ 'e-n-accordion-item-title-text' ],
941 - 'data-binding-index': view.collection.length + 1,
942 - 'data-binding-type': 'repeater-item',
943 - 'data-binding-repeater-name': 'items',
944 - 'data-binding-setting': ['item_title', 'element_css_id'],
945 - 'data-binding-config': JSON.stringify({
946 - 'element_css_id': {
947 - editType: 'attribute',
948 - attr: 'id',
949 - selector: 'details'
950 - },
951 - 'item_title': {
952 - editType: 'text'
953 - }
954 - }),
955 - };
956 -
957 - view.addRenderAttribute( 'details-container', itemWrapperAttributes, null, true );
958 - view.addRenderAttribute( 'summary-container', itemTitleAttributes, null, true );
959 - view.addRenderAttribute( 'text-container', itemTitleTextAttributes, null, true );
960 - #>
961 -
962 - <details {{{ view.getRenderAttributeString( 'details-container' ) }}}>
963 - <summary {{{ view.getRenderAttributeString( 'summary-container' ) }}}>
964 - <span class="e-n-accordion-item-title-header">
965 - <div {{{ view.getRenderAttributeString( 'text-container' ) }}}>{{{ data.item_title }}}</div>
966 - </span>
967 - <span class="e-n-accordion-item-title-icon">
968 - <span class="e-opened"><i aria-hidden="true" class="fas fa-minus"></i></span>
969 - <span class="e-closed"><i aria-hidden="true" class="fas fa-plus"></i></span>
970 - </span>
971 - </summary>
972 - </details>
973 - <?php
974 - }
975 -
976 172 protected function content_template() {
977 173 ?>
978 - <div class="e-n-accordion" aria-label="Accordion. Open links with Enter or Space, close with Escape, and navigate with Arrow Keys">
174 + <div class="e-n-accordion" role="tablist" aria-orientation="vertical">
979 175 <# if ( settings['items'] ) {
980 - const elementUid = view.getIDInt().toString().substring( 0, 3 ),
981 - titleHTMLTag = elementor.helpers.validateHTMLTag( settings.title_tag ),
982 - defaultState = settings.default_state,
983 - itemTitleIcon = elementor.helpers.renderIcon( view, settings['accordion_item_title_icon'], { 'aria-hidden': true }, 'i', 'object' ) ?? '',
984 - itemTitleIconActive = '' === settings.accordion_item_title_icon_active.value
985 - ? itemTitleIcon
986 - : elementor.helpers.renderIcon( view, settings['accordion_item_title_icon_active'], { 'aria-hidden': true }, 'i', 'object' );
987 - #>
176 + const elementUid = view.getIDInt().toString().substr( 0, 3 ); #>
988 177
989 - <# _.each( settings['items'], function( item, index ) {
990 - const itemCount = index + 1,
991 - itemUid = elementUid + index,
992 - itemTitleTextKey = 'item-title-text-' + itemUid,
993 - itemWrapperKey = itemUid,
994 - itemTitleKey = 'item-' + itemUid,
995 - ariaExpanded = 'expanded' === defaultState && 0 === index ? 'true' : 'false';
178 + <# _.each( settings['items'], function( item, index ) {
179 + const itemCount = index + 1,
180 + itemUid = elementUid + itemCount,
181 + itemWrapperKey = itemUid,
182 + itemTitleKey = 'item-' + itemUid;
996 183
997 - if ( '' !== item.element_css_id ) {
998 - itemId = item.element_css_id;
999 - } else {
1000 - itemId = 'e-n-accordion-item-' + itemUid;
1001 - }
184 + if ( '' !== item.element_css_id ) {
185 + itemId = item.element_css_id;
186 + } else {
187 + itemId = 'e-n-accordion-item-' + itemUid;
188 + }
1002 189
1003 - const itemWrapperAttributes = {
1004 - 'id': itemId,
1005 - 'class': [ 'e-n-accordion-item', 'e-normal' ],
1006 - };
190 + view.addRenderAttribute( itemWrapperKey, {
191 + 'id': itemId,
192 + 'class': [ 'e-n-accordion-item','e-normal' ],
193 + } );
1007 194
1008 - if ( defaultState === 'expanded' && index === 0) {
1009 - itemWrapperAttributes['open'] = true;
1010 - }
195 + view.addRenderAttribute( itemTitleKey, {
196 + 'class': [ 'e-n-accordion-item-title' ],
197 + } );
1011 198
1012 - view.addRenderAttribute( itemWrapperKey, itemWrapperAttributes );
199 + #>
1013 200
1014 - view.addRenderAttribute( itemTitleKey, {
1015 - 'class': ['e-n-accordion-item-title'],
1016 - 'data-accordion-index': itemCount,
1017 - 'tabindex': 0 === index ? 0 : -1,
1018 - 'aria-expanded': ariaExpanded,
1019 - 'aria-controls': itemId,
1020 - });
1021 -
1022 - view.addRenderAttribute( itemTitleTextKey, {
1023 - 'class': ['e-n-accordion-item-title-text'],
1024 - 'data-binding-index': itemCount,
1025 - 'data-binding-type': 'repeater-item',
1026 - 'data-binding-repeater-name': 'items',
1027 - 'data-binding-setting': ['item_title', 'element_css_id'],
1028 - 'data-binding-config': JSON.stringify({
1029 - 'element_css_id': {
1030 - editType: 'attribute',
1031 - attr: 'id',
1032 - selector: 'details'
1033 - },
1034 - 'item_title': {
1035 - editType: 'text'
1036 - }
1037 - }),
1038 - });
1039 - #>
1040 -
1041 201 <details {{{ view.getRenderAttributeString( itemWrapperKey ) }}}>
1042 - <summary {{{ view.getRenderAttributeString( itemTitleKey ) }}}>
1043 - <span class="e-n-accordion-item-title-header">
1044 - <{{{ titleHTMLTag }}} {{{ view.getRenderAttributeString( itemTitleTextKey ) }}}>
1045 - {{{ item.item_title }}}
1046 - </{{{ titleHTMLTag }}}>
1047 - </span>
1048 - <# if (settings.accordion_item_title_icon.value) { #>
1049 - <span class="e-n-accordion-item-title-icon">
1050 - <span class="e-opened">{{{ itemTitleIconActive.value }}}</span>
1051 - <span class="e-closed">{{{ itemTitleIcon.value }}}</span>
1052 - </span>
1053 - <# } #>
1054 - </summary>
202 + <summary {{{ view.getRenderAttributeString( itemTitleKey ) }}}>{{{ item.item_title }}}</summary>
1055 203 </details>
1056 204 <# } ); #>
1057 205 <# } #>
1058 - </div>
206 + </div>
1059 207 <?php
1060 208 }
1061 209 }