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/custom-table.php +266 -138 1.2.0 → 1.3.18 View file →
@@ -1,5 +1,6 @@
1 1 <?php
2 +
2 3 namespace UiCoreElements;
3 4
4 5 use Elementor\Plugin;
5 6 use Elementor\Controls_Manager;
@@ -8,9 +9,10 @@
8 9 use UiCoreElements\Utils\Animation_Trait;
9 10
10 11 defined('ABSPATH') || exit();
11 12
12 -class CustomTable extends UiCoreNestedWidget {
13 +class CustomTable extends UiCoreNestedWidget
14 +{
13 15
14 16 use Animation_Trait;
15 17
16 18 public function get_name()
@@ -40,49 +42,61 @@
40 42 public function get_scripts()
41 43 {
42 44 return [];
43 45 }
46 + public function has_widget_inner_wrapper(): bool
47 + {
48 + // TODO: remove after Optmized Markup experiment is merged to the core
49 + return ! \Elementor\Plugin::$instance->experiments->is_feature_active('e_optimized_markup');
50 + }
44 51
45 - protected function carousel_content_container( int $index ) {
46 - return [
47 - 'elType' => 'container',
48 - 'settings' => [
52 + protected function carousel_content_container(int $index)
53 + {
54 + return [
55 + 'elType' => 'container',
56 + 'settings' => [
49 57 /* translators: %s: Item index */
50 - '_title' => sprintf( __( 'Cel #%s', 'uicore-elements' ), $index ),
51 - 'content_width' => 'full',
52 - // 'flex_justify_content' => 'center',
53 - // 'flex_align_items' => 'center',
54 - // the settings work only ofr first default items
55 - ],
58 + '_title' => sprintf(__('Cel #%s', 'uicore-elements'), $index),
59 + 'content_width' => 'full',
60 + ],
56 61 ];
57 - }
62 + }
58 63
59 - protected function get_default_children_elements() {
60 - return [
61 - $this->carousel_content_container( 1 ),
62 - $this->carousel_content_container( 2 ),
63 - $this->carousel_content_container( 3 ),
64 - ];
65 - }
64 + protected function get_default_children_elements()
65 + {
66 + return [
67 + $this->carousel_content_container(1),
68 + $this->carousel_content_container(2),
69 + $this->carousel_content_container(3),
70 + ];
71 + }
66 72
67 - protected function get_default_repeater_title_setting_key() {
68 - return 'table_cels';
69 - }
73 + protected function get_default_repeater_title_setting_key()
74 + {
75 + return 'item';
76 + }
70 77
71 - protected function get_default_children_title() {
72 - /* translators: %d: Item index */
73 - return esc_html__( 'Cell #%d', 'uicore-elements' );
74 - }
75 - protected function get_default_children_placeholder_selector() {
76 - return '.ui-e-table';
77 - }
78 + protected function get_default_children_title()
79 + {
80 + /* translators: %d: Item index */
81 + return esc_html__('Cel #%d', 'uicore-elements');
82 + }
83 + protected function get_default_children_placeholder_selector()
84 + {
85 + return '.ui-e-table';
86 + }
78 87
88 + protected function get_default_children_container_placeholder_selector()
89 + {
90 + return '.ui-e-table-editor-placeholder';
91 + }
92 +
79 93 protected function register_controls()
80 94 {
81 - if( !Plugin::$instance->experiments->is_feature_active('nested-elements') ) {
82 - $this->nesting_fallback('controls');
83 - return;
84 - }
95 + if (!Plugin::$instance->experiments->is_feature_active('nested-elements')) {
96 + $this->nesting_fallback('controls');
97 + return;
98 + }
85 99
86 100 $this->start_controls_section(
87 101 'section_content',
88 102 [
@@ -90,8 +104,18 @@
90 104 'tab' => Controls_Manager::TAB_CONTENT,
91 105 ]
92 106 );
93 107
108 + $this->add_control(
109 + 'rerender_table',
110 + [
111 + 'label' => esc_html__('Preview', 'uicore-elements'),
112 + 'type' => Controls_Manager::BUTTON,
113 + 'text' => esc_html__('Refresh Table', 'uicore-elements'),
114 + 'separator' => 'before',
115 + 'event' => 'ui-e-custom-table-rerender',
116 + ]
117 + );
94 118
95 119 //Columns
96 120 $columns = new Repeater();
97 121 $columns->add_responsive_control(
@@ -98,9 +122,9 @@
98 122 'col_size',
99 123 [
100 124 'label' => __('Column Size', 'uicore-elements'),
101 125 'type' => Controls_Manager::SLIDER,
102 - 'size_units' => ['px', 'fr','custom'],
126 + 'size_units' => ['px', 'fr', 'custom'],
103 127 'default' => [
104 128 'size' => 300,
105 129 'unit' => 'px',
106 130 ],
@@ -113,8 +137,9 @@
113 137 'min' => 1,
114 138 'max' => 12,
115 139 ],
116 140 ],
141 + 'render_type' => 'ui',
117 142 'selectors' => [
118 143 '{{WRAPPER}}' => '--ui-e-last:{{SIZE}}{{UNIT}};',
119 144 ],
120 145 ]
@@ -125,13 +150,13 @@
125 150 [
126 151 'type' => Controls_Manager::REPEATER,
127 152 'fields' => $columns->get_controls(),
128 153 'title_field' => 'Column',
129 - 'render_type' => 'template',
154 + 'render_type' => 'ui',
130 155 'default' => [
131 - [ 'col_size' => [ 'size' => 1, 'unit' => 'fr' ] ],
132 - [ 'col_size' => [ 'size' => 1, 'unit' => 'fr' ] ],
133 - [ 'col_size' => [ 'size' => 1, 'unit' => 'fr' ] ],
156 + ['col_size' => ['size' => 1, 'unit' => 'fr']],
157 + ['col_size' => ['size' => 1, 'unit' => 'fr']],
158 + ['col_size' => ['size' => 1, 'unit' => 'fr']],
134 159 ],
135 160 ]
136 161 );
137 162
@@ -143,8 +168,9 @@
143 168 'item',
144 169 [
145 170 'label' => __('Title', 'uicore-elements'),
146 171 'type' => Controls_Manager::TEXT,
172 + 'render_type' => 'ui'
147 173 ]
148 174 );
149 175
150 176 $this->add_control(
@@ -151,13 +177,14 @@
151 177 'cells',
152 178 [
153 179 'type' => Control_Nested_Repeater::CONTROL_TYPE,
154 180 'fields' => $repeater->get_controls(),
181 + 'title_field' => '{{{ item }}}',
155 182 'allow_empty' => false,
156 183 'default' => [
157 - [ 'item' => __( 'Cel #1', 'uicore-elements' ) ],
158 - [ 'item' => __( 'Cel #2', 'uicore-elements' ) ],
159 - [ 'item' => __( 'Cel #3', 'uicore-elements' ) ],
184 + ['item' => __('Cel #1', 'uicore-elements')],
185 + ['item' => __('Cel #2', 'uicore-elements')],
186 + ['item' => __('Cel #3', 'uicore-elements')],
160 187 ],
161 188 ]
162 189 );
163 190
@@ -172,34 +199,110 @@
172 199 'tab' => Controls_Manager::TAB_STYLE,
173 200 ]
174 201 );
175 202
176 - //even rows background color
203 + $this->start_controls_tabs(
204 + 'row_tabs'
205 + );
206 +
207 + $this->start_controls_tab(
208 + 'odd_row',
209 + [
210 + 'label' => esc_html__('Odd row', 'textdomain'),
211 + ]
212 + );
213 +
177 214 $this->add_control(
215 + 'odd_row_bg_color',
216 + [
217 + 'label' => __('Row background', 'uicore-elements'),
218 + 'type' => Controls_Manager::COLOR,
219 + 'selectors' => [
220 + '{{WRAPPER}} .ui-e-table > .ui-e-odd' => 'background-color: {{VALUE}};',
221 + ],
222 + ]
223 + );
224 +
225 + $this->add_control(
226 + 'odd_row_padding',
227 + [
228 + 'label' => esc_html__('Row Padding', 'uicore-elements'),
229 + 'type' => Controls_Manager::DIMENSIONS,
230 + 'size_units' => ['px', 'em', 'rem', 'custom'],
231 + 'selectors' => [
232 + "{{WRAPPER}} .ui-e-table > .ui-e-odd" => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
233 + ],
234 + ]
235 + );
236 +
237 + $this->add_control(
238 + 'odd_row_radius',
239 + [
240 + 'label' => esc_html__('Row Border Radius', 'uicore-elements'),
241 + 'type' => Controls_Manager::DIMENSIONS,
242 + 'size_units' => ['px', 'em', 'rem', 'custom'],
243 + 'selectors' => [
244 + "{{WRAPPER}} .ui-e-table > .ui-e-odd.ui-e-first-row-cel" => 'border-radius: {{TOP}}{{UNIT}} 0 0 {{LEFT}}{{UNIT}};',
245 + "{{WRAPPER}} .ui-e-table > .ui-e-odd.ui-e-last-row-cel" => 'border-radius: 0 {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} 0;'
246 + ],
247 + ]
248 + );
249 +
250 + $this->end_controls_tab();
251 +
252 + $this->start_controls_tab(
253 + 'even_row',
254 + [
255 + 'label' => esc_html__('Even row', 'textdomain'),
256 + ]
257 + );
258 +
259 + $this->add_control(
178 260 'even_row_bg_color',
179 261 [
180 - 'label' => __('Even Rows Background', 'uicore-elements'),
262 + 'label' => __('Row background', 'uicore-elements'),
181 263 'type' => Controls_Manager::COLOR,
182 264 'selectors' => [
183 - '{{WRAPPER}} .ui-e-table .ui-e-even' => 'background-color: {{VALUE}};',
265 + '{{WRAPPER}} .ui-e-table > .ui-e-even' => 'background-color: {{VALUE}};',
184 266 ],
185 267 ]
186 268 );
187 269
270 + $this->add_control(
271 + 'even_row_padding',
272 + [
273 + 'label' => esc_html__('Row Padding', 'uicore-elements'),
274 + 'type' => Controls_Manager::DIMENSIONS,
275 + 'size_units' => ['px', 'em', 'rem', 'custom'],
276 + 'selectors' => [
277 + "{{WRAPPER}} .ui-e-table > .ui-e-even" => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
278 + ],
279 + ]
280 + );
188 281
282 + $this->add_control(
283 + 'even_row_radius',
284 + [
285 + 'label' => esc_html__('Row Border Radius', 'uicore-elements'),
286 + 'type' => Controls_Manager::DIMENSIONS,
287 + 'size_units' => ['px', 'em', 'rem', 'custom'],
288 + 'selectors' => [
289 + "{{WRAPPER}} .ui-e-table > .ui-e-even.ui-e-first-row-cel" => 'border-radius: {{TOP}}{{UNIT}} 0 0 {{LEFT}}{{UNIT}};',
290 + "{{WRAPPER}} .ui-e-table > .ui-e-even.ui-e-last-row-cel" => 'border-radius: 0 {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} 0;'
291 + ],
292 + ]
293 + );
294 +
295 + $this->end_controls_tab();
296 +
297 + $this->end_controls_tabs();
298 +
299 +
189 300 $this->end_controls_section();
190 301 }
191 302
192 - public function render()
303 + protected function build_grid_css($cols)
193 304 {
194 - if(!Plugin::$instance->experiments->is_feature_active('nested-elements')) {
195 - $this->nesting_fallback();
196 - return;
197 - }
198 -
199 - $cells = $this->get_settings_for_display('cells');
200 - $cols = $this->get_settings_for_display('columns');
201 -
202 305 // Build the grid columns css
203 306 if ($cols) {
204 307 $grid_css = '';
205 308 $grid_columns = [];
@@ -204,33 +307,23 @@
204 307 $grid_css = '';
205 308 $grid_columns = [];
206 309 $breakpoints = Plugin::$instance->breakpoints->get_active_breakpoints();
207 310
208 - $fallback = [
209 - 'size' => 2,
210 - 'unit' => 'fr',
211 - ];
311 + foreach ($cols as $index => $item) {
212 312
213 - // Columns loop
214 - foreach ($cols as $index => $item) {
215 - // Set desktop column size if we have both size and unit
216 - if (isset($item['col_size']['size']) && isset($item['col_size']['unit'])) {
217 - $grid_columns['desktop'][] = $item['col_size']['size'] . $item['col_size']['unit'];
218 - } else {
219 - $grid_columns['desktop'][] = $fallback['size'] . $fallback['unit'];
220 - }
313 + // Set desktop column size
314 + $grid_columns['desktop'][] = isset($item['col_size']['size']) && isset($item['col_size']['unit'])
315 + ? $item['col_size']['size'] . $item['col_size']['unit']
316 + : '1fr'; // fallback
221 317
222 - // Check for the current column responsive sizes
223 318 foreach ($breakpoints as $breakpoint => $object) {
224 319 $size_slug = 'col_size_' . $breakpoint;
225 320
226 - // Register the current column responsive size if it exists and
227 - // the value is not empty, because empty values will break the table design
228 - if (isset($item[$size_slug]['size']) && isset($item[$size_slug]['unit'])) {
229 - $grid_columns[$breakpoint][] = $item[$size_slug]['size'] . $item[$size_slug]['unit'];
230 - } else {
231 - $grid_columns[$breakpoint][] = $grid_columns['desktop'][$index];
232 - }
321 + // Register the current column responsive size if exists and the
322 + // value is not empty, because empty values breaks the table design
323 + $grid_columns[$breakpoint][] = isset($item[$size_slug]['size']) && isset($item[$size_slug]['unit'])
324 + ? $item[$size_slug]['size'] . $item[$size_slug]['unit']
325 + : $grid_columns['desktop'][$index];
233 326 }
234 327 }
235 328
236 329 // Generate the css variables
@@ -238,99 +331,134 @@
238 331 $breakpoint = $device === 'desktop' ? '' : '-' . $device;
239 332 $grid_css .= '--ui-e-table-cols' . $breakpoint . ':' . implode(' ', $values) . ';';
240 333 }
241 334
242 - // Add it to the widget wrapper
243 - $this->add_render_attribute('_wrapper', [
244 - 'style' => $grid_css,
245 - ]);
335 + return $grid_css;
246 336 }
337 + }
247 338
248 - ?>
339 + public function render()
340 + {
341 + if (!Plugin::$instance->experiments->is_feature_active('nested-elements')) {
342 + $this->nesting_fallback();
343 + return;
344 + }
345 +
346 + $cells = $this->get_settings_for_display('cells');
347 + $cols = $this->get_settings_for_display('columns');
348 + $grid_css = $this->build_grid_css($cols);
349 +
350 + // Add it to the widget wrapper
351 + $this->add_render_attribute('_wrapper', ['style' => $grid_css]);
352 +
353 +?>
249 354 <div class="ui-e-table">
250 355 <?php
251 356
252 - $columns = count($cols);
357 + $columns = count($cols);
253 358
254 - foreach ($cells as $index => $item) {
255 - $is_even = floor($index / $columns) % 2 !== 0;
359 + foreach ($cells as $index => $item) {
360 + $row_class = floor($index / $columns) % 2 !== 0
361 + ? 'ui-e-even'
362 + : 'ui-e-odd';
256 363
257 - // TODO: maybe there's a way of adding the class to the child wrapper instead of printing an extra element
258 - if ($is_even) {
259 - ?>
260 - <div class="ui-e-even">
261 - <?php $this->print_child($index); ?>
262 - </div>
263 - <?php
264 - } else {
265 - $this->print_child($index);
266 - }
364 + // TODO: in the future experiment a nth-child approach so we don't need this first/last classes
365 + // Add classes to the first and last items of each row
366 + if ($index % $columns === 0) {
367 + $row_class .= ' ui-e-first-row-cel';
368 + } else if (($index + 1) % $columns === 0) {
369 + $row_class .= ' ui-e-last-row-cel';
267 370 }
371 +
372 + $this->print_child($index, ['class' => $row_class]);
373 + }
268 374 ?>
269 375 </div>
270 - <?php
376 + <?php
271 377 }
272 378
379 + public function print_child($index, array $atts = [])
380 + {
381 + $children = $this->get_children();
273 382
274 - protected function get_initial_config(): array {
275 - if (Plugin::$instance->experiments->is_feature_active('e_nested_atomic_repeaters')) {
276 - return array_merge(parent::get_initial_config(), [
277 - 'support_improved_repeaters' => true,
278 - 'node' => '.ui-e-table'
279 - ]);
280 - }
383 + if (! empty($children[$index])) {
281 384
282 - return parent::get_initial_config();
283 - }
385 + // Add custom attributes to each child container.
386 + if (!empty($atts)) {
387 + //$child_settings = $children[ $index ]->get_settings_for_display();
388 + foreach ($atts as $key => $value) {
389 + $children[$index]->add_render_attribute('_wrapper', $key, $value);
390 + }
391 + }
284 392
393 + $children[$index]->print_element();
394 + }
395 + }
285 396
286 - protected function content_template() {
287 - ?>
397 + protected function get_initial_config(): array
398 + {
399 + if (Plugin::$instance->experiments->is_feature_active('e_nested_atomic_repeaters')) {
400 + return array_merge(parent::get_initial_config(), [
401 + 'support_improved_repeaters' => true,
402 + 'node' => '.ui-e-table'
403 + ]);
404 + }
405 +
406 + return parent::get_initial_config();
407 + }
408 +
409 +
410 + protected function content_template()
411 + {
412 + ?>
288 413 <#
289 - const cols = settings.columns;
290 - const cols_qty = '--ui-e-cols-qty:' + settings.columns.length;
414 + const cols=settings.columns || [];
415 + const cells=settings.cells || [];
416 + const cols_qty='--ui-e-cols-qty:' + cols.length;
291 417
292 418 if ( cols ) {
293 - let gridCss = '';
294 - const gridColumns = {};
295 - const breakpoints = elementorFrontend.config.breakpoints.activeBreakpoints;
419 + let gridCss='' ;
420 + const gridColumns={};
421 + const breakpoints=elementorFrontend.config.responsive.activeBreakpoints;
296 422
297 - _.each( cols, function( item, index ) {
423 + _.each( cols, function( item, index ) {
298 424
299 - if ( ! gridColumns.desktop ) {
300 - gridColumns.desktop = [];
301 - }
425 + if ( ! gridColumns.desktop ) {
426 + gridColumns.desktop=[];
427 + }
302 428
303 - gridColumns.desktop.push( item.col_size.size + item.col_size.unit );
429 + gridColumns.desktop.push( item.col_size.size + item.col_size.unit );
304 430
305 - _.each( breakpoints, function( object, breakpoint ) {
306 - const sizeSlug = 'col_size_' + breakpoint;
431 + _.each( breakpoints, function( object, breakpoint ) {
432 + const sizeSlug='col_size_' + breakpoint;
307 433
308 - if ( item[sizeSlug] && item[sizeSlug].size ) {
309 - if ( ! gridColumns[breakpoint] ) {
310 - gridColumns[breakpoint] = [];
311 - }
312 - gridColumns[breakpoint].push( item[sizeSlug].size + item[sizeSlug].unit );
313 - } else {
314 - if ( ! gridColumns[breakpoint] ) {
315 - gridColumns[breakpoint] = [];
316 - }
317 - gridColumns[breakpoint].push( item.col_size.size + item.col_size.unit );
318 - }
319 - });
320 - });
434 + if ( item[sizeSlug] && item[sizeSlug].size ) {
435 + if ( ! gridColumns[breakpoint] ) {
436 + gridColumns[breakpoint]=[];
437 + }
438 + gridColumns[breakpoint].push( item[sizeSlug].size + item[sizeSlug].unit );
439 + } else {
440 + if ( ! gridColumns[breakpoint] ) {
441 + gridColumns[breakpoint]=[];
442 + }
443 + gridColumns[breakpoint].push( item.col_size.size + item.col_size.unit );
444 + }
445 + });
446 + });
321 447
322 - _.each( gridColumns, function( values, device ) {
323 - const breakpoint = device === 'desktop' ? '' : '-' + device;
324 - gridCss += '--ui-e-table-cols' + breakpoint + ':' + values.join(' ') + ';';
325 - });
448 + _.each( gridColumns, function( values, device ) {
449 + const breakpoint=device==='desktop' ? '' : '-' + device;
450 + gridCss +='--ui-e-table-cols' + breakpoint + ':' + values.join(' ') + ' ;';
451 + });
326 452
327 - view.addRenderAttribute('table', 'style', [gridCss, cols_qty].join(' '));
453 + view.addRenderAttribute('table', 'data-cell-count' , cells.length);
454 + view.addRenderAttribute('table', 'style' , [gridCss, cols_qty].join(' '));
328 455 }
329 - #>
330 - <div class="ui-e-table" {{{ view.getRenderAttributeString('table') }}}>
456 + #>
457 + <div class="ui-e-table" {{{ view.getRenderAttributeString('table') }}}>
331 458
332 - </div>
333 - <?php
459 + </div>
460 + <div class="ui-e-table-editor-placeholder"></div>
461 + <?php
334 462 }
335 463 }
336 -\Elementor\Plugin::instance()->widgets_manager->register(new CustomTable());
464 +\Elementor\Plugin::instance()->widgets_manager->register(new CustomTable());