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

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