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
← All changes | includes/widgets/custom-carousel.php +215 -153 1.0.151.3.17 View file →
@@ -1,6 +1,8 @@
1 1 <?php
2 +
2 3 namespace UiCoreElements;
4 +
3 5 use Elementor\Plugin;
4 6 use Elementor\Controls_Manager;
5 7 use Elementor\Repeater;
6 8 use Elementor\Modules\NestedElements\Controls\Control_Nested_Repeater;
@@ -16,9 +18,10 @@
16 18 * @author Lucas Marini Falbo <lucas@uicore.co>
17 19 * @since 1.0.7
18 20 */
19 21
20 -class CustomCarousel extends UiCoreNestedWidget {
22 +class CustomCarousel extends UiCoreNestedWidget
23 +{
21 24
22 25 use Carousel_Trait;
23 26 use Animation_Trait;
24 27 use Item_Style_Component;
@@ -54,37 +57,49 @@
54 57 public function get_scripts()
55 58 {
56 59 return $this->TRAIT_get_carousel_scripts(false);
57 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 + }
58 66
59 67 // Nested required functions
60 - protected function carousel_content_container( int $index ) {
61 - return [
62 - 'elType' => 'container',
63 - 'settings' => [
64 - '_title' => sprintf( __( 'Item #%s', 'uicore-elements' ), $index ),
65 - 'content_width' => 'full',
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',
66 76 'flex_justify_content' => 'center',
67 77 'flex_align_items' => 'center',
68 - ],
69 - ];
70 - }
71 - protected function get_default_children_elements() {
72 - return [
73 - $this->carousel_content_container( 1 ),
74 - $this->carousel_content_container( 2 ),
75 - $this->carousel_content_container( 3 ),
76 - ];
77 - }
78 - protected function get_default_repeater_title_setting_key() {
79 - return 'carousel_item_title';
80 - }
81 - protected function get_default_children_title() {
82 - return esc_html__( 'Item #%d', 'uicore-elements' );
83 - }
84 - protected function get_default_children_placeholder_selector() {
85 - return '.swiper-wrapper';
86 - }
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 + }
87 102
88 103 /**
89 104 * We've set a bool variable to this function because Custom Slider extends this widget and requires one extra control.
90 105 *
@@ -92,12 +107,12 @@
92 107 */
93 108 protected function register_controls(bool $is_slider = false)
94 109 {
95 110
96 - if( !Plugin::$instance->experiments->is_feature_active('nested-elements') ){
97 - $this->nesting_fallback('controls');
98 - return;
99 - }
111 + if (!Plugin::$instance->experiments->is_feature_active('nested-elements')) {
112 + $this->nesting_fallback('controls');
113 + return;
114 + }
100 115
101 116 $this->start_controls_section(
102 117 'section_content',
103 118 [
@@ -105,34 +120,34 @@
105 120 'tab' => Controls_Manager::TAB_CONTENT,
106 121 ]
107 122 );
108 123
109 - $repeater = new Repeater();
124 + $repeater = new Repeater();
110 125
111 - $repeater->add_control(
112 - 'carousel_item_title',
113 - [
114 - 'label' => __('Title', 'uicore-elements'),
115 - 'type' => Controls_Manager::TEXT,
116 - 'render_type' => 'template',
117 - 'dynamic' => [
118 - 'active' => true,
119 - ],
120 - ]
121 - );
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 + );
122 137
123 - $this->add_control(
124 - 'carousel_items',
125 - [
126 - 'type' => Control_Nested_Repeater::CONTROL_TYPE,
127 - 'fields' => $repeater->get_controls(),
128 - 'default' => [
129 - [ 'carousel_item_title' => __( 'Item #1', 'uicore-elements' ) ],
130 - [ 'carousel_item_title' => __( 'Item #2', 'uicore-elements' ) ],
131 - [ 'carousel_item_title' => __( 'Item #3', 'uicore-elements' ) ],
132 - ]
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')],
133 147 ]
134 - );
148 + ]
149 + );
135 150
136 151 $this->end_controls_section();
137 152
138 153 // Additional Carousel Controls
@@ -143,20 +158,20 @@
143 158 'tab' => Controls_Manager::TAB_CONTENT,
144 159 ]
145 160 );
146 161
147 - $this->TRAIT_register_carousel_additional_controls($is_slider); // Carousel Additionals
162 + $this->TRAIT_register_carousel_additional_controls($is_slider); // Carousel Additionals
148 163
149 164 $this->end_controls_section();
150 165
151 166 $this->start_controls_section(
152 - 'section_carousel_settings',
153 - [
154 - 'label' => __('Carousel Settings', 'uicore-elements'),
155 - ]
156 - );
167 + 'section_carousel_settings',
168 + [
169 + 'label' => __('Carousel Settings', 'uicore-elements'),
170 + ]
171 + );
157 172
158 - $this->TRAIT_register_carousel_settings_controls(); // Carousel settings
173 + $this->TRAIT_register_carousel_settings_controls(); // Carousel settings
159 174
160 175 $this->end_controls_section();
161 176
162 177 $this->TRAIT_register_navigation_controls(); // Navigation settings
@@ -161,16 +176,16 @@
161 176
162 177 $this->TRAIT_register_navigation_controls(); // Navigation settings
163 178
164 179 $this->start_controls_section(
165 - 'section_style_review_items',
166 - [
167 - 'label' => esc_html__( 'Items', 'uicore-elements' ),
168 - 'tab' => Controls_Manager::TAB_STYLE,
169 - ]
170 - );
180 + 'section_style_review_items',
181 + [
182 + 'label' => esc_html__('Items', 'uicore-elements'),
183 + 'tab' => Controls_Manager::TAB_STYLE,
184 + ]
185 + );
171 186
172 - $this->TRAIT_register_all_item_style_controls();
187 + $this->TRAIT_register_all_item_style_controls();
173 188
174 189 $this->end_controls_section();
175 190
176 191 $this->TRAIT_register_navigation_style_controls(); // Carousel Navigation Styles
@@ -190,125 +205,172 @@
190 205 // Adds description to loop
191 206 $this->update_control('loop', [
192 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'),
193 208 ]);
194 -
195 209 }
196 210
197 211 public function render()
198 212 {
199 - if( Plugin::$instance->experiments->is_feature_active('nested-elements') == false ){
200 - $this->nesting_fallback();
201 - return;
202 - }
213 + if (Plugin::$instance->experiments->is_feature_active('nested-elements') == false) {
214 + $this->nesting_fallback();
215 + return;
216 + }
203 217
204 218 $items = $this->get_settings_for_display('carousel_items');
205 219 $carousel_items = '';
206 220
207 - foreach ( $items as $index => $item ) {
221 + $total_slides = count($items);
222 + $this->TRAIT_render_center_loop_warning($total_slides);
223 +
224 + foreach ($items as $index => $item) {
208 225 ob_start();
209 226 $this->render_item($index);
210 - $carousel_items .= ob_get_clean();
227 + $current_slide = ob_get_clean();
228 +
229 + $carousel_items .= $current_slide;
211 230 }
212 - ?>
213 - <div class="ui-e-carousel swiper">
214 231
215 - <div class='swiper-wrapper'>
216 - <?php echo $carousel_items; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
217 - </div>
232 +?>
233 + <div class="ui-e-carousel ui-e-nested swiper">
218 234
219 - <?php $this->TRAIT_render_carousel_navigations(); ?>
235 + <div class='swiper-wrapper'>
236 + <?php echo $carousel_items; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
237 + ?>
220 238 </div>
221 - <?php
239 +
240 + </div>
241 +
242 + <?php $this->TRAIT_render_carousel_navigations($total_slides); ?>
243 + <?php
222 244 }
223 245
224 - public function render_item( $index ) {
225 - ?>
226 - <div class="ui-e-wrp swiper-slide" data-hash="<?php echo esc_html($index);?>">
227 - <?php $this->print_child( $index ); ?>
228 - </div>
229 - <?php
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
230 253 }
231 254
232 - public function print_child( $index ) {
233 - $children = $this->get_children();
234 - $child_ids = [];
255 + public function print_child($index)
256 + {
257 + $children = $this->get_children();
258 + $child_ids = [];
235 259
236 - if( empty( $children )){
237 - return;
238 - }
260 + if (empty($children) || ! isset($children[$index])) {
261 + return;
262 + }
239 263
240 - foreach ( $children as $child ) {
241 - $child_ids[] = $child->get_id();
242 - }
264 + foreach ($children as $child) {
265 + $child_ids[] = $child->get_id();
266 + }
243 267
244 - // Add the `ui-e-item` class directly on the item container
245 - $add_attribute_to_container = function ( $should_render, $container ) use ( $child_ids ) {
246 - if ( in_array( $container->get_id(), $child_ids ) ) {
247 - $container->add_render_attribute( '_wrapper', [
248 - 'class' => 'ui-e-item',
249 - ] );
250 - }
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);
251 271
252 - return $should_render;
253 - };
272 + $children[$index]->print_element();
254 273
255 - add_filter( 'elementor/frontend/container/should_render', $add_attribute_to_container, 10, 3 );
256 - $children[ $index ]->print_element();
257 - remove_filter( 'elementor/frontend/container/should_render', $add_attribute_to_container );
258 - }
274 + remove_filter('elementor/frontend/container/should_render', [$this, 'add_child_attributes']);
275 + }
259 276
260 - protected function get_initial_config(): array {
261 - if ( Plugin::$instance->experiments->is_feature_active( 'e_nested_atomic_repeaters' ) ) {
262 - return array_merge( parent::get_initial_config(), [
263 - 'support_improved_repeaters' => true,
264 - 'node' => 'button',
265 - ] );
266 - }
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 + {
267 282
268 - return parent::get_initial_config();
269 - }
283 + // custom cases may be added here
270 284
271 - protected function content_template() {
285 + if (in_array($container->get_id(), $child_ids)) {
286 + $container->add_render_attribute('_wrapper', [
287 + 'class' => $classnames,
288 + ]);
289 + }
272 290
273 - if( Plugin::$instance->experiments->is_feature_active('nested-elements') == false ){
274 - return;
275 - }
291 + return $should_render;
292 + }
276 293
277 - ?>
278 - <#
279 - var carouselItems = settings.carousel_items,
280 - navigationDots = settings.navigation.includes('dots'),
281 - navigationArrows = settings.navigation.includes('arrows'),
282 - navigationFraction = settings.navigation.includes('fraction');
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 + }
283 302
284 - var prev = elementor.helpers.renderIcon( view, settings.previous_arrow, { 'aria-hidden': true }, 'i' , 'object' ),
285 - next = elementor.helpers.renderIcon( view, settings.next_arrow, { 'aria-hidden': true }, 'i' , 'object' );
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' );
286 330 #>
287 - <div class="ui-e-carousel swiper {{ elementorFrontend.config.swiperClass }}">
288 331
289 - <div class='swiper-wrapper'> </div>
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>
290 337
291 - <# if ( navigationDots ) { #>
292 - <div class="swiper-pagination ui-e-dots"></div>
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>
293 346 <# } #>
294 - <# if ( navigationArrows ) { #>
295 - <div class="ui-e-button ui-e-previous" role="button" aria-label="Previous slide">
296 - {{{ prev.value }}}
347 +
348 + <div class="ui-e-carousel ui-e-nested swiper {{ elementorFrontend.config.swiperClass }}">
349 + <div class='swiper-wrapper'> </div>
297 350 </div>
298 - <div class="ui-e-button ui-e-next" role="button" aria-label="Next slide">
299 - {{{ next.value }}}
300 - </div>
301 - <# } #>
302 - <# if ( navigationFraction ) { #>
303 - <div class="ui-e-fraction">
304 - <span class="ui-e-current"></span>
305 - /
306 - <span class="ui-e-total"></span>
307 - </div>
308 - <# } #>
309 - </div>
310 - <?php
311 - }
312 351
313 -}
314 -\Elementor\Plugin::instance()->widgets_manager->register(new CustomCarousel());
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());