PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.3
Elementor Website Builder – more than just a page builder v3.6.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 / tabs.php

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

579 lines 15.5 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 tabs widget.
13 *
14 * Elementor widget that displays vertical or horizontal tabs with different
15 * pieces of content.
16 *
17 * @since 1.0.0
18 */
19 class Widget_Tabs extends Widget_Base {
20
21 /**
22 * Get widget name.
23 *
24 * Retrieve tabs 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 'tabs';
33 }
34
35 /**
36 * Get widget title.
37 *
38 * Retrieve tabs 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 esc_html__( 'Tabs', 'elementor' );
47 }
48
49 /**
50 * Get widget icon.
51 *
52 * Retrieve tabs 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-tabs';
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 tabs 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_tabs',
88 [
89 'label' => esc_html__( 'Tabs', 'elementor' ),
90 ]
91 );
92
93 $repeater = new Repeater();
94
95 $repeater->add_control(
96 'tab_title',
97 [
98 'label' => esc_html__( 'Title & Description', 'elementor' ),
99 'type' => Controls_Manager::TEXT,
100 'default' => esc_html__( 'Tab Title', 'elementor' ),
101 'placeholder' => esc_html__( 'Tab Title', 'elementor' ),
102 'label_block' => true,
103 'dynamic' => [
104 'active' => true,
105 ],
106 ]
107 );
108
109 $repeater->add_control(
110 'tab_content',
111 [
112 'label' => esc_html__( 'Content', 'elementor' ),
113 'default' => esc_html__( 'Tab Content', 'elementor' ),
114 'placeholder' => esc_html__( 'Tab Content', 'elementor' ),
115 'type' => Controls_Manager::WYSIWYG,
116 'show_label' => false,
117 ]
118 );
119
120 $this->add_control(
121 'tabs',
122 [
123 'label' => esc_html__( 'Tabs Items', 'elementor' ),
124 'type' => Controls_Manager::REPEATER,
125 'fields' => $repeater->get_controls(),
126 'default' => [
127 [
128 'tab_title' => esc_html__( 'Tab #1', 'elementor' ),
129 'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
130 ],
131 [
132 'tab_title' => esc_html__( 'Tab #2', 'elementor' ),
133 'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
134 ],
135 ],
136 'title_field' => '{{{ tab_title }}}',
137 ]
138 );
139
140 $this->add_control(
141 'view',
142 [
143 'label' => esc_html__( 'View', 'elementor' ),
144 'type' => Controls_Manager::HIDDEN,
145 'default' => 'traditional',
146 ]
147 );
148
149 $this->add_control(
150 'type',
151 [
152 'label' => esc_html__( 'Position', 'elementor' ),
153 'type' => Controls_Manager::SELECT,
154 'default' => 'horizontal',
155 'options' => [
156 'horizontal' => esc_html__( 'Horizontal', 'elementor' ),
157 'vertical' => esc_html__( 'Vertical', 'elementor' ),
158 ],
159 'prefix_class' => 'elementor-tabs-view-',
160 'separator' => 'before',
161 ]
162 );
163
164 $this->add_control(
165 'tabs_align_horizontal',
166 [
167 'label' => esc_html__( 'Alignment', 'elementor' ),
168 'type' => Controls_Manager::CHOOSE,
169 'options' => [
170 '' => [
171 'title' => esc_html__( 'Start', 'elementor' ),
172 'icon' => 'eicon-h-align-left',
173 ],
174 'center' => [
175 'title' => esc_html__( 'Center', 'elementor' ),
176 'icon' => 'eicon-h-align-center',
177 ],
178 'end' => [
179 'title' => esc_html__( 'End', 'elementor' ),
180 'icon' => 'eicon-h-align-right',
181 ],
182 'stretch' => [
183 'title' => esc_html__( 'Justified', 'elementor' ),
184 'icon' => 'eicon-h-align-stretch',
185 ],
186 ],
187 'prefix_class' => 'elementor-tabs-alignment-',
188 'condition' => [
189 'type' => 'horizontal',
190 ],
191 ]
192 );
193
194 $this->add_control(
195 'tabs_align_vertical',
196 [
197 'label' => esc_html__( 'Alignment', 'elementor' ),
198 'type' => Controls_Manager::CHOOSE,
199 'options' => [
200 '' => [
201 'title' => esc_html__( 'Start', 'elementor' ),
202 'icon' => 'eicon-v-align-top',
203 ],
204 'center' => [
205 'title' => esc_html__( 'Center', 'elementor' ),
206 'icon' => 'eicon-v-align-middle',
207 ],
208 'end' => [
209 'title' => esc_html__( 'End', 'elementor' ),
210 'icon' => 'eicon-v-align-bottom',
211 ],
212 'stretch' => [
213 'title' => esc_html__( 'Justified', 'elementor' ),
214 'icon' => 'eicon-v-align-stretch',
215 ],
216 ],
217 'prefix_class' => 'elementor-tabs-alignment-',
218 'condition' => [
219 'type' => 'vertical',
220 ],
221 ]
222 );
223
224 $this->end_controls_section();
225
226 $this->start_controls_section(
227 'section_tabs_style',
228 [
229 'label' => esc_html__( 'Tabs', 'elementor' ),
230 'tab' => Controls_Manager::TAB_STYLE,
231 ]
232 );
233
234 $this->add_control(
235 'navigation_width',
236 [
237 'label' => esc_html__( 'Navigation Width', 'elementor' ),
238 'type' => Controls_Manager::SLIDER,
239 'default' => [
240 'unit' => '%',
241 ],
242 'range' => [
243 '%' => [
244 'min' => 10,
245 'max' => 50,
246 ],
247 ],
248 'selectors' => [
249 '{{WRAPPER}} .elementor-tabs-wrapper' => 'width: {{SIZE}}{{UNIT}}',
250 ],
251 'condition' => [
252 'type' => 'vertical',
253 ],
254 ]
255 );
256
257 $this->add_control(
258 'border_width',
259 [
260 'label' => esc_html__( 'Border Width', 'elementor' ),
261 'type' => Controls_Manager::SLIDER,
262 'default' => [
263 'size' => 1,
264 ],
265 'range' => [
266 'px' => [
267 'min' => 0,
268 'max' => 10,
269 ],
270 ],
271 'selectors' => [
272 '{{WRAPPER}} .elementor-tab-title, {{WRAPPER}} .elementor-tab-title:before, {{WRAPPER}} .elementor-tab-title:after, {{WRAPPER}} .elementor-tab-content, {{WRAPPER}} .elementor-tabs-content-wrapper' => 'border-width: {{SIZE}}{{UNIT}};',
273 ],
274 ]
275 );
276
277 $this->add_control(
278 'border_color',
279 [
280 'label' => esc_html__( 'Border Color', 'elementor' ),
281 'type' => Controls_Manager::COLOR,
282 'selectors' => [
283 '{{WRAPPER}} .elementor-tab-mobile-title, {{WRAPPER}} .elementor-tab-desktop-title.elementor-active, {{WRAPPER}} .elementor-tab-title:before, {{WRAPPER}} .elementor-tab-title:after, {{WRAPPER}} .elementor-tab-content, {{WRAPPER}} .elementor-tabs-content-wrapper' => 'border-color: {{VALUE}};',
284 ],
285 ]
286 );
287
288 $this->add_control(
289 'background_color',
290 [
291 'label' => esc_html__( 'Background Color', 'elementor' ),
292 'type' => Controls_Manager::COLOR,
293 'selectors' => [
294 '{{WRAPPER}} .elementor-tab-desktop-title.elementor-active' => 'background-color: {{VALUE}};',
295 '{{WRAPPER}} .elementor-tabs-content-wrapper' => 'background-color: {{VALUE}};',
296 ],
297 ]
298 );
299
300 $this->add_control(
301 'heading_title',
302 [
303 'label' => esc_html__( 'Title', 'elementor' ),
304 'type' => Controls_Manager::HEADING,
305 'separator' => 'before',
306 ]
307 );
308
309 $this->add_control(
310 'tab_color',
311 [
312 'label' => esc_html__( 'Color', 'elementor' ),
313 'type' => Controls_Manager::COLOR,
314 'selectors' => [
315 '{{WRAPPER}} .elementor-tab-title, {{WRAPPER}} .elementor-tab-title a' => 'color: {{VALUE}}',
316 ],
317 'global' => [
318 'default' => Global_Colors::COLOR_PRIMARY,
319 ],
320 ]
321 );
322
323 $this->add_control(
324 'tab_active_color',
325 [
326 'label' => esc_html__( 'Active Color', 'elementor' ),
327 'type' => Controls_Manager::COLOR,
328 'selectors' => [
329 '{{WRAPPER}} .elementor-tab-title.elementor-active,
330 {{WRAPPER}} .elementor-tab-title.elementor-active a' => 'color: {{VALUE}}',
331 ],
332 'global' => [
333 'default' => Global_Colors::COLOR_ACCENT,
334 ],
335 ]
336 );
337
338 $this->add_group_control(
339 Group_Control_Typography::get_type(),
340 [
341 'name' => 'tab_typography',
342 'selector' => '{{WRAPPER}} .elementor-tab-title',
343 'global' => [
344 'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
345 ],
346 ]
347 );
348
349 $this->add_group_control(
350 Group_Control_Text_Stroke::get_type(),
351 [
352 'name' => 'text_stroke',
353 'selector' => '{{WRAPPER}} .elementor-tab-title',
354 ]
355 );
356
357 $this->add_group_control(
358 Group_Control_Text_Shadow::get_type(),
359 [
360 'name' => 'title_shadow',
361 'selector' => '{{WRAPPER}} .elementor-tab-title',
362 ]
363 );
364
365 $this->add_control(
366 'title_align',
367 [
368 'label' => esc_html__( 'Alignment', 'elementor' ),
369 'type' => Controls_Manager::CHOOSE,
370 'options' => [
371 'left' => [
372 'title' => esc_html__( 'Left', 'elementor' ),
373 'icon' => 'eicon-text-align-left',
374 ],
375 'center' => [
376 'title' => esc_html__( 'Center', 'elementor' ),
377 'icon' => 'eicon-text-align-center',
378 ],
379 'right' => [
380 'title' => esc_html__( 'Right', 'elementor' ),
381 'icon' => 'eicon-text-align-right',
382 ],
383 ],
384 'selectors' => [
385 '{{WRAPPER}} .elementor-tab-title' => 'text-align: {{VALUE}};',
386 ],
387 'condition' => [
388 'tabs_align' => 'stretch',
389 ],
390 ]
391 );
392
393 $this->add_control(
394 'heading_content',
395 [
396 'label' => esc_html__( 'Content', 'elementor' ),
397 'type' => Controls_Manager::HEADING,
398 'separator' => 'before',
399 ]
400 );
401
402 $this->add_control(
403 'content_color',
404 [
405 'label' => esc_html__( 'Color', 'elementor' ),
406 'type' => Controls_Manager::COLOR,
407 'selectors' => [
408 '{{WRAPPER}} .elementor-tab-content' => 'color: {{VALUE}};',
409 ],
410 'global' => [
411 'default' => Global_Colors::COLOR_TEXT,
412 ],
413 ]
414 );
415
416 $this->add_group_control(
417 Group_Control_Typography::get_type(),
418 [
419 'name' => 'content_typography',
420 'selector' => '{{WRAPPER}} .elementor-tab-content',
421 'global' => [
422 'default' => Global_Typography::TYPOGRAPHY_TEXT,
423 ],
424 ]
425 );
426
427 $this->add_group_control(
428 Group_Control_Text_Shadow::get_type(),
429 [
430 'name' => 'content_shadow',
431 'selector' => '{{WRAPPER}} .elementor-tab-content',
432 ]
433 );
434
435 $this->end_controls_section();
436 }
437
438 /**
439 * Render tabs widget output on the frontend.
440 *
441 * Written in PHP and used to generate the final HTML.
442 *
443 * @since 1.0.0
444 * @access protected
445 */
446 protected function render() {
447 $tabs = $this->get_settings_for_display( 'tabs' );
448
449 $id_int = substr( $this->get_id_int(), 0, 3 );
450
451 $a11y_improvements_experiment = Plugin::$instance->experiments->is_feature_active( 'a11y_improvements' );
452
453 $this->add_render_attribute( 'elementor-tabs', 'class', 'elementor-tabs' );
454
455 ?>
456 <div <?php $this->print_render_attribute_string( 'elementor-tabs' ); ?>>
457 <div class="elementor-tabs-wrapper" role="tablist" >
458 <?php
459 foreach ( $tabs as $index => $item ) :
460 $tab_count = $index + 1;
461 $tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
462 $tab_title = $a11y_improvements_experiment ? $item['tab_title'] : '<a href="">' . $item['tab_title'] . '</a>';
463
464 $this->add_render_attribute( $tab_title_setting_key, [
465 'id' => 'elementor-tab-title-' . $id_int . $tab_count,
466 'class' => [ 'elementor-tab-title', 'elementor-tab-desktop-title' ],
467 'aria-selected' => 1 === $tab_count ? 'true' : 'false',
468 'data-tab' => $tab_count,
469 'role' => 'tab',
470 'tabindex' => 1 === $tab_count ? '0' : '-1',
471 'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
472 'aria-expanded' => 'false',
473 ] );
474 ?>
475 <div <?php $this->print_render_attribute_string( $tab_title_setting_key ); ?>><?php
476 // PHPCS - the main text of a widget should not be escaped.
477 echo $tab_title; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
478 ?></div>
479 <?php endforeach; ?>
480 </div>
481 <div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
482 <?php
483 foreach ( $tabs as $index => $item ) :
484 $tab_count = $index + 1;
485 $hidden = 1 === $tab_count ? 'false' : 'hidden';
486 $tab_content_setting_key = $this->get_repeater_setting_key( 'tab_content', 'tabs', $index );
487
488 $tab_title_mobile_setting_key = $this->get_repeater_setting_key( 'tab_title_mobile', 'tabs', $tab_count );
489
490 $this->add_render_attribute( $tab_content_setting_key, [
491 'id' => 'elementor-tab-content-' . $id_int . $tab_count,
492 'class' => [ 'elementor-tab-content', 'elementor-clearfix' ],
493 'data-tab' => $tab_count,
494 'role' => 'tabpanel',
495 'aria-labelledby' => 'elementor-tab-title-' . $id_int . $tab_count,
496 'tabindex' => '0',
497 'hidden' => $hidden,
498 ] );
499
500 $this->add_render_attribute( $tab_title_mobile_setting_key, [
501 'class' => [ 'elementor-tab-title', 'elementor-tab-mobile-title' ],
502 'aria-selected' => 1 === $tab_count ? 'true' : 'false',
503 'data-tab' => $tab_count,
504 'role' => 'tab',
505 'tabindex' => 1 === $tab_count ? '0' : '-1',
506 'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
507 'aria-expanded' => 'false',
508 ] );
509
510 $this->add_inline_editing_attributes( $tab_content_setting_key, 'advanced' );
511 ?>
512 <div <?php $this->print_render_attribute_string( $tab_title_mobile_setting_key ); ?>><?php
513 $this->print_unescaped_setting( 'tab_title', 'tabs', $index );
514 ?></div>
515 <div <?php $this->print_render_attribute_string( $tab_content_setting_key ); ?>><?php
516 $this->print_text_editor( $item['tab_content'] );
517 ?></div>
518 <?php endforeach; ?>
519 </div>
520 </div>
521 <?php
522 }
523
524 /**
525 * Render tabs widget output in the editor.
526 *
527 * Written as a Backbone JavaScript template and used to generate the live preview.
528 *
529 * @since 2.9.0
530 * @access protected
531 */
532 protected function content_template() {
533 ?>
534 <div class="elementor-tabs" role="tablist" aria-orientation="vertical">
535 <# if ( settings.tabs ) {
536 var elementUid = view.getIDInt().toString().substr( 0, 3 ); #>
537 <div class="elementor-tabs-wrapper" role="tablist">
538 <# _.each( settings.tabs, function( item, index ) {
539 var tabCount = index + 1,
540 tabUid = elementUid + tabCount,
541 tabTitleKey = 'tab-title-' + tabUid;
542
543 view.addRenderAttribute( tabTitleKey, {
544 'id': 'elementor-tab-title-' + tabUid,
545 'class': [ 'elementor-tab-title','elementor-tab-desktop-title' ],
546 'data-tab': tabCount,
547 'role': 'tab',
548 'tabindex': 1 === tabCount ? '0' : '-1',
549 'aria-controls': 'elementor-tab-content-' + tabUid,
550 'aria-expanded': 'false',
551 } );
552 #>
553 <div {{{ view.getRenderAttributeString( tabTitleKey ) }}}>{{{ item.tab_title }}}</div>
554 <# } ); #>
555 </div>
556 <div class="elementor-tabs-content-wrapper">
557 <# _.each( settings.tabs, function( item, index ) {
558 var tabCount = index + 1,
559 tabContentKey = view.getRepeaterSettingKey( 'tab_content', 'tabs',index );
560
561 view.addRenderAttribute( tabContentKey, {
562 'id': 'elementor-tab-content-' + elementUid + tabCount,
563 'class': [ 'elementor-tab-content', 'elementor-clearfix', 'elementor-repeater-item-' + item._id ],
564 'data-tab': tabCount,
565 'role' : 'tabpanel',
566 'aria-labelledby' : 'elementor-tab-title-' + elementUid + tabCount
567 } );
568
569 view.addInlineEditingAttributes( tabContentKey, 'advanced' ); #>
570 <div class="elementor-tab-title elementor-tab-mobile-title" data-tab="{{ tabCount }}" role="tab">{{{ item.tab_title }}}</div>
571 <div {{{ view.getRenderAttributeString( tabContentKey ) }}}>{{{ item.tab_content }}}</div>
572 <# } ); #>
573 </div>
574 <# } #>
575 </div>
576 <?php
577 }
578 }
579