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 / tabs.php

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

564 lines 14.9 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 __( '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' => __( 'Tabs', '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' => __( 'Tab Title', 'elementor' ),
101 'placeholder' => __( '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' => __( 'Content', 'elementor' ),
113 'default' => __( 'Tab Content', 'elementor' ),
114 'placeholder' => __( 'Tab Content', 'elementor' ),
115 'type' => Controls_Manager::WYSIWYG,
116 'show_label' => false,
117 ]
118 );
119
120 $this->add_control(
121 'tabs',
122 [
123 'label' => __( 'Tabs Items', 'elementor' ),
124 'type' => Controls_Manager::REPEATER,
125 'fields' => $repeater->get_controls(),
126 'default' => [
127 [
128 'tab_title' => __( 'Tab #1', 'elementor' ),
129 'tab_content' => __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
130 ],
131 [
132 'tab_title' => __( 'Tab #2', 'elementor' ),
133 'tab_content' => __( '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' => __( 'View', 'elementor' ),
144 'type' => Controls_Manager::HIDDEN,
145 'default' => 'traditional',
146 ]
147 );
148
149 $this->add_control(
150 'type',
151 [
152 'label' => __( 'Position', 'elementor' ),
153 'type' => Controls_Manager::SELECT,
154 'default' => 'horizontal',
155 'options' => [
156 'horizontal' => __( 'Horizontal', 'elementor' ),
157 'vertical' => __( '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' => __( 'Alignment', 'elementor' ),
168 'type' => Controls_Manager::CHOOSE,
169 'options' => [
170 '' => [
171 'title' => __( 'Start', 'elementor' ),
172 'icon' => 'eicon-h-align-left',
173 ],
174 'center' => [
175 'title' => __( 'Center', 'elementor' ),
176 'icon' => 'eicon-h-align-center',
177 ],
178 'end' => [
179 'title' => __( 'End', 'elementor' ),
180 'icon' => 'eicon-h-align-right',
181 ],
182 'stretch' => [
183 'title' => __( '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' => __( 'Alignment', 'elementor' ),
198 'type' => Controls_Manager::CHOOSE,
199 'options' => [
200 '' => [
201 'title' => __( 'Start', 'elementor' ),
202 'icon' => 'eicon-v-align-top',
203 ],
204 'center' => [
205 'title' => __( 'Center', 'elementor' ),
206 'icon' => 'eicon-v-align-middle',
207 ],
208 'end' => [
209 'title' => __( 'End', 'elementor' ),
210 'icon' => 'eicon-v-align-bottom',
211 ],
212 'stretch' => [
213 'title' => __( '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' => __( 'Tabs', 'elementor' ),
230 'tab' => Controls_Manager::TAB_STYLE,
231 ]
232 );
233
234 $this->add_control(
235 'navigation_width',
236 [
237 'label' => __( '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' => __( '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' => __( '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' => __( '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' => __( 'Title', 'elementor' ),
304 'type' => Controls_Manager::HEADING,
305 'separator' => 'before',
306 ]
307 );
308
309 $this->add_control(
310 'tab_color',
311 [
312 'label' => __( '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' => __( '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_Shadow::get_type(),
351 [
352 'name' => 'title_shadow',
353 'selector' => '{{WRAPPER}} .elementor-tab-title',
354 ]
355 );
356
357 $this->add_control(
358 'title_align',
359 [
360 'label' => __( 'Alignment', 'elementor' ),
361 'type' => Controls_Manager::CHOOSE,
362 'options' => [
363 'left' => [
364 'title' => __( 'Left', 'elementor' ),
365 'icon' => 'eicon-text-align-left',
366 ],
367 'center' => [
368 'title' => __( 'Center', 'elementor' ),
369 'icon' => 'eicon-text-align-center',
370 ],
371 'right' => [
372 'title' => __( 'Right', 'elementor' ),
373 'icon' => 'eicon-text-align-right',
374 ],
375 ],
376 'selectors' => [
377 '{{WRAPPER}} .elementor-tab-title' => 'text-align: {{VALUE}};',
378 ],
379 'condition' => [
380 'tabs_align' => 'stretch',
381 ],
382 ]
383 );
384
385 $this->add_control(
386 'heading_content',
387 [
388 'label' => __( 'Content', 'elementor' ),
389 'type' => Controls_Manager::HEADING,
390 'separator' => 'before',
391 ]
392 );
393
394 $this->add_control(
395 'content_color',
396 [
397 'label' => __( 'Color', 'elementor' ),
398 'type' => Controls_Manager::COLOR,
399 'selectors' => [
400 '{{WRAPPER}} .elementor-tab-content' => 'color: {{VALUE}};',
401 ],
402 'global' => [
403 'default' => Global_Colors::COLOR_TEXT,
404 ],
405 ]
406 );
407
408 $this->add_group_control(
409 Group_Control_Typography::get_type(),
410 [
411 'name' => 'content_typography',
412 'selector' => '{{WRAPPER}} .elementor-tab-content',
413 'global' => [
414 'default' => Global_Typography::TYPOGRAPHY_TEXT,
415 ],
416 ]
417 );
418
419 $this->add_group_control(
420 Group_Control_Text_Shadow::get_type(),
421 [
422 'name' => 'content_shadow',
423 'selector' => '{{WRAPPER}} .elementor-tab-content',
424 ]
425 );
426
427 $this->end_controls_section();
428 }
429
430 /**
431 * Render tabs widget output on the frontend.
432 *
433 * Written in PHP and used to generate the final HTML.
434 *
435 * @since 1.0.0
436 * @access protected
437 */
438 protected function render() {
439 $tabs = $this->get_settings_for_display( 'tabs' );
440
441 $id_int = substr( $this->get_id_int(), 0, 3 );
442
443 $a11y_improvements_experiment = Plugin::$instance->experiments->is_feature_active( 'a11y_improvements' );
444
445 $this->add_render_attribute( 'elementor-tabs', 'class', 'elementor-tabs' );
446
447 ?>
448 <div <?php echo $this->get_render_attribute_string( 'elementor-tabs' ); ?>>
449 <div class="elementor-tabs-wrapper" role="tablist" >
450 <?php
451 foreach ( $tabs as $index => $item ) :
452 $tab_count = $index + 1;
453 $tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
454 $tab_title = $a11y_improvements_experiment ? $item['tab_title'] : '<a href="">' . $item['tab_title'] . '</a>';
455
456 $this->add_render_attribute( $tab_title_setting_key, [
457 'id' => 'elementor-tab-title-' . $id_int . $tab_count,
458 'class' => [ 'elementor-tab-title', 'elementor-tab-desktop-title' ],
459 'aria-selected' => 1 === $tab_count ? 'true' : 'false',
460 'data-tab' => $tab_count,
461 'role' => 'tab',
462 'tabindex' => 1 === $tab_count ? '0' : '-1',
463 'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
464 'aria-expanded' => 'false',
465 ] );
466 ?>
467 <div <?php echo $this->get_render_attribute_string( $tab_title_setting_key ); ?>><?php echo $tab_title; ?></div>
468 <?php endforeach; ?>
469 </div>
470 <div class="elementor-tabs-content-wrapper" role="tablist" aria-orientation="vertical">
471 <?php
472 foreach ( $tabs as $index => $item ) :
473 $tab_count = $index + 1;
474 $hidden = 1 === $tab_count ? 'false' : 'hidden';
475 $tab_content_setting_key = $this->get_repeater_setting_key( 'tab_content', 'tabs', $index );
476
477 $tab_title_mobile_setting_key = $this->get_repeater_setting_key( 'tab_title_mobile', 'tabs', $tab_count );
478
479 $this->add_render_attribute( $tab_content_setting_key, [
480 'id' => 'elementor-tab-content-' . $id_int . $tab_count,
481 'class' => [ 'elementor-tab-content', 'elementor-clearfix' ],
482 'data-tab' => $tab_count,
483 'role' => 'tabpanel',
484 'aria-labelledby' => 'elementor-tab-title-' . $id_int . $tab_count,
485 'tabindex' => '0',
486 'hidden' => $hidden,
487 ] );
488
489 $this->add_render_attribute( $tab_title_mobile_setting_key, [
490 'class' => [ 'elementor-tab-title', 'elementor-tab-mobile-title' ],
491 'aria-selected' => 1 === $tab_count ? 'true' : 'false',
492 'data-tab' => $tab_count,
493 'role' => 'tab',
494 'tabindex' => 1 === $tab_count ? '0' : '-1',
495 'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
496 'aria-expanded' => 'false',
497 ] );
498
499 $this->add_inline_editing_attributes( $tab_content_setting_key, 'advanced' );
500 ?>
501 <div <?php echo $this->get_render_attribute_string( $tab_title_mobile_setting_key ); ?>><?php echo $item['tab_title']; ?></div>
502 <div <?php echo $this->get_render_attribute_string( $tab_content_setting_key ); ?>><?php echo $this->parse_text_editor( $item['tab_content'] ); ?></div>
503 <?php endforeach; ?>
504 </div>
505 </div>
506 <?php
507 }
508
509 /**
510 * Render tabs widget output in the editor.
511 *
512 * Written as a Backbone JavaScript template and used to generate the live preview.
513 *
514 * @since 2.9.0
515 * @access protected
516 */
517 protected function content_template() {
518 ?>
519 <div class="elementor-tabs" role="tablist" aria-orientation="vertical">
520 <# if ( settings.tabs ) {
521 var elementUid = view.getIDInt().toString().substr( 0, 3 ); #>
522 <div class="elementor-tabs-wrapper" role="tablist">
523 <# _.each( settings.tabs, function( item, index ) {
524 var tabCount = index + 1,
525 tabUid = elementUid + tabCount,
526 tabTitleKey = 'tab-title-' + tabUid;
527
528 view.addRenderAttribute( tabTitleKey, {
529 'id': 'elementor-tab-title-' + tabUid,
530 'class': [ 'elementor-tab-title','elementor-tab-desktop-title' ],
531 'data-tab': tabCount,
532 'role': 'tab',
533 'tabindex': 1 === tabCount ? '0' : '-1',
534 'aria-controls': 'elementor-tab-content-' + tabUid,
535 'aria-expanded': 'false',
536 } );
537 #>
538 <div {{{ view.getRenderAttributeString( tabTitleKey ) }}}>{{{ item.tab_title }}}</div>
539 <# } ); #>
540 </div>
541 <div class="elementor-tabs-content-wrapper">
542 <# _.each( settings.tabs, function( item, index ) {
543 var tabCount = index + 1,
544 tabContentKey = view.getRepeaterSettingKey( 'tab_content', 'tabs',index );
545
546 view.addRenderAttribute( tabContentKey, {
547 'id': 'elementor-tab-content-' + elementUid + tabCount,
548 'class': [ 'elementor-tab-content', 'elementor-clearfix', 'elementor-repeater-item-' + item._id ],
549 'data-tab': tabCount,
550 'role' : 'tabpanel',
551 'aria-labelledby' : 'elementor-tab-title-' + elementUid + tabCount
552 } );
553
554 view.addInlineEditingAttributes( tabContentKey, 'advanced' ); #>
555 <div class="elementor-tab-title elementor-tab-mobile-title" data-tab="{{ tabCount }}" role="tab">{{{ item.tab_title }}}</div>
556 <div {{{ view.getRenderAttributeString( tabContentKey ) }}}>{{{ item.tab_content }}}</div>
557 <# } ); #>
558 </div>
559 <# } #>
560 </div>
561 <?php
562 }
563 }
564