PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.3.18
UiCore Elements – Free widgets and templates for Elementor v1.3.18
1.3.18 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 All 42 releases
← All changes | includes/widgets/advanced-product-grid.php +363 -127 1.2.0 → 1.3.18 View file →
@@ -37,9 +37,9 @@
37 37 return 'eicon-gallery-grid ui-e-widget';
38 38 }
39 39 public function get_keywords()
40 40 {
41 - return [ 'woocommerce', 'product', 'shop', 'store', 'post', 'grid' ];
41 + return ['woocommerce', 'product', 'shop', 'store', 'post', 'grid'];
42 42 }
43 43 public function get_styles()
44 44 {
45 45 // get parent get_styles
@@ -47,9 +47,9 @@
47 47
48 48 // remove parent AdvancedPostGrid widget main style. OBS: the IDE complains because get_styles doc
49 49 // says it returns obj, but we're extending a widget that returns the array, so the parent
50 50 // is not widget base, but the AdvancedPostGrid widget
51 - if ( ($key = array_search('advanced-post-grid', $styles)) !== false) {
51 + if (($key = array_search('advanced-post-grid', $styles)) !== false) {
52 52 unset($styles[$key]);
53 53 }
54 54
55 55 // Add the product grid style
@@ -56,8 +56,26 @@
56 56 $styles[] = 'advanced-product-grid';
57 57
58 58 return $styles;
59 59 }
60 +
61 + /**
62 + * Makes sure some of our custom controls are present. This should be a
63 + * temporary fix to a problem that do not happens consistently.
64 + */
65 + function custom_controls_verification()
66 + {
67 + // In some contexts, such as theme-builder, our custom controls are not available
68 + // and requiring in register_controls method breaks the widget render in editor
69 + if (! defined('DOING_AJAX') || ! DOING_AJAX) {
70 + if (! class_exists('UiCoreElements\Controls\Post_Filter')) {
71 + require_once UICORE_ELEMENTS_INCLUDES . '/controls/class-post-filter-control.php';
72 + }
73 + if (! class_exists('UiCoreElements\Controls\Product_Filter')) {
74 + require_once UICORE_ELEMENTS_INCLUDES . '/controls/class-product-filter-control.php';
75 + }
76 + }
77 + }
60 78 function get_query()
61 79 {
62 80 return $this->_query;
63 81 }
@@ -63,10 +81,12 @@
63 81 }
64 82
65 83 protected function register_controls()
66 84 {
85 + $this->custom_controls_verification();
86 +
67 87 // Fallback
68 - if( !class_exists('WooCommerce') ) {
88 + if (!class_exists('WooCommerce')) {
69 89 $this->start_controls_section(
70 90 'section_fallback',
71 91 [
72 92 'label' => esc_html__('Content', 'uicore-elements'),
@@ -71,16 +91,16 @@
71 91 [
72 92 'label' => esc_html__('Content', 'uicore-elements'),
73 93 ]
74 94 );
75 - $this->add_control(
76 - 'woocommerce_warning',
77 - [
78 - 'type' => \Elementor\Controls_Manager::ALERT,
79 - 'alert_type' => 'warning',
80 - 'content' => esc_html__('Please enable WooCommerce to use this widget.', 'uicore-elements'),
81 - ]
82 - );
95 + $this->add_control(
96 + 'woocommerce_warning',
97 + [
98 + 'type' => \Elementor\Controls_Manager::ALERT,
99 + 'alert_type' => 'warning',
100 + 'content' => esc_html__('Please enable WooCommerce to use this widget.', 'uicore-elements'),
101 + ]
102 + );
83 103 $this->end_controls_section();
84 104 return;
85 105 }
86 106
@@ -93,109 +113,318 @@
93 113 $this->remove_control('after_title_meta');
94 114 $this->remove_control('bottom_meta');
95 115
96 116 // Register query control with updated options
97 - $this->start_injection( [
98 - 'of' => 'section_post_grid_def',
99 - 'at' => 'after',
100 - ] );
101 - $this->add_group_control(
102 - Product_Filter::get_type(),
103 - [
104 - 'name' => 'product-filter',
105 - 'label' => esc_html__('Products', 'uicore-elements'),
106 - 'description' => esc_html__('Current Query Settings > Reading', 'uicore-elements'),
107 - ]
108 - );
109 - $this->end_injection();
117 + $this->start_injection([
118 + 'of' => 'section_post_grid_def',
119 + 'at' => 'after',
120 + ]);
121 + $this->add_group_control(
122 + Product_Filter::get_type(),
123 + [
124 + 'name' => 'product-filter',
125 + 'label' => esc_html__('Products', 'uicore-elements'),
126 + 'description' => esc_html__('Current Query Settings > Reading', 'uicore-elements'),
127 + ]
128 + );
129 + $this->end_injection();
110 130
111 131 // Register meta controls with updated options
112 - $this->start_injection( [
113 - 'of' => 'section_extra_item_content',
114 - 'at' => 'after',
115 - ] );
116 - $this->TRAIT_register_post_meta_controls(false, true);
117 - $this->end_injection();
132 + $this->start_injection([
133 + 'of' => 'section_extra_item_content',
134 + 'at' => 'after',
135 + ]);
136 + $this->TRAIT_register_post_meta_controls(false, true);
137 + $this->end_injection();
118 138
119 139 // Register new button placement control
120 - $this->start_injection( [
121 - 'of' => 'section_button_style',
122 - 'at' => 'after',
123 - ] );
124 - $this->add_control(
125 - 'button_position',
126 - [
127 - 'label' => esc_html__('Placement', 'uicore-elements'),
128 - 'type' => \Elementor\Controls_Manager::SELECT,
129 - 'options' => [
130 - '' => 'Default',
131 - 'ui-e-button-placement-image' => 'On Image',
132 - ],
133 - 'default' => 'ui-e-button-placement-image',
134 - 'render_type' => 'template',
135 - 'prefix_class' => ''
136 - ]
137 - );
138 - $this->end_injection();
140 + $this->start_injection([
141 + 'of' => 'section_button_style',
142 + 'at' => 'after',
143 + ]);
144 + $this->add_control(
145 + 'button_position',
146 + [
147 + 'label' => esc_html__('Placement', 'uicore-elements'),
148 + 'type' => \Elementor\Controls_Manager::SELECT,
149 + 'options' => [
150 + '' => 'Default',
151 + 'ui-e-button-placement-image' => 'On Image',
152 + ],
153 + 'default' => 'ui-e-button-placement-image',
154 + 'render_type' => 'template',
155 + 'prefix_class' => ''
156 + ]
157 + );
158 + $this->end_injection();
139 159
140 160 // Register new Swatches and Sale Badge controls
141 - $this->start_injection( [
142 - 'of' => 'show_button',
143 - 'at' => 'after',
144 - ] );
161 + $this->start_injection([
162 + 'of' => 'show_button',
163 + 'at' => 'after',
164 + ]);
165 +
166 + if (defined('UICORE_ASSETS')) {
145 167 $this->add_control(
146 168 'show_swatches',
147 169 [
148 170 'label' => esc_html__('Swatches', 'uicore-elements'),
149 171 'type' => \Elementor\Controls_Manager::SWITCHER,
150 - 'label_on' => esc_html__( 'Show', 'uicore-elements' ),
151 - 'label_off' => esc_html__( 'Hide', 'uicore-elements' ),
172 + 'label_on' => esc_html__('Show', 'uicore-elements'),
173 + 'label_off' => esc_html__('Hide', 'uicore-elements'),
152 174 'description' => esc_html__('Will only work if you have Uicore Framework plugin active at least on version 6.0.1', 'uicore-elements'),
153 175 'default' => 'yes',
154 176 ]
155 177 );
178 + }
179 +
180 + $this->add_control(
181 + 'show_sale_badge',
182 + [
183 + 'label' => esc_html__('Sale Badge', 'uicore-elements'),
184 + 'type' => \Elementor\Controls_Manager::SWITCHER,
185 + 'label_on' => esc_html__('Show', 'uicore-elements'),
186 + 'label_off' => esc_html__('Hide', 'uicore-elements'),
187 + 'default' => 'yes',
188 + 'prefix_class' => 'ui-e-show-sale-badge-',
189 + ]
190 + );
191 + $this->add_control(
192 + 'badge_warning',
193 + [
194 + 'type' => \Elementor\Controls_Manager::RAW_HTML,
195 + 'raw' => __("If you can't see the Sale Badge after setting 'Show', you problably didn't set any Meta option as 'Product Sale', or you don't have products on sale.", 'uicore-elements'),
196 + 'content_classes' => 'elementor-control-field-description',
197 + 'condition' => [
198 + 'show_sale_badge' => 'yes',
199 + ],
200 + ]
201 + );
202 +
203 + $this->end_injection();
204 +
205 + if (defined('UICORE_ASSETS')) {
206 + $this->start_injection([
207 + 'of' => 'section_style_content',
208 + 'at' => 'after',
209 + ]);
210 + $this->start_controls_section(
211 + 'section_swatches',
212 + [
213 + 'label' => esc_html__('Swatches', 'uicore-elements') . UICORE_ELEMENTS_NEW_OPTION,
214 + 'tab' => \Elementor\Controls_Manager::TAB_STYLE,
215 + 'condition' => [
216 + 'show_swatches' => 'yes',
217 + ],
218 + ]
219 + );
220 +
156 221 $this->add_control(
157 - 'show_sale_badge',
222 + 'swatches_to',
158 223 [
159 - 'label' => esc_html__('Sale Badge', 'uicore-elements'),
224 + 'label' => esc_html__('Use Framework defaults', 'uicore-elements'),
160 225 'type' => \Elementor\Controls_Manager::SWITCHER,
161 - 'label_on' => esc_html__( 'Show', 'uicore-elements' ),
162 - 'label_off' => esc_html__( 'Hide', 'uicore-elements' ),
226 + 'description' => esc_html__('If enabled, the swatches will inherit your theme options.', 'uicore-elements'),
227 + 'label_on' => esc_html__('Yes', 'uicore-elements'),
228 + 'label_off' => esc_html__('No', 'uicore-elements'),
163 229 'default' => 'yes',
164 - 'prefix_class' => 'ui-e-show-sale-badge-',
165 230 ]
166 231 );
232 +
167 233 $this->add_control(
168 - 'badge_warning',
234 + 'swatches_size',
169 235 [
170 - 'type' => \Elementor\Controls_Manager::RAW_HTML,
171 - 'raw' => __("If you can't see the Sale Badge after setting 'Show', you problably didn't set any Meta option as 'Product Sale', or you don't have products on sale.", 'uicore-elements'),
172 - 'content_classes' => 'elementor-control-field-description',
236 + 'label' => esc_html__('Size', 'uicore-elements'),
237 + 'type' => \Elementor\Controls_Manager::SLIDER,
238 + 'size_units' => ['px'],
239 + 'range' => [
240 + 'px' => [
241 + 'min' => 10,
242 + 'max' => 100,
243 + ],
244 + ],
245 + 'default' => [
246 + 'unit' => 'px',
247 + 'size' => 30,
248 + ],
173 249 'condition' => [
174 - 'show_sale_badge' => 'yes',
250 + 'show_swatches' => 'yes',
251 + 'swatches_to!' => 'yes',
175 252 ],
253 + 'selectors' => [
254 + '{{WRAPPER}}' => '--uicore-swatch-size: {{SIZE}}{{UNIT}};',
255 + ],
176 256 ]
177 257 );
178 - $this->end_injection();
179 258
180 - // Register new Hide out of stock products control
181 - $this->start_injection( [
182 - 'of' => 'sticky',
183 - 'at' => 'before',
184 - ] );
185 259 $this->add_control(
186 - 'hide_out_of_stock',
260 + 'swatches_outer_radius',
187 261 [
188 - 'label' => esc_html__('Hide out of stock', 'uicore-elements'),
189 - 'type' => \Elementor\Controls_Manager::SWITCHER,
262 + 'label' => esc_html__('Outer Border Radius', 'uicore-elements'),
263 + 'type' => \Elementor\Controls_Manager::SLIDER,
264 + 'size_units' => ['%', 'px'],
265 + 'range' => [
266 + '%' => [
267 + 'min' => 0,
268 + 'max' => 100,
269 + ],
270 + 'px' => [
271 + 'min' => 0,
272 + 'max' => 50,
273 + ],
274 + ],
275 + 'default' => [
276 + 'unit' => '%',
277 + 'size' => 50,
278 + ],
279 + 'separator' => 'before',
190 280 'condition' => [
191 - 'product-filter_post_type!' => 'related',
281 + 'show_swatches' => 'yes',
282 + 'swatches_to!' => 'yes',
192 283 ],
284 + 'selectors' => [
285 + '{{WRAPPER}}' => '--uicore-swatch-radius: {{SIZE}}{{UNIT}}; --uicore-swatch-big-radius: {{SIZE}}{{UNIT}};',
286 + '{{WRAPPER}} .uicore-swatch.uicore-swatch--color' => 'border-radius: {{SIZE}}{{UNIT}};',
287 + ],
193 288 ]
194 289 );
195 - $this->end_injection();
196 290
291 + $this->add_control(
292 + 'swatches_inner_radius',
293 + [
294 + 'label' => esc_html__('Inner Border Radius', 'uicore-elements'),
295 + 'type' => \Elementor\Controls_Manager::SLIDER,
296 + 'size_units' => ['px', '%'],
297 + 'range' => [
298 + 'px' => [
299 + 'min' => 0,
197 300
301 + 'max' => 100,
302 + ],
303 + '%' => [
304 + 'min' => 0,
305 + 'max' => 50,
306 + ],
307 + ],
308 + 'default' => [
309 + 'unit' => 'px',
310 + 'size' => 4,
311 + ],
312 + 'separator' => 'after',
313 + 'condition' => [
314 + 'show_swatches' => 'yes',
315 + 'swatches_to!' => 'yes',
316 + ],
317 + 'selectors' => [
318 + '{{WRAPPER}} .uicore-swatch > div' => 'border-radius: {{SIZE}}{{UNIT}};',
319 + ],
320 + ]
321 + );
322 +
323 + $this->add_group_control(
324 + \Elementor\Group_Control_Border::get_type(),
325 + [
326 + 'name' => 'swatch_border',
327 + 'selector' => '{{WRAPPER}} .uicore-swatch',
328 + 'condition' => [
329 + 'show_swatches' => 'yes',
330 + 'swatches_to!' => 'yes',
331 + ],
332 + ]
333 + );
334 +
335 + $this->add_control(
336 + 'hover_border_size',
337 + [
338 + 'label' => esc_html__('Hover Border Size', 'uicore-elements'),
339 + 'type' => \Elementor\Controls_Manager::SLIDER,
340 + 'size_units' => ['px'],
341 + 'range' => [
342 + 'px' => [
343 + 'min' => 0,
344 +
345 + 'max' => 5,
346 + ],
347 + ],
348 + 'default' => [
349 + 'unit' => 'px',
350 + 'size' => 1,
351 + ],
352 + 'condition' => [
353 + 'show_swatches' => 'yes',
354 + 'swatches_to!' => 'yes',
355 + ],
356 + 'selectors' => [
357 + '{{WRAPPER}} .uicore-swatch:hover' => 'box-shadow: 0 0 0 {{SIZE}}{{UNIT}} var(--uicore-swatch-border);',
358 + ],
359 + ]
360 + );
361 +
362 + $this->add_control(
363 + 'swatch_hover_color',
364 + [
365 + 'label' => esc_html__('Hover Border Color', 'uicore-elements'),
366 + 'type' => \Elementor\Controls_Manager::COLOR,
367 + 'condition' => [
368 + 'show_swatches' => 'yes',
369 + 'swatches_to!' => 'yes',
370 + ],
371 + 'selectors' => [
372 + '{{WRAPPER}}' => '--uicore-swatch-border: {{VALUE}};',
373 + '{{WRAPPER}} .uicore-swatch:hover' => 'border-color: {{VALUE}};',
374 + ],
375 + ]
376 + );
377 +
378 + $this->end_controls_section();
379 + $this->end_injection();
380 + }
381 +
382 + // Register new Hide out of stock products control
383 + $this->start_injection([
384 + 'of' => 'sticky',
385 + 'at' => 'before',
386 + ]);
387 + $this->add_control(
388 + 'hide_out_of_stock',
389 + [
390 + 'label' => esc_html__('Hide out of stock', 'uicore-elements'),
391 + 'type' => \Elementor\Controls_Manager::SWITCHER,
392 + 'condition' => [
393 + 'product-filter_post_type!' => 'related',
394 + ],
395 + ]
396 + );
397 + $this->end_injection();
398 +
399 + $this->start_injection([
400 + 'of' => 'text',
401 + 'at' => 'after',
402 + ]);
403 + $this->add_control(
404 + 'variations_text',
405 + [
406 + 'type' => \Elementor\Controls_Manager::TEXT,
407 + 'label' => esc_html__('Select Options Text', 'uicore-elements'),
408 + 'label_block' => true,
409 + 'default' => '',
410 + 'description' => esc_html__('Variable product purchase text.', 'uicore-elements'),
411 + 'placeholder' => esc_html__('Select Options', 'uicore-elements'),
412 + ]
413 + );
414 + $this->add_control(
415 + 'unavailable_text',
416 + [
417 + 'type' => \Elementor\Controls_Manager::TEXT,
418 + 'label' => esc_html__('Unavailable Text', 'uicore-elements'),
419 + 'label_block' => true,
420 + 'default' => '',
421 + 'description' => esc_html__('Out of stock or not available purchase text.', 'uicore-elements'),
422 + 'placeholder' => esc_html__('Read more', 'uicore-elements'),
423 + ]
424 + );
425 + $this->end_injection();
426 +
198 427 // Update controls that uses 'posts_filter' to 'product_filter'
199 428 $this->update_control(
200 429 'item_limit',
201 430 [
@@ -263,9 +492,9 @@
263 492 ]
264 493 );
265 494 $this->update_control(
266 495 'excerpt_trim',
267 - [ 'label' => esc_html__('Summary Length (words)', 'uicore-elements') ]
496 + ['label' => esc_html__('Summary Length (words)', 'uicore-elements')]
268 497 );
269 498 $this->update_control(
270 499 'show_button',
271 500 [
@@ -275,24 +504,25 @@
275 504 );
276 505 $this->update_control(
277 506 'text',
278 507 [
279 - 'label' => esc_html__('Custom Text', 'uicore-elements'),
508 + 'label' => esc_html__('Add to Cart Text', 'uicore-elements'),
509 + 'label_block' => true,
280 510 'default' => '',
281 - 'description' => esc_html__('If left blank, the default add to cart button text will be used.', 'uicore-elements')
511 + 'placeholder' => esc_html__('Add to cart', 'uicore-elements'),
282 512 ]
283 513 );
284 514 $this->update_control(
285 515 'text_color',
286 - [ 'label' => esc_html__('Summary Color', 'uicore-elements') ]
516 + ['label' => esc_html__('Summary Color', 'uicore-elements')]
287 517 );
288 518 $this->update_control(
289 519 'text_typography',
290 - [ 'label' => esc_html__('Summary Typography', 'uicore-elements') ]
520 + ['label' => esc_html__('Summary Typography', 'uicore-elements')]
291 521 );
292 522 $this->update_control(
293 523 'text_gap',
294 - [ 'label' => esc_html__('Summary Top Space', 'uicore-elements') ]
524 + ['label' => esc_html__('Summary Top Space', 'uicore-elements')]
295 525 );
296 526
297 527 // Update button controls
298 528 $this->update_control(
@@ -297,15 +527,15 @@
297 527 // Update button controls
298 528 $this->update_control(
299 529 'border_radius', // button border-radius
300 530 [
301 - 'default' => [ 'top' => 0, 'right' => 0, 'bottom' => 0, 'left' => 0 ]
531 + 'default' => ['top' => 0, 'right' => 0, 'bottom' => 0, 'left' => 0]
302 532 ]
303 533 );
304 534 $this->update_control(
305 535 'text_padding', // button padding
306 536 [
307 - 'default' => [ 'top' => 10, 'right' => 10, 'bottom' => 10, 'left' => 10, 'unit' => 'px' ]
537 + 'default' => ['top' => 10, 'right' => 10, 'bottom' => 10, 'left' => 10, 'unit' => 'px']
308 538 ]
309 539 );
310 540 $this->update_control(
311 541 'button_align',
@@ -311,8 +541,13 @@
311 541 'button_align',
312 542 [
313 543 'condition' => [
314 544 'button_position!' => 'ui-e-button-placement-image',
545 + ],
546 + // since product might have ajax add to cart, wich has flex display so the cart added icon do not break button layout,
547 + // we justify the flex content to center so justified text align button keeps text centralized. See: https://uicore.atlassian.net/browse/ELM-429
548 + 'selectors' => [
549 + '{{WRAPPER}} .ui-e-readmore' => 'align-self: {{VALUE}}; justify-content: center;',
315 550 ]
316 551 ]
317 552 );
318 553 $this->update_control(
@@ -331,32 +566,33 @@
331 566 * This method retrieves the widget settings; set up the query, and renders each post item.
332 567 * If no posts are found, it returns false. After rendering, it resets the query and returns the output.
333 568 *
334 569 * @param array|false $current_query The current query args, or false if the widget isn't set to use the current query.
570 + * @param int $pageID The ID of the page where the widget is located.
335 571 *
336 572 * @return string|false The rendered widget content or false if no posts are found.
337 - */
573 + */
338 574 public function render_ajax($current_query)
339 575 {
340 576 // Get settings and post type
341 577 $settings = $this->get_settings();
342 578
343 - $this->TRAIT_query_products( $settings, $current_query );
579 + $this->TRAIT_query_products($settings, $current_query);
344 580 $wc_query = $this->get_query();
345 581
346 582 $products = wc_get_products($wc_query);
347 583
348 584 // No products found
349 - if ( empty($products) ) {
585 + if (empty($products)) {
350 586 return false;
351 587 }
352 588
353 589 \ob_start();
354 - foreach ($products as $product) {
590 + foreach ($products as $index => $product) {
355 591 $post_object = get_post($product->get_id());
356 592 setup_postdata($post_object);
357 593
358 - $this->TRAIT_render_product($product, false, true, true);
594 + $this->TRAIT_render_product($product, $index, false, true, true);
359 595
360 596 wp_reset_postdata();
361 597 }
362 598 $markup = \ob_get_clean();
@@ -368,10 +604,10 @@
368 604 }
369 605
370 606 protected function render()
371 607 {
372 - if( !class_exists('WooCommerce') ) {
373 - if ( $this->is_edit_mode() ) {
608 + if (!class_exists('WooCommerce')) {
609 + if ($this->is_edit_mode()) {
374 610 echo '<p>' . esc_html__('Please enable WooCommerce to use this widget.', 'uicore-elements') . '</p>';
375 611 }
376 612 return;
377 613 }
@@ -378,21 +614,22 @@
378 614
379 615 global $wp_query;
380 616 $settings = $this->get_settings();
381 617
618 + // Get product ID
619 + $product_id = get_the_ID();
620 +
382 621 // Related products, on save page action at editor, triggers an fata error upon post object handle.
383 622 // Prevent it for now by disabling the widget on edit mode. TODO: remove it after fixing the issue
384 - if ( 'related' === $settings['product-filter_post_type'] && $this->is_edit_mode() ) {
623 + if ('related' === $settings['product-filter_post_type'] && $this->is_edit_mode()) {
385 624 echo '<p>' . esc_html__('This widget is set to display related products. To see the results, please preview the page, or customize your widget before setting "current" query.', 'uicore-elements') . '</p>';
386 625 return;
387 626 }
388 627
389 628 // Build query
390 - $products = $this->TRAIT_query_products( $settings, $wp_query->query );
629 + $products = $this->TRAIT_query_products($settings, $wp_query->query);
391 630 $wc_query = $this->get_query();
392 631
393 - $this->TRAIT_set_meta_font_size_to_svg($settings); // SVG icon experiment font-size adjustment
394 -
395 632 // Store widget settings in a transient
396 633 $ID = strval($this->get_ID());
397 634 set_transient('ui_elements_widgetdata_' . $ID, $settings, \MONTH_IN_SECONDS);
398 635
@@ -402,53 +639,52 @@
402 639
403 640 $this->TRAIT_render_filters($settings, true);
404 641
405 642 // No posts found
406 - if ( empty($products) ) {
643 + if (empty($products)) {
407 644 echo '<p style="text-align:center">' . esc_html__('No products found.', 'uicore-elements') . '</p>';
408 -
409 645 } else {
410 - ?>
411 - <div class="ui-e-adv-grid">
412 - <?php
413 - foreach ($products as $product) {
646 +?>
647 + <div class="ui-e-adv-grid">
648 + <?php
649 + foreach ($products as $index => $product) {
414 650
415 - // sticky posts disregards posts per page, so ending the loop if $items == $loop forces the query respects the users item limit
416 - if ($settings['sticky'] && $items == $loops) {
417 - break;
418 - }
651 + // sticky posts disregards posts per page, so ending the loop if $items == $loop forces the query respects the users item limit
652 + if ($settings['sticky'] && $items == $loops) {
653 + break;
654 + }
419 655
420 - // check is is related post type
421 - if ( 'related' === $settings['product-filter_post_type'] ) {
422 - $product = wc_get_product($product);
423 - }
656 + // check is is related post type
657 + if ('related' === $settings['product-filter_post_type']) {
658 + $product = wc_get_product($product);
659 + }
424 660
425 - $post_object = get_post($product->get_id());
426 - setup_postdata($post_object);
661 + $post_object = get_post($product->get_id());
662 + setup_postdata($post_object);
427 663
428 - $this->TRAIT_render_product($product, false, true);
664 + $this->TRAIT_render_product($product, $index, false, true);
429 665
430 - wp_reset_postdata(); // Reset post data after rendering each product
431 - $loops++;
432 - }
433 - ?>
434 - </div>
435 - <?php
666 + wp_reset_postdata(); // Reset post data after rendering each product
667 + $loops++;
668 + }
669 + ?>
670 + </div>
671 +<?php
436 672
437 - $this->TRAIT_render_pagination($settings, true);
673 + $this->TRAIT_render_pagination($settings, $product_id, true);
438 674
439 - // Add some data, to help rest api, to the js
440 - if( $settings['pagination'] == 'yes' && $settings['pagination_type'] == 'load_more' ) {
675 + // Add some data, to help rest api, to the js
676 + if ($this->is_option('pagination', 'yes') && $this->is_option('pagination_type', 'load_more')) {
441 677
442 678 echo '<script>';
443 679
444 - // Add total pages to js variable
445 - echo 'window.ui_total_pages_' . esc_html($ID) . ' = ' . esc_html( $wc_query['total_pages'] ) . ';';
680 + // Add total pages to js variable
681 + echo 'window.ui_total_pages_' . esc_html($ID) . ' = ' . esc_html($wc_query['total_pages']) . ';';
446 682
447 - // Pass current query to js variable
448 - if( $settings['product-filter_post_type'] == 'current' ) {
449 - echo 'window.ui_query_' . esc_html($ID) . ' = ' . \json_encode($wc_query) . ';';
450 - }
683 + // Pass current query to js variable
684 + if ($settings['product-filter_post_type'] == 'current') {
685 + echo 'window.ui_query_' . esc_html($ID) . ' = ' . \json_encode($wc_query) . ';';
686 + }
451 687
452 688 echo '</script>';
453 689 }
454 690 }