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 / image-carousel.php

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

910 lines 21.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
10 /**
11 * Elementor image carousel widget.
12 *
13 * Elementor widget that displays a set of images in a rotating carousel or
14 * slider.
15 *
16 * @since 1.0.0
17 */
18 class Widget_Image_Carousel extends Widget_Base {
19
20 /**
21 * Get widget name.
22 *
23 * Retrieve image carousel 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 'image-carousel';
32 }
33
34 /**
35 * Get widget title.
36 *
37 * Retrieve image carousel 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 esc_html__( 'Image Carousel', 'elementor' );
46 }
47
48 /**
49 * Get widget icon.
50 *
51 * Retrieve image carousel 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-slider-push';
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 [ 'image', 'photo', 'visual', 'carousel', 'slider' ];
74 }
75
76 /**
77 * Register image carousel 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_image_carousel',
87 [
88 'label' => esc_html__( 'Image Carousel', 'elementor' ),
89 ]
90 );
91
92 $this->add_control(
93 'carousel',
94 [
95 'label' => esc_html__( 'Add Images', 'elementor' ),
96 'type' => Controls_Manager::GALLERY,
97 'default' => [],
98 'show_label' => false,
99 'dynamic' => [
100 'active' => true,
101 ],
102 ]
103 );
104
105 $this->add_group_control(
106 Group_Control_Image_Size::get_type(),
107 [
108 'name' => 'thumbnail', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `thumbnail_size` and `thumbnail_custom_dimension`.
109 'separator' => 'none',
110 ]
111 );
112
113 $slides_to_show = range( 1, 10 );
114 $slides_to_show = array_combine( $slides_to_show, $slides_to_show );
115
116 $this->add_responsive_control(
117 'slides_to_show',
118 [
119 'label' => esc_html__( 'Slides to Show', 'elementor' ),
120 'type' => Controls_Manager::SELECT,
121 'options' => [
122 '' => esc_html__( 'Default', 'elementor' ),
123 ] + $slides_to_show,
124 'frontend_available' => true,
125 'render_type' => 'template',
126 'selectors' => [
127 '{{WRAPPER}}' => '--e-image-carousel-slides-to-show: {{VALUE}}',
128 ],
129 ]
130 );
131
132 $this->add_responsive_control(
133 'slides_to_scroll',
134 [
135 'label' => esc_html__( 'Slides to Scroll', 'elementor' ),
136 'type' => Controls_Manager::SELECT,
137 'description' => esc_html__( 'Set how many slides are scrolled per swipe.', 'elementor' ),
138 'options' => [
139 '' => esc_html__( 'Default', 'elementor' ),
140 ] + $slides_to_show,
141 'condition' => [
142 'slides_to_show!' => '1',
143 ],
144 'frontend_available' => true,
145 ]
146 );
147
148 $this->add_control(
149 'image_stretch',
150 [
151 'label' => esc_html__( 'Image Stretch', 'elementor' ),
152 'type' => Controls_Manager::SELECT,
153 'default' => 'no',
154 'options' => [
155 'no' => esc_html__( 'No', 'elementor' ),
156 'yes' => esc_html__( 'Yes', 'elementor' ),
157 ],
158 ]
159 );
160
161 $this->add_control(
162 'navigation',
163 [
164 'label' => esc_html__( 'Navigation', 'elementor' ),
165 'type' => Controls_Manager::SELECT,
166 'default' => 'both',
167 'options' => [
168 'both' => esc_html__( 'Arrows and Dots', 'elementor' ),
169 'arrows' => esc_html__( 'Arrows', 'elementor' ),
170 'dots' => esc_html__( 'Dots', 'elementor' ),
171 'none' => esc_html__( 'None', 'elementor' ),
172 ],
173 'frontend_available' => true,
174 ]
175 );
176
177 $this->add_control(
178 'link_to',
179 [
180 'label' => esc_html__( 'Link', 'elementor' ),
181 'type' => Controls_Manager::SELECT,
182 'default' => 'none',
183 'options' => [
184 'none' => esc_html__( 'None', 'elementor' ),
185 'file' => esc_html__( 'Media File', 'elementor' ),
186 'custom' => esc_html__( 'Custom URL', 'elementor' ),
187 ],
188 ]
189 );
190
191 $this->add_control(
192 'link',
193 [
194 'label' => esc_html__( 'Link', 'elementor' ),
195 'type' => Controls_Manager::URL,
196 'placeholder' => esc_html__( 'https://your-link.com', 'elementor' ),
197 'condition' => [
198 'link_to' => 'custom',
199 ],
200 'show_label' => false,
201 'dynamic' => [
202 'active' => true,
203 ],
204 ]
205 );
206
207 $this->add_control(
208 'open_lightbox',
209 [
210 'label' => esc_html__( 'Lightbox', 'elementor' ),
211 'type' => Controls_Manager::SELECT,
212 'default' => 'default',
213 'options' => [
214 'default' => esc_html__( 'Default', 'elementor' ),
215 'yes' => esc_html__( 'Yes', 'elementor' ),
216 'no' => esc_html__( 'No', 'elementor' ),
217 ],
218 'condition' => [
219 'link_to' => 'file',
220 ],
221 ]
222 );
223
224 $this->add_control(
225 'caption_type',
226 [
227 'label' => esc_html__( 'Caption', 'elementor' ),
228 'type' => Controls_Manager::SELECT,
229 'default' => '',
230 'options' => [
231 '' => esc_html__( 'None', 'elementor' ),
232 'title' => esc_html__( 'Title', 'elementor' ),
233 'caption' => esc_html__( 'Caption', 'elementor' ),
234 'description' => esc_html__( 'Description', 'elementor' ),
235 ],
236 ]
237 );
238
239 $this->add_control(
240 'view',
241 [
242 'label' => esc_html__( 'View', 'elementor' ),
243 'type' => Controls_Manager::HIDDEN,
244 'default' => 'traditional',
245 ]
246 );
247
248 $this->end_controls_section();
249
250 $this->start_controls_section(
251 'section_additional_options',
252 [
253 'label' => esc_html__( 'Additional Options', 'elementor' ),
254 ]
255 );
256
257 $this->add_control(
258 'lazyload',
259 [
260 'label' => esc_html__( 'Lazyload', 'elementor' ),
261 'type' => Controls_Manager::SWITCHER,
262 'frontend_available' => true,
263 ]
264 );
265
266 $this->add_control(
267 'autoplay',
268 [
269 'label' => esc_html__( 'Autoplay', 'elementor' ),
270 'type' => Controls_Manager::SELECT,
271 'default' => 'yes',
272 'options' => [
273 'yes' => esc_html__( 'Yes', 'elementor' ),
274 'no' => esc_html__( 'No', 'elementor' ),
275 ],
276 'frontend_available' => true,
277 ]
278 );
279
280 $this->add_control(
281 'pause_on_hover',
282 [
283 'label' => esc_html__( 'Pause on Hover', 'elementor' ),
284 'type' => Controls_Manager::SELECT,
285 'default' => 'yes',
286 'options' => [
287 'yes' => esc_html__( 'Yes', 'elementor' ),
288 'no' => esc_html__( 'No', 'elementor' ),
289 ],
290 'condition' => [
291 'autoplay' => 'yes',
292 ],
293 'render_type' => 'none',
294 'frontend_available' => true,
295 ]
296 );
297
298 $this->add_control(
299 'pause_on_interaction',
300 [
301 'label' => esc_html__( 'Pause on Interaction', 'elementor' ),
302 'type' => Controls_Manager::SELECT,
303 'default' => 'yes',
304 'options' => [
305 'yes' => esc_html__( 'Yes', 'elementor' ),
306 'no' => esc_html__( 'No', 'elementor' ),
307 ],
308 'condition' => [
309 'autoplay' => 'yes',
310 ],
311 'frontend_available' => true,
312 ]
313 );
314
315 $this->add_control(
316 'autoplay_speed',
317 [
318 'label' => esc_html__( 'Autoplay Speed', 'elementor' ),
319 'type' => Controls_Manager::NUMBER,
320 'default' => 5000,
321 'condition' => [
322 'autoplay' => 'yes',
323 ],
324 'render_type' => 'none',
325 'frontend_available' => true,
326 ]
327 );
328
329 // Loop requires a re-render so no 'render_type = none'
330 $this->add_control(
331 'infinite',
332 [
333 'label' => esc_html__( 'Infinite Loop', 'elementor' ),
334 'type' => Controls_Manager::SELECT,
335 'default' => 'yes',
336 'options' => [
337 'yes' => esc_html__( 'Yes', 'elementor' ),
338 'no' => esc_html__( 'No', 'elementor' ),
339 ],
340 'frontend_available' => true,
341 ]
342 );
343
344 $this->add_control(
345 'effect',
346 [
347 'label' => esc_html__( 'Effect', 'elementor' ),
348 'type' => Controls_Manager::SELECT,
349 'default' => 'slide',
350 'options' => [
351 'slide' => esc_html__( 'Slide', 'elementor' ),
352 'fade' => esc_html__( 'Fade', 'elementor' ),
353 ],
354 'condition' => [
355 'slides_to_show' => '1',
356 ],
357 'frontend_available' => true,
358 ]
359 );
360
361 $this->add_control(
362 'speed',
363 [
364 'label' => esc_html__( 'Animation Speed', 'elementor' ),
365 'type' => Controls_Manager::NUMBER,
366 'default' => 500,
367 'render_type' => 'none',
368 'frontend_available' => true,
369 ]
370 );
371
372 $this->add_control(
373 'direction',
374 [
375 'label' => esc_html__( 'Direction', 'elementor' ),
376 'type' => Controls_Manager::SELECT,
377 'default' => 'ltr',
378 'options' => [
379 'ltr' => esc_html__( 'Left', 'elementor' ),
380 'rtl' => esc_html__( 'Right', 'elementor' ),
381 ],
382 ]
383 );
384
385 $this->end_controls_section();
386
387 $this->start_controls_section(
388 'section_style_navigation',
389 [
390 'label' => esc_html__( 'Navigation', 'elementor' ),
391 'tab' => Controls_Manager::TAB_STYLE,
392 'condition' => [
393 'navigation' => [ 'arrows', 'dots', 'both' ],
394 ],
395 ]
396 );
397
398 $this->add_control(
399 'heading_style_arrows',
400 [
401 'label' => esc_html__( 'Arrows', 'elementor' ),
402 'type' => Controls_Manager::HEADING,
403 'separator' => 'before',
404 'condition' => [
405 'navigation' => [ 'arrows', 'both' ],
406 ],
407 ]
408 );
409
410 $this->add_control(
411 'arrows_position',
412 [
413 'label' => esc_html__( 'Position', 'elementor' ),
414 'type' => Controls_Manager::SELECT,
415 'default' => 'inside',
416 'options' => [
417 'inside' => esc_html__( 'Inside', 'elementor' ),
418 'outside' => esc_html__( 'Outside', 'elementor' ),
419 ],
420 'prefix_class' => 'elementor-arrows-position-',
421 'condition' => [
422 'navigation' => [ 'arrows', 'both' ],
423 ],
424 ]
425 );
426
427 $this->add_control(
428 'arrows_size',
429 [
430 'label' => esc_html__( 'Size', 'elementor' ),
431 'type' => Controls_Manager::SLIDER,
432 'range' => [
433 'px' => [
434 'min' => 20,
435 'max' => 60,
436 ],
437 ],
438 'selectors' => [
439 '{{WRAPPER}} .elementor-swiper-button.elementor-swiper-button-prev, {{WRAPPER}} .elementor-swiper-button.elementor-swiper-button-next' => 'font-size: {{SIZE}}{{UNIT}};',
440 ],
441 'condition' => [
442 'navigation' => [ 'arrows', 'both' ],
443 ],
444 ]
445 );
446
447 $this->add_control(
448 'arrows_color',
449 [
450 'label' => esc_html__( 'Color', 'elementor' ),
451 'type' => Controls_Manager::COLOR,
452 'selectors' => [
453 '{{WRAPPER}} .elementor-swiper-button.elementor-swiper-button-prev, {{WRAPPER}} .elementor-swiper-button.elementor-swiper-button-next' => 'color: {{VALUE}};',
454 '{{WRAPPER}} .elementor-swiper-button.elementor-swiper-button-prev svg, {{WRAPPER}} .elementor-swiper-button.elementor-swiper-button-next svg' => 'fill: {{VALUE}};',
455 ],
456 'condition' => [
457 'navigation' => [ 'arrows', 'both' ],
458 ],
459 ]
460 );
461
462 $this->add_control(
463 'heading_style_dots',
464 [
465 'label' => esc_html__( 'Pagination', 'elementor' ),
466 'type' => Controls_Manager::HEADING,
467 'separator' => 'before',
468 'condition' => [
469 'navigation' => [ 'dots', 'both' ],
470 ],
471 ]
472 );
473
474 $this->add_control(
475 'dots_position',
476 [
477 'label' => esc_html__( 'Position', 'elementor' ),
478 'type' => Controls_Manager::SELECT,
479 'default' => 'outside',
480 'options' => [
481 'outside' => esc_html__( 'Outside', 'elementor' ),
482 'inside' => esc_html__( 'Inside', 'elementor' ),
483 ],
484 'prefix_class' => 'elementor-pagination-position-',
485 'condition' => [
486 'navigation' => [ 'dots', 'both' ],
487 ],
488 ]
489 );
490
491 $this->add_control(
492 'dots_size',
493 [
494 'label' => esc_html__( 'Size', 'elementor' ),
495 'type' => Controls_Manager::SLIDER,
496 'range' => [
497 'px' => [
498 'min' => 5,
499 'max' => 10,
500 ],
501 ],
502 'selectors' => [
503 '{{WRAPPER}} .swiper-pagination-bullet' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
504 ],
505 'condition' => [
506 'navigation' => [ 'dots', 'both' ],
507 ],
508 ]
509 );
510
511 $this->add_control(
512 'dots_inactive_color',
513 [
514 'label' => esc_html__( 'Color', 'elementor' ),
515 'type' => Controls_Manager::COLOR,
516 'selectors' => [
517 // The opacity property will override the default inactive dot color which is opacity 0.2.
518 '{{WRAPPER}} .swiper-pagination-bullet:not(.swiper-pagination-bullet-active)' => 'background: {{VALUE}}; opacity: 1',
519 ],
520 'condition' => [
521 'navigation' => [ 'dots', 'both' ],
522 ],
523 ]
524 );
525
526 $this->add_control(
527 'dots_color',
528 [
529 'label' => esc_html__( 'Active Color', 'elementor' ),
530 'type' => Controls_Manager::COLOR,
531 'selectors' => [
532 '{{WRAPPER}} .swiper-pagination-bullet' => 'background: {{VALUE}};',
533 ],
534 'condition' => [
535 'navigation' => [ 'dots', 'both' ],
536 ],
537 ]
538 );
539
540 $this->end_controls_section();
541
542 $this->start_controls_section(
543 'section_style_image',
544 [
545 'label' => esc_html__( 'Image', 'elementor' ),
546 'tab' => Controls_Manager::TAB_STYLE,
547 ]
548 );
549
550 $this->add_responsive_control(
551 'gallery_vertical_align',
552 [
553 'label' => esc_html__( 'Vertical Align', 'elementor' ),
554 'type' => Controls_Manager::CHOOSE,
555 'options' => [
556 'flex-start' => [
557 'title' => esc_html__( 'Start', 'elementor' ),
558 'icon' => 'eicon-v-align-top',
559 ],
560 'center' => [
561 'title' => esc_html__( 'Center', 'elementor' ),
562 'icon' => 'eicon-v-align-middle',
563 ],
564 'flex-end' => [
565 'title' => esc_html__( 'End', 'elementor' ),
566 'icon' => 'eicon-v-align-bottom',
567 ],
568 ],
569 'condition' => [
570 'slides_to_show!' => '1',
571 ],
572 'selectors' => [
573 '{{WRAPPER}} .swiper-wrapper' => 'display: flex; align-items: {{VALUE}};',
574 ],
575 ]
576 );
577
578 $this->add_control(
579 'image_spacing',
580 [
581 'label' => esc_html__( 'Spacing', 'elementor' ),
582 'type' => Controls_Manager::SELECT,
583 'options' => [
584 '' => esc_html__( 'Default', 'elementor' ),
585 'custom' => esc_html__( 'Custom', 'elementor' ),
586 ],
587 'default' => '',
588 'condition' => [
589 'slides_to_show!' => '1',
590 ],
591 ]
592 );
593
594 $this->add_control(
595 'image_spacing_custom',
596 [
597 'label' => esc_html__( 'Image Spacing', 'elementor' ),
598 'type' => Controls_Manager::SLIDER,
599 'range' => [
600 'px' => [
601 'max' => 100,
602 ],
603 ],
604 'default' => [
605 'size' => 20,
606 ],
607 'show_label' => false,
608 'condition' => [
609 'image_spacing' => 'custom',
610 'slides_to_show!' => '1',
611 ],
612 'frontend_available' => true,
613 'render_type' => 'none',
614 'separator' => 'after',
615 ]
616 );
617
618 $this->add_group_control(
619 Group_Control_Border::get_type(),
620 [
621 'name' => 'image_border',
622 'selector' => '{{WRAPPER}} .elementor-image-carousel-wrapper .elementor-image-carousel .swiper-slide-image',
623 ]
624 );
625
626 $this->add_control(
627 'image_border_radius',
628 [
629 'label' => esc_html__( 'Border Radius', 'elementor' ),
630 'type' => Controls_Manager::DIMENSIONS,
631 'size_units' => [ 'px', '%' ],
632 'selectors' => [
633 '{{WRAPPER}} .elementor-image-carousel-wrapper .elementor-image-carousel .swiper-slide-image' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
634 ],
635 ]
636 );
637
638 $this->end_controls_section();
639
640 $this->start_controls_section(
641 'section_caption',
642 [
643 'label' => esc_html__( 'Caption', 'elementor' ),
644 'tab' => Controls_Manager::TAB_STYLE,
645 'condition' => [
646 'caption_type!' => '',
647 ],
648 ]
649 );
650
651 $this->add_control(
652 'caption_align',
653 [
654 'label' => esc_html__( 'Alignment', 'elementor' ),
655 'type' => Controls_Manager::CHOOSE,
656 'options' => [
657 'left' => [
658 'title' => esc_html__( 'Left', 'elementor' ),
659 'icon' => 'eicon-text-align-left',
660 ],
661 'center' => [
662 'title' => esc_html__( 'Center', 'elementor' ),
663 'icon' => 'eicon-text-align-center',
664 ],
665 'right' => [
666 'title' => esc_html__( 'Right', 'elementor' ),
667 'icon' => 'eicon-text-align-right',
668 ],
669 'justify' => [
670 'title' => esc_html__( 'Justified', 'elementor' ),
671 'icon' => 'eicon-text-align-justify',
672 ],
673 ],
674 'default' => 'center',
675 'selectors' => [
676 '{{WRAPPER}} .elementor-image-carousel-caption' => 'text-align: {{VALUE}};',
677 ],
678 ]
679 );
680
681 $this->add_control(
682 'caption_text_color',
683 [
684 'label' => esc_html__( 'Text Color', 'elementor' ),
685 'type' => Controls_Manager::COLOR,
686 'default' => '',
687 'selectors' => [
688 '{{WRAPPER}} .elementor-image-carousel-caption' => 'color: {{VALUE}};',
689 ],
690 ]
691 );
692
693 $this->add_group_control(
694 Group_Control_Typography::get_type(),
695 [
696 'name' => 'caption_typography',
697 'global' => [
698 'default' => Global_Colors::COLOR_ACCENT,
699 ],
700 'selector' => '{{WRAPPER}} .elementor-image-carousel-caption',
701 ]
702 );
703
704 $this->add_group_control(
705 Group_Control_Text_Shadow::get_type(),
706 [
707 'name' => 'caption_shadow',
708 'selector' => '{{WRAPPER}} .elementor-image-carousel-caption',
709 ]
710 );
711
712 $this->end_controls_section();
713
714 }
715
716 /**
717 * Render image carousel widget output on the frontend.
718 *
719 * Written in PHP and used to generate the final HTML.
720 *
721 * @since 1.0.0
722 * @access protected
723 */
724 protected function render() {
725 $settings = $this->get_settings_for_display();
726
727 $lazyload = 'yes' === $settings['lazyload'];
728
729 if ( empty( $settings['carousel'] ) ) {
730 return;
731 }
732
733 $slides = [];
734
735 foreach ( $settings['carousel'] as $index => $attachment ) {
736 $image_url = Group_Control_Image_Size::get_attachment_image_src( $attachment['id'], 'thumbnail', $settings );
737
738 if ( ! $image_url && isset( $attachment['url'] ) ) {
739 $image_url = $attachment['url'];
740 }
741
742 if ( $lazyload ) {
743 $image_html = '<img class="swiper-slide-image swiper-lazy" data-src="' . esc_attr( $image_url ) . '" alt="' . esc_attr( Control_Media::get_image_alt( $attachment ) ) . '" />';
744 } else {
745 $image_html = '<img class="swiper-slide-image" src="' . esc_attr( $image_url ) . '" alt="' . esc_attr( Control_Media::get_image_alt( $attachment ) ) . '" />';
746 }
747
748 $link_tag = '';
749
750 $link = $this->get_link_url( $attachment, $settings );
751
752 if ( $link ) {
753 $link_key = 'link_' . $index;
754
755 $this->add_lightbox_data_attributes( $link_key, $attachment['id'], $settings['open_lightbox'], $this->get_id() );
756
757 if ( Plugin::$instance->editor->is_edit_mode() ) {
758 $this->add_render_attribute( $link_key, [
759 'class' => 'elementor-clickable',
760 ] );
761 }
762
763 $this->add_link_attributes( $link_key, $link );
764
765 $link_tag = '<a ' . $this->get_render_attribute_string( $link_key ) . '>';
766 }
767
768 $image_caption = $this->get_image_caption( $attachment );
769
770 $slide_html = '<div class="swiper-slide">' . $link_tag . '<figure class="swiper-slide-inner">' . $image_html;
771
772 if ( $lazyload ) {
773 $slide_html .= '<div class="swiper-lazy-preloader"></div>';
774 }
775
776 if ( ! empty( $image_caption ) ) {
777 $slide_html .= '<figcaption class="elementor-image-carousel-caption">' . wp_kses_post( $image_caption ) . '</figcaption>';
778 }
779
780 $slide_html .= '</figure>';
781
782 if ( $link ) {
783 $slide_html .= '</a>';
784 }
785
786 $slide_html .= '</div>';
787
788 $slides[] = $slide_html;
789
790 }
791
792 if ( empty( $slides ) ) {
793 return;
794 }
795
796 $this->add_render_attribute( [
797 'carousel' => [
798 'class' => 'elementor-image-carousel swiper-wrapper',
799 ],
800 'carousel-wrapper' => [
801 'class' => 'elementor-image-carousel-wrapper swiper-container',
802 'dir' => $settings['direction'],
803 ],
804 ] );
805
806 $show_dots = ( in_array( $settings['navigation'], [ 'dots', 'both' ] ) );
807 $show_arrows = ( in_array( $settings['navigation'], [ 'arrows', 'both' ] ) );
808
809 if ( 'yes' === $settings['image_stretch'] ) {
810 $this->add_render_attribute( 'carousel', 'class', 'swiper-image-stretch' );
811 }
812
813 $slides_count = count( $settings['carousel'] );
814
815 ?>
816 <div <?php $this->print_render_attribute_string( 'carousel-wrapper' ); ?>>
817 <div <?php $this->print_render_attribute_string( 'carousel' ); ?>>
818 <?php // PHPCS - $slides contains the slides content, all the relevent content is escaped above. ?>
819 <?php echo implode( '', $slides ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
820 </div>
821 <?php if ( 1 < $slides_count ) : ?>
822 <?php if ( $show_dots ) : ?>
823 <div class="swiper-pagination"></div>
824 <?php endif; ?>
825 <?php if ( $show_arrows ) : ?>
826 <div class="elementor-swiper-button elementor-swiper-button-prev">
827 <?php $this->render_swiper_button( 'previous' ); ?>
828 <span class="elementor-screen-only"><?php echo esc_html__( 'Previous', 'elementor' ); ?></span>
829 </div>
830 <div class="elementor-swiper-button elementor-swiper-button-next">
831 <?php $this->render_swiper_button( 'next' ); ?>
832 <span class="elementor-screen-only"><?php echo esc_html__( 'Next', 'elementor' ); ?></span>
833 </div>
834 <?php endif; ?>
835 <?php endif; ?>
836 </div>
837 <?php
838 }
839
840 /**
841 * Retrieve image carousel link URL.
842 *
843 * @since 1.0.0
844 * @access private
845 *
846 * @param array $attachment
847 * @param object $instance
848 *
849 * @return array|string|false An array/string containing the attachment URL, or false if no link.
850 */
851 private function get_link_url( $attachment, $instance ) {
852 if ( 'none' === $instance['link_to'] ) {
853 return false;
854 }
855
856 if ( 'custom' === $instance['link_to'] ) {
857 if ( empty( $instance['link']['url'] ) ) {
858 return false;
859 }
860
861 return $instance['link'];
862 }
863
864 return [
865 'url' => wp_get_attachment_url( $attachment['id'] ),
866 ];
867 }
868
869 /**
870 * Retrieve image carousel caption.
871 *
872 * @since 1.2.0
873 * @access private
874 *
875 * @param array $attachment
876 *
877 * @return string The caption of the image.
878 */
879 private function get_image_caption( $attachment ) {
880 $caption_type = $this->get_settings_for_display( 'caption_type' );
881
882 if ( empty( $caption_type ) ) {
883 return '';
884 }
885
886 $attachment_post = get_post( $attachment['id'] );
887
888 if ( 'caption' === $caption_type ) {
889 return $attachment_post->post_excerpt;
890 }
891
892 if ( 'title' === $caption_type ) {
893 return $attachment_post->post_title;
894 }
895
896 return $attachment_post->post_content;
897 }
898
899 private function render_swiper_button( $type ) {
900 $direction = 'next' === $type ? 'right' : 'left';
901
902 $icon_value = 'eicon-chevron-' . $direction;
903
904 Icons_Manager::render_icon( [
905 'library' => 'eicons',
906 'value' => $icon_value,
907 ], [ 'aria-hidden' => 'true' ] );
908 }
909 }
910