PluginProbe
Elementor Website Builder – more than just a page builder / 3.22.0-dev4
Elementor Website Builder – more than just a page builder v3.22.0-dev4
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.22.0-dev4, at includes/widgets/counter.php

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