PluginProbe
Elementor Website Builder – more than just a page builder / 3.21.4
Elementor Website Builder – more than just a page builder v3.21.4
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 / counter.php

counter.php in Elementor Website Builder – more than just a page builder 3.21.4, at includes/widgets/counter.php

692 lines 16.8 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 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
10
11 /**
12 * Elementor counter widget.
13 *
14 * Elementor widget that displays stats and numbers in an escalating manner.
15 *
16 * @since 1.0.0
17 */
18 class Widget_Counter extends Widget_Base {
19
20 /**
21 * Get widget name.
22 *
23 * Retrieve counter 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 'counter';
32 }
33
34 /**
35 * Get widget title.
36 *
37 * Retrieve counter 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__( 'Counter', 'elementor' );
46 }
47
48 /**
49 * Get widget icon.
50 *
51 * Retrieve counter 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-counter';
60 }
61
62 /**
63 * Retrieve the list of scripts the counter widget depended on.
64 *
65 * Used to set scripts dependencies required to run the widget.
66 *
67 * @since 1.3.0
68 * @access public
69 *
70 * @return array Widget scripts dependencies.
71 */
72 public function get_script_depends() {
73 return [ 'jquery-numerator' ];
74 }
75
76 /**
77 * Get widget keywords.
78 *
79 * Retrieve the list of keywords the widget belongs to.
80 *
81 * @since 2.1.0
82 * @access public
83 *
84 * @return array Widget keywords.
85 */
86 public function get_keywords() {
87 return [ 'counter' ];
88 }
89
90 /**
91 * Register counter widget controls.
92 *
93 * Adds different input fields to allow the user to change and customize the widget settings.
94 *
95 * @since 3.1.0
96 * @access protected
97 */
98 protected function register_controls() {
99 $start = is_rtl() ? 'right' : 'left';
100 $end = ! is_rtl() ? 'right' : 'left';
101
102 $this->start_controls_section(
103 'section_counter',
104 [
105 'label' => esc_html__( 'Counter', 'elementor' ),
106 ]
107 );
108
109 $this->add_control(
110 'starting_number',
111 [
112 'label' => esc_html__( 'Starting Number', 'elementor' ),
113 'type' => Controls_Manager::NUMBER,
114 'default' => 0,
115 'dynamic' => [
116 'active' => true,
117 ],
118 ]
119 );
120
121 $this->add_control(
122 'ending_number',
123 [
124 'label' => esc_html__( 'Ending Number', 'elementor' ),
125 'type' => Controls_Manager::NUMBER,
126 'default' => 100,
127 'dynamic' => [
128 'active' => true,
129 ],
130 ]
131 );
132
133 $this->add_control(
134 'prefix',
135 [
136 'label' => esc_html__( 'Number Prefix', 'elementor' ),
137 'type' => Controls_Manager::TEXT,
138 'dynamic' => [
139 'active' => true,
140 ],
141 'ai' => [
142 'active' => false,
143 ],
144 'default' => '',
145 ]
146 );
147
148 $this->add_control(
149 'suffix',
150 [
151 'label' => esc_html__( 'Number Suffix', 'elementor' ),
152 'type' => Controls_Manager::TEXT,
153 'dynamic' => [
154 'active' => true,
155 ],
156 'ai' => [
157 'active' => false,
158 ],
159 'default' => '',
160 ]
161 );
162
163 $this->add_control(
164 'duration',
165 [
166 'label' => esc_html__( 'Animation Duration', 'elementor' ) . ' (ms)',
167 'type' => Controls_Manager::NUMBER,
168 'default' => 2000,
169 'min' => 100,
170 'step' => 100,
171 ]
172 );
173
174 $this->add_control(
175 'thousand_separator',
176 [
177 'label' => esc_html__( 'Thousand Separator', 'elementor' ),
178 'type' => Controls_Manager::SWITCHER,
179 'default' => 'yes',
180 'label_on' => esc_html__( 'Show', 'elementor' ),
181 'label_off' => esc_html__( 'Hide', 'elementor' ),
182 ]
183 );
184
185 $this->add_control(
186 'thousand_separator_char',
187 [
188 'label' => esc_html__( 'Separator', 'elementor' ),
189 'type' => Controls_Manager::SELECT,
190 'condition' => [
191 'thousand_separator' => 'yes',
192 ],
193 'options' => [
194 '' => 'Default',
195 '.' => 'Dot',
196 ' ' => 'Space',
197 '_' => 'Underline',
198 "'" => 'Apostrophe',
199 ],
200 ]
201 );
202
203 $this->add_control(
204 'title',
205 [
206 'label' => esc_html__( 'Title', 'elementor' ),
207 'type' => Controls_Manager::TEXT,
208 'label_block' => true,
209 'separator' => 'before',
210 'dynamic' => [
211 'active' => true,
212 ],
213 'default' => esc_html__( 'Cool Number', 'elementor' ),
214 ]
215 );
216
217 $this->add_control(
218 'title_tag',
219 [
220 'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
221 'type' => Controls_Manager::SELECT,
222 'options' => [
223 'h1' => 'H1',
224 'h2' => 'H2',
225 'h3' => 'H3',
226 'h4' => 'H4',
227 'h5' => 'H5',
228 'h6' => 'H6',
229 'div' => 'div',
230 'span' => 'span',
231 'p' => 'p',
232 ],
233 'default' => 'div',
234 'condition' => [
235 'title!' => '',
236 ],
237 ]
238 );
239
240 $this->end_controls_section();
241
242 $this->start_controls_section(
243 'section_counter_style',
244 [
245 'label' => esc_html__( 'Counter', 'elementor' ),
246 'tab' => Controls_Manager::TAB_STYLE,
247 ]
248 );
249
250 $this->add_responsive_control(
251 'title_position',
252 [
253 'label' => esc_html__( 'Title Position', 'elementor' ),
254 'type' => Controls_Manager::CHOOSE,
255 'options' => [
256 'before' => [
257 'title' => esc_html__( 'Before', 'elementor' ),
258 'icon' => 'eicon-v-align-top',
259 ],
260 'after' => [
261 'title' => esc_html__( 'After', 'elementor' ),
262 'icon' => 'eicon-v-align-bottom',
263 ],
264
265 'start' => [
266 'title' => esc_html__( 'Start', 'elementor' ),
267 'icon' => "eicon-h-align-$start",
268 ],
269 'end' => [
270 'title' => esc_html__( 'End', 'elementor' ),
271 'icon' => "eicon-h-align-$end",
272 ],
273 ],
274 'selectors_dictionary' => [
275 'before' => 'flex-direction: column;',
276 'after' => 'flex-direction: column-reverse;',
277 'start' => 'flex-direction: row;',
278 'end' => 'flex-direction: row-reverse;',
279 ],
280 'selectors' => [
281 '{{WRAPPER}} .elementor-counter' => '{{VALUE}}',
282 ],
283 'condition' => [
284 'title!' => '',
285 ],
286 ]
287 );
288
289 $this->add_responsive_control(
290 'title_horizontal_alignment',
291 [
292 'label' => esc_html__( 'Title Horizontal Alignment', 'elementor' ),
293 'type' => Controls_Manager::CHOOSE,
294 'options' => [
295 'start' => [
296 'title' => esc_html__( 'Start', 'elementor' ),
297 'icon' => "eicon-h-align-$start",
298 ],
299 'center' => [
300 'title' => esc_html__( 'Center', 'elementor' ),
301 'icon' => 'eicon-h-align-center',
302 ],
303 'end' => [
304 'title' => esc_html__( 'End', 'elementor' ),
305 'icon' => "eicon-h-align-$end",
306 ],
307 ],
308 'separator' => 'before',
309 'selectors' => [
310 '{{WRAPPER}} .elementor-counter-title' => 'justify-content: {{VALUE}};',
311 ],
312 'condition' => [
313 'title!' => '',
314 ],
315 ]
316 );
317
318 $this->add_responsive_control(
319 'title_vertical_alignment',
320 [
321 'label' => esc_html__( 'Title Vertical Alignment', 'elementor' ),
322 'type' => Controls_Manager::CHOOSE,
323 'options' => [
324 'start' => [
325 'title' => esc_html__( 'Top', 'elementor' ),
326 'icon' => 'eicon-v-align-top',
327 ],
328 'center' => [
329 'title' => esc_html__( 'Middle', 'elementor' ),
330 'icon' => 'eicon-v-align-middle',
331 ],
332 'end' => [
333 'title' => esc_html__( 'Bottom', 'elementor' ),
334 'icon' => 'eicon-v-align-bottom',
335 ],
336 ],
337 'selectors' => [
338 '{{WRAPPER}} .elementor-counter-title' => 'align-items: {{VALUE}};',
339 ],
340 'condition' => [
341 'title!' => '',
342 'title_position' => [ 'start', 'end' ],
343 ],
344 ]
345 );
346
347 $this->add_responsive_control(
348 'title_gap',
349 [
350 'label' => esc_html__( 'Title Gap', 'elementor' ),
351 'type' => Controls_Manager::SLIDER,
352 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
353 'selectors' => [
354 '{{WRAPPER}} .elementor-counter' => 'gap: {{SIZE}}{{UNIT}};',
355 ],
356 'condition' => [
357 'title!' => '',
358 'title_position' => [ '', 'before', 'after' ],
359 ],
360 ]
361 );
362
363 $this->add_responsive_control(
364 'number_position',
365 [
366 'label' => esc_html__( 'Number Position', 'elementor' ),
367 'type' => Controls_Manager::CHOOSE,
368 'options' => [
369 'start' => [
370 'title' => esc_html__( 'Start', 'elementor' ),
371 'icon' => "eicon-h-align-$start",
372 ],
373 'center' => [
374 'title' => esc_html__( 'Center', 'elementor' ),
375 'icon' => 'eicon-h-align-center',
376 ],
377 'end' => [
378 'title' => esc_html__( 'End', 'elementor' ),
379 'icon' => "eicon-h-align-$end",
380 ],
381 'stretch' => [
382 'title' => esc_html__( 'Stretch', 'elementor' ),
383 'icon' => 'eicon-grow',
384 ],
385 ],
386 'selectors_dictionary' => [
387 'start' => 'text-align: {{VALUE}}; --counter-prefix-grow: 0; --counter-suffix-grow: 1; --counter-number-grow: 0;',
388 'center' => 'text-align: {{VALUE}}; --counter-prefix-grow: 1; --counter-suffix-grow: 1; --counter-number-grow: 0;',
389 'end' => 'text-align: {{VALUE}}; --counter-prefix-grow: 1; --counter-suffix-grow: 0; --counter-number-grow: 0;',
390 'stretch' => '--counter-prefix-grow: 0; --counter-suffix-grow: 0; --counter-number-grow: 1;',
391 ],
392 'selectors' => [
393 '{{WRAPPER}} .elementor-counter-number-wrapper' => '{{VALUE}}',
394 ],
395 'separator' => 'before',
396 ]
397 );
398
399 $this->add_responsive_control(
400 'number_alignment',
401 [
402 'label' => esc_html__( 'Number Alignment', 'elementor' ),
403 'type' => Controls_Manager::CHOOSE,
404 'options' => [
405 'start' => [
406 'title' => esc_html__( 'Start', 'elementor' ),
407 'icon' => "eicon-text-align-$start",
408 ],
409 'center' => [
410 'title' => esc_html__( 'Center', 'elementor' ),
411 'icon' => 'eicon-text-align-center',
412 ],
413 'end' => [
414 'title' => esc_html__( 'End', 'elementor' ),
415 'icon' => "eicon-text-align-$end",
416 ],
417 ],
418 'selectors' => [
419 '{{WRAPPER}} .elementor-counter-number' => 'text-align: {{VALUE}};',
420 ],
421 'condition' => [
422 'number_position' => 'stretch',
423 ],
424 ]
425 );
426
427 $this->add_responsive_control(
428 'number_gap',
429 [
430 'label' => esc_html__( 'Number Gap', 'elementor' ),
431 'type' => Controls_Manager::SLIDER,
432 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
433 'selectors' => [
434 '{{WRAPPER}} .elementor-counter-number-wrapper' => 'gap: {{SIZE}}{{UNIT}};',
435 ],
436 'conditions' => [
437 'relation' => 'and',
438 'terms' => [
439 [
440 'name' => 'number_position',
441 'operator' => '!==',
442 'value' => 'stretch',
443 ],
444 [
445 'relation' => 'or',
446 'terms' => [
447 [
448 'name' => 'prefix',
449 'operator' => '!==',
450 'value' => '',
451 ],
452 [
453 'name' => 'suffix',
454 'operator' => '!==',
455 'value' => '',
456 ],
457 ],
458 ],
459 ],
460 ],
461 ]
462 );
463
464 $this->end_controls_section();
465
466 $this->start_controls_section(
467 'section_number',
468 [
469 'label' => esc_html__( 'Number', 'elementor' ),
470 'tab' => Controls_Manager::TAB_STYLE,
471 ]
472 );
473
474 $this->add_control(
475 'number_color',
476 [
477 'label' => esc_html__( 'Text Color', 'elementor' ),
478 'type' => Controls_Manager::COLOR,
479 'global' => [
480 'default' => Global_Colors::COLOR_PRIMARY,
481 ],
482 'selectors' => [
483 '{{WRAPPER}} .elementor-counter-number-wrapper' => 'color: {{VALUE}};',
484 ],
485 ]
486 );
487
488 $this->add_group_control(
489 Group_Control_Typography::get_type(),
490 [
491 'name' => 'typography_number',
492 'global' => [
493 'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
494 ],
495 'selector' => '{{WRAPPER}} .elementor-counter-number-wrapper',
496 ]
497 );
498
499 $this->add_group_control(
500 Group_Control_Text_Stroke::get_type(),
501 [
502 'name' => 'number_stroke',
503 'selector' => '{{WRAPPER}} .elementor-counter-number-wrapper',
504 ]
505 );
506
507 $this->add_group_control(
508 Group_Control_Text_Shadow::get_type(),
509 [
510 'name' => 'number_shadow',
511 'selector' => '{{WRAPPER}} .elementor-counter-number-wrapper',
512 ]
513 );
514
515 $this->end_controls_section();
516
517 $this->start_controls_section(
518 'section_title',
519 [
520 'label' => esc_html__( 'Title', 'elementor' ),
521 'tab' => Controls_Manager::TAB_STYLE,
522 'condition' => [
523 'title!' => '',
524 ],
525 ]
526 );
527
528 $this->add_control(
529 'title_color',
530 [
531 'label' => esc_html__( 'Text Color', 'elementor' ),
532 'type' => Controls_Manager::COLOR,
533 'global' => [
534 'default' => Global_Colors::COLOR_SECONDARY,
535 ],
536 'selectors' => [
537 '{{WRAPPER}} .elementor-counter-title' => 'color: {{VALUE}};',
538 ],
539 'condition' => [
540 'title!' => '',
541 ],
542 ]
543 );
544
545 $this->add_group_control(
546 Group_Control_Typography::get_type(),
547 [
548 'name' => 'typography_title',
549 'global' => [
550 'default' => Global_Typography::TYPOGRAPHY_SECONDARY,
551 ],
552 'selector' => '{{WRAPPER}} .elementor-counter-title',
553 'condition' => [
554 'title!' => '',
555 ],
556 ]
557 );
558
559 $this->add_group_control(
560 Group_Control_Text_Stroke::get_type(),
561 [
562 'name' => 'title_stroke',
563 'selector' => '{{WRAPPER}} .elementor-counter-title',
564 'condition' => [
565 'title!' => '',
566 ],
567 ]
568 );
569
570 $this->add_group_control(
571 Group_Control_Text_Shadow::get_type(),
572 [
573 'name' => 'title_shadow',
574 'selector' => '{{WRAPPER}} .elementor-counter-title',
575 'condition' => [
576 'title!' => '',
577 ],
578 ]
579 );
580
581 $this->end_controls_section();
582 }
583
584 /**
585 * Render counter widget output in the editor.
586 *
587 * Written as a Backbone JavaScript template and used to generate the live preview.
588 *
589 * @since 2.9.0
590 * @access protected
591 */
592 protected function content_template() {
593 ?>
594 <#
595 view.addRenderAttribute( 'elementor-counter', 'class', 'elementor-counter' );
596
597 view.addRenderAttribute( 'counter-number', 'class', 'elementor-counter-number-wrapper' );
598
599 view.addRenderAttribute(
600 'counter',
601 {
602 'class': 'elementor-counter-number',
603 'data-duration': settings.duration,
604 'data-to-value': settings.ending_number,
605 'data-from-value': settings.starting_number,
606 }
607 );
608
609 if ( settings.thousand_separator ) {
610 const delimiter = settings.thousand_separator_char ? settings.thousand_separator_char : ',';
611 view.addRenderAttribute( 'counter', 'data-delimiter', delimiter );
612 }
613
614 view.addRenderAttribute( 'prefix', 'class', 'elementor-counter-number-prefix' );
615
616 view.addRenderAttribute( 'suffix', 'class', 'elementor-counter-number-suffix' );
617
618 view.addRenderAttribute( 'counter-title', 'class', 'elementor-counter-title' );
619
620 view.addInlineEditingAttributes( 'counter-title' );
621
622 const titleTag = elementor.helpers.validateHTMLTag( settings.title_tag );
623 #>
624 <div {{{ view.getRenderAttributeString( 'elementor-counter' ) }}}>
625 <# if ( settings.title ) {
626 #><{{ titleTag }} {{{ view.getRenderAttributeString( 'counter-title' ) }}}>{{{ settings.title }}}</{{ titleTag }}><#
627 } #>
628 <div {{{ view.getRenderAttributeString( 'counter-number' ) }}}>
629 <span {{{ view.getRenderAttributeString( 'prefix' ) }}}>{{{ settings.prefix }}}</span>
630 <span {{{ view.getRenderAttributeString( 'counter' ) }}}>{{{ settings.starting_number }}}</span>
631 <span {{{ view.getRenderAttributeString( 'suffix' ) }}}>{{{ settings.suffix }}}</span>
632 </div>
633 </div>
634 <?php
635 }
636
637 /**
638 * Render counter widget output on the frontend.
639 *
640 * Written in PHP and used to generate the final HTML.
641 *
642 * @since 1.0.0
643 * @access protected
644 */
645 protected function render() {
646 $settings = $this->get_settings_for_display();
647
648 $this->add_render_attribute( 'elementor-counter', 'class', 'elementor-counter' );
649
650 $this->add_render_attribute( 'counter-number', 'class', 'elementor-counter-number-wrapper' );
651
652 $this->add_render_attribute(
653 'counter',
654 [
655 'class' => 'elementor-counter-number',
656 'data-duration' => $settings['duration'],
657 'data-to-value' => $settings['ending_number'],
658 'data-from-value' => $settings['starting_number'],
659 ]
660 );
661
662 if ( ! empty( $settings['thousand_separator'] ) ) {
663 $delimiter = empty( $settings['thousand_separator_char'] ) ? ',' : $settings['thousand_separator_char'];
664 $this->add_render_attribute( 'counter', 'data-delimiter', $delimiter );
665 }
666
667 $this->add_render_attribute( 'prefix', 'class', 'elementor-counter-number-prefix' );
668
669 $this->add_render_attribute( 'suffix', 'class', 'elementor-counter-number-suffix' );
670
671 $this->add_render_attribute( 'counter-title', 'class', 'elementor-counter-title' );
672
673 $this->add_inline_editing_attributes( 'counter-title' );
674
675 $title_tag = Utils::validate_html_tag( $settings['title_tag'] );
676 ?>
677 <div <?php $this->print_render_attribute_string( 'elementor-counter' ); ?>>
678 <?php
679 if ( $settings['title'] ) :
680 ?><<?php Utils::print_validated_html_tag( $title_tag ); ?> <?php $this->print_render_attribute_string( 'counter-title' ); ?>><?php $this->print_unescaped_setting( 'title' ); ?></<?php Utils::print_validated_html_tag( $title_tag ); ?>><?php
681 endif;
682 ?>
683 <div <?php $this->print_render_attribute_string( 'counter-number' ); ?>>
684 <span <?php $this->print_render_attribute_string( 'prefix' ); ?>><?php $this->print_unescaped_setting( 'prefix' ); ?></span>
685 <span <?php $this->print_render_attribute_string( 'counter' ); ?>><?php $this->print_unescaped_setting( 'starting_number' ); ?></span>
686 <span <?php $this->print_render_attribute_string( 'suffix' ); ?>><?php $this->print_unescaped_setting( 'suffix' ); ?></span>
687 </div>
688 </div>
689 <?php
690 }
691 }
692