PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.3.17
UiCore Elements – Free widgets and templates for Elementor v1.3.17
1.3.17 1.3.16 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 All 41 releases
uicore-elements / includes / widgets / custom-carousel.php

custom-carousel.php in UiCore Elements – Free widgets and templates for Elementor 1.3.17, at includes/widgets/custom-carousel.php

377 lines 12.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace UiCoreElements;
4
5 use Elementor\Plugin;
6 use Elementor\Controls_Manager;
7 use Elementor\Repeater;
8 use Elementor\Modules\NestedElements\Controls\Control_Nested_Repeater;
9 use UiCoreElements\Utils\Carousel_Trait;
10 use UiCoreElements\Utils\Animation_Trait;
11 use UiCoreElements\Utils\Item_Style_Component;
12
13 defined('ABSPATH') || exit();
14
15 /**
16 * Custom Carousel
17 *
18 * @author Lucas Marini Falbo <lucas@uicore.co>
19 * @since 1.0.7
20 */
21
22 class CustomCarousel extends UiCoreNestedWidget
23 {
24
25 use Carousel_Trait;
26 use Animation_Trait;
27 use Item_Style_Component;
28
29 public function get_name()
30 {
31 return 'uicore-custom-carousel';
32 }
33 public function get_title()
34 {
35 return esc_html__('Custom Carousel', 'uicore-elements');
36 }
37 public function get_icon()
38 {
39 return 'eicon-carousel-loop ui-e-widget';
40 }
41 public function get_categories()
42 {
43 return ['uicore'];
44 }
45 public function get_keywords()
46 {
47 return ['slide', 'carousel', 'nested'];
48 }
49 public function get_styles()
50 {
51 $styles = [
52 'custom-carousel',
53 'carousel'
54 ];
55 return $styles;
56 }
57 public function get_scripts()
58 {
59 return $this->TRAIT_get_carousel_scripts(false);
60 }
61 public function has_widget_inner_wrapper(): bool
62 {
63 // TODO: remove after Optmized Markup experiment is merged to the core
64 return ! \Elementor\Plugin::$instance->experiments->is_feature_active('e_optimized_markup');
65 }
66
67 // Nested required functions
68 protected function carousel_content_container(int $index)
69 {
70 return [
71 'elType' => 'container',
72 'settings' => [
73 /* translators: %s: Item number */
74 '_title' => sprintf(esc_html__('Item #%s', 'uicore-elements'), $index),
75 'content_width' => 'full',
76 'flex_justify_content' => 'center',
77 'flex_align_items' => 'center',
78 ],
79 ];
80 }
81 protected function get_default_children_elements()
82 {
83 return [
84 $this->carousel_content_container(1),
85 $this->carousel_content_container(2),
86 $this->carousel_content_container(3),
87 ];
88 }
89 protected function get_default_repeater_title_setting_key()
90 {
91 return 'carousel_item_title';
92 }
93 protected function get_default_children_title()
94 {
95 /* translators: %d: Item number */
96 return esc_html__('Item #%d', 'uicore-elements');
97 }
98 protected function get_default_children_placeholder_selector()
99 {
100 return '.swiper-wrapper';
101 }
102
103 /**
104 * We've set a bool variable to this function because Custom Slider extends this widget and requires one extra control.
105 *
106 * @param bool $is_slider - If the widget is a slider, it will enable the slider height control.
107 */
108 protected function register_controls(bool $is_slider = false)
109 {
110
111 if (!Plugin::$instance->experiments->is_feature_active('nested-elements')) {
112 $this->nesting_fallback('controls');
113 return;
114 }
115
116 $this->start_controls_section(
117 'section_content',
118 [
119 'label' => __('Items', 'uicore-elements'),
120 'tab' => Controls_Manager::TAB_CONTENT,
121 ]
122 );
123
124 $repeater = new Repeater();
125
126 $repeater->add_control(
127 'carousel_item_title',
128 [
129 'label' => __('Title', 'uicore-elements'),
130 'type' => Controls_Manager::TEXT,
131 'render_type' => 'template',
132 'dynamic' => [
133 'active' => true,
134 ],
135 ]
136 );
137
138 $this->add_control(
139 'carousel_items',
140 [
141 'type' => Control_Nested_Repeater::CONTROL_TYPE,
142 'fields' => $repeater->get_controls(),
143 'default' => [
144 ['carousel_item_title' => __('Item #1', 'uicore-elements')],
145 ['carousel_item_title' => __('Item #2', 'uicore-elements')],
146 ['carousel_item_title' => __('Item #3', 'uicore-elements')],
147 ]
148 ]
149 );
150
151 $this->end_controls_section();
152
153 // Additional Carousel Controls
154 $this->start_controls_section(
155 'section_additional_settings',
156 [
157 'label' => __('Additional Settings', 'uicore-elements'),
158 'tab' => Controls_Manager::TAB_CONTENT,
159 ]
160 );
161
162 $this->TRAIT_register_carousel_additional_controls($is_slider); // Carousel Additionals
163
164 $this->end_controls_section();
165
166 $this->start_controls_section(
167 'section_carousel_settings',
168 [
169 'label' => __('Carousel Settings', 'uicore-elements'),
170 ]
171 );
172
173 $this->TRAIT_register_carousel_settings_controls(); // Carousel settings
174
175 $this->end_controls_section();
176
177 $this->TRAIT_register_navigation_controls(); // Navigation settings
178
179 $this->start_controls_section(
180 'section_style_review_items',
181 [
182 'label' => esc_html__('Items', 'uicore-elements'),
183 'tab' => Controls_Manager::TAB_STYLE,
184 ]
185 );
186
187 $this->TRAIT_register_all_item_style_controls();
188
189 $this->end_controls_section();
190
191 $this->TRAIT_register_navigation_style_controls(); // Carousel Navigation Styles
192
193 // Decrease default item padding
194 $this->update_control('item_padding', [
195 'default' => [
196 'top' => 25,
197 'right' => 25,
198 'bottom' => 25,
199 'left' => 25,
200 'unit' => 'px',
201 'isLinked' => true,
202 ],
203 ]);
204
205 // Adds description to loop
206 $this->update_control('loop', [
207 'description' => esc_html__('Loop preview is disabled here on the editor, due to compatibility issues. But you can test on the front-end, since it works outside the editor.', 'uicore-elements'),
208 ]);
209 }
210
211 public function render()
212 {
213 if (Plugin::$instance->experiments->is_feature_active('nested-elements') == false) {
214 $this->nesting_fallback();
215 return;
216 }
217
218 $items = $this->get_settings_for_display('carousel_items');
219 $carousel_items = '';
220
221 $total_slides = count($items);
222 $this->TRAIT_render_center_loop_warning($total_slides);
223
224 foreach ($items as $index => $item) {
225 ob_start();
226 $this->render_item($index);
227 $current_slide = ob_get_clean();
228
229 $carousel_items .= $current_slide;
230 }
231
232 ?>
233 <div class="ui-e-carousel ui-e-nested swiper">
234
235 <div class='swiper-wrapper'>
236 <?php echo $carousel_items; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
237 ?>
238 </div>
239
240 </div>
241
242 <?php $this->TRAIT_render_carousel_navigations($total_slides); ?>
243 <?php
244 }
245
246 public function render_item($index)
247 {
248 ?>
249 <div class="ui-e-wrp swiper-slide" data-hash="<?php echo esc_html($index); ?>">
250 <?php $this->print_child($index); ?>
251 </div>
252 <?php
253 }
254
255 public function print_child($index)
256 {
257 $children = $this->get_children();
258 $child_ids = [];
259
260 if (empty($children) || ! isset($children[$index])) {
261 return;
262 }
263
264 foreach ($children as $child) {
265 $child_ids[] = $child->get_id();
266 }
267
268 add_filter('elementor/frontend/container/should_render', function ($should_render, $container) use ($child_ids) {
269 return $this->add_child_attributes($should_render, $container, $child_ids);
270 }, 10, 3);
271
272 $children[$index]->print_element();
273
274 remove_filter('elementor/frontend/container/should_render', [$this, 'add_child_attributes']);
275 }
276
277 /**
278 * Adds attributes to child elements containers.
279 */
280 protected function add_child_attributes($should_render, $container, $child_ids, $classnames = ['ui-e-item'])
281 {
282
283 // custom cases may be added here
284
285 if (in_array($container->get_id(), $child_ids)) {
286 $container->add_render_attribute('_wrapper', [
287 'class' => $classnames,
288 ]);
289 }
290
291 return $should_render;
292 }
293
294 protected function get_initial_config(): array
295 {
296 if (Plugin::$instance->experiments->is_feature_active('e_nested_atomic_repeaters')) {
297 return array_merge(parent::get_initial_config(), [
298 'support_improved_repeaters' => true,
299 'node' => 'button',
300 ]);
301 }
302
303 return parent::get_initial_config();
304 }
305
306 protected function content_template()
307 {
308
309 if (Plugin::$instance->experiments->is_feature_active('nested-elements') == false) {
310 return;
311 }
312
313 ?>
314 <#
315 var carouselItems=settings.carousel_items || [],
316 hideNavigation=settings.animation_style && settings.animation_style.includes('marquee'),
317 navigationDots=settings.navigation && settings.navigation.includes('dots') && !hideNavigation,
318 navigationArrows=settings.navigation && settings.navigation.includes('arrows') && !hideNavigation,
319 navigationFraction=settings.navigation && settings.navigation.includes('fraction') && !hideNavigation,
320 totalSlides=carouselItems.length,
321 perView=parseInt(settings.slides_per_view, 10) || 0,
322 needsCenterLoopWarning=settings.center_slides &&
323 settings.loop &&
324 perView % 2===0 &&
325 totalSlides < (perView + 2),
326 missingSlides=(perView + 2) - totalSlides;
327
328 var prev=elementor.helpers.renderIcon(view, settings.previous_arrow, { 'aria-hidden' : true }, 'i' , 'object' ),
329 next=elementor.helpers.renderIcon(view, settings.next_arrow, { 'aria-hidden' : true }, 'i' , 'object' );
330 #>
331
332 <# if ( needsCenterLoopWarning ) { #>
333 <div style="background: red; mix-blend-mode: difference; padding: 15px; border-radius: 5px;">
334 <span style="color: white; font-size: 1.2em; font-weight: bold;">
335 <?php echo esc_html__('Warning', 'uicore-elements'); ?>
336 </span>
337
338 <p style="color: white; margin-bottom: 0px;">
339 <?php echo esc_html__('You enabled centered slides, loop, and have an even number of slides per view', 'uicore-elements'); ?>
340 ({{{ perView }}} <?php echo esc_html__('slides per view', 'uicore-elements'); ?>).
341 <?php echo esc_html__('For this configuration to work properly, you need to have', 'uicore-elements'); ?>
342 {{{ missingSlides }}}
343 <?php echo esc_html__('more slide(s) or disable one of the mentioned features.', 'uicore-elements'); ?>
344 </p>
345 </div>
346 <# } #>
347
348 <div class="ui-e-carousel ui-e-nested swiper {{ elementorFrontend.config.swiperClass }}">
349 <div class='swiper-wrapper'> </div>
350 </div>
351
352 <# if ( navigationDots ) { #>
353 <div class="swiper-pagination ui-e-dots ui-e-carousel-dots"></div>
354 <# } #>
355
356 <# if ( navigationArrows ) { #>
357 <div class="ui-e-button ui-e-carousel-button ui-e-previous" role="button" aria-label="Previous slide">
358 {{{ prev.value }}}
359 </div>
360 <div class="ui-e-button ui-e-carousel-button ui-e-next" role="button" aria-label="Next slide">
361 {{{ next.value }}}
362 </div>
363 <# } #>
364
365 <# if ( navigationFraction ) { #>
366 <div class="ui-e-fraction ui-e-carousel-fraction">
367 <span class="ui-e-current"></span>
368 /
369 <span class="ui-e-total"></span>
370 </div>
371 <# } #>
372 <?php
373 }
374 }
375
376 \Elementor\Plugin::instance()->widgets_manager->register(new CustomCarousel());
377