PluginProbe
Elementor Website Builder – more than just a page builder / 3.9.1
Elementor Website Builder – more than just a page builder v3.9.1
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 / video.php

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

1,244 lines 29.3 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 use Elementor\Modules\DynamicTags\Module as TagsModule;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit; // Exit if accessed directly.
8 }
9
10 /**
11 * Elementor video widget.
12 *
13 * Elementor widget that displays a video player.
14 *
15 * @since 1.0.0
16 */
17 class Widget_Video extends Widget_Base {
18
19 /**
20 * Get widget name.
21 *
22 * Retrieve video widget name.
23 *
24 * @since 1.0.0
25 * @access public
26 *
27 * @return string Widget name.
28 */
29 public function get_name() {
30 return 'video';
31 }
32
33 /**
34 * Get widget title.
35 *
36 * Retrieve video widget title.
37 *
38 * @since 1.0.0
39 * @access public
40 *
41 * @return string Widget title.
42 */
43 public function get_title() {
44 return esc_html__( 'Video', 'elementor' );
45 }
46
47 /**
48 * Get widget icon.
49 *
50 * Retrieve video widget icon.
51 *
52 * @since 1.0.0
53 * @access public
54 *
55 * @return string Widget icon.
56 */
57 public function get_icon() {
58 return 'eicon-youtube';
59 }
60
61 /**
62 * Get widget categories.
63 *
64 * Retrieve the list of categories the video widget belongs to.
65 *
66 * Used to determine where to display the widget in the editor.
67 *
68 * @since 2.0.0
69 * @access public
70 *
71 * @return array Widget categories.
72 */
73 public function get_categories() {
74 return [ 'basic' ];
75 }
76
77 /**
78 * Get widget keywords.
79 *
80 * Retrieve the list of keywords the widget belongs to.
81 *
82 * @since 2.1.0
83 * @access public
84 *
85 * @return array Widget keywords.
86 */
87 public function get_keywords() {
88 return [ 'video', 'player', 'embed', 'youtube', 'vimeo', 'dailymotion' ];
89 }
90
91 /**
92 * Register video widget controls.
93 *
94 * Adds different input fields to allow the user to change and customize the widget settings.
95 *
96 * @since 3.1.0
97 * @access protected
98 */
99 protected function register_controls() {
100 $this->start_controls_section(
101 'section_video',
102 [
103 'label' => esc_html__( 'Video', 'elementor' ),
104 ]
105 );
106
107 $this->add_control(
108 'video_type',
109 [
110 'label' => esc_html__( 'Source', 'elementor' ),
111 'type' => Controls_Manager::SELECT,
112 'default' => 'youtube',
113 'options' => [
114 'youtube' => esc_html__( 'YouTube', 'elementor' ),
115 'vimeo' => esc_html__( 'Vimeo', 'elementor' ),
116 'dailymotion' => esc_html__( 'Dailymotion', 'elementor' ),
117 'hosted' => esc_html__( 'Self Hosted', 'elementor' ),
118 ],
119 'frontend_available' => true,
120 ]
121 );
122
123 $this->add_control(
124 'youtube_url',
125 [
126 'label' => esc_html__( 'Link', 'elementor' ),
127 'type' => Controls_Manager::TEXT,
128 'dynamic' => [
129 'active' => true,
130 'categories' => [
131 TagsModule::POST_META_CATEGORY,
132 TagsModule::URL_CATEGORY,
133 ],
134 ],
135 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (YouTube)',
136 'default' => 'https://www.youtube.com/watch?v=XHOmBV4js_E',
137 'label_block' => true,
138 'condition' => [
139 'video_type' => 'youtube',
140 ],
141 'frontend_available' => true,
142 ]
143 );
144
145 $this->add_control(
146 'vimeo_url',
147 [
148 'label' => esc_html__( 'Link', 'elementor' ),
149 'type' => Controls_Manager::TEXT,
150 'dynamic' => [
151 'active' => true,
152 'categories' => [
153 TagsModule::POST_META_CATEGORY,
154 TagsModule::URL_CATEGORY,
155 ],
156 ],
157 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (Vimeo)',
158 'default' => 'https://vimeo.com/235215203',
159 'label_block' => true,
160 'condition' => [
161 'video_type' => 'vimeo',
162 ],
163 ]
164 );
165
166 $this->add_control(
167 'dailymotion_url',
168 [
169 'label' => esc_html__( 'Link', 'elementor' ),
170 'type' => Controls_Manager::TEXT,
171 'dynamic' => [
172 'active' => true,
173 'categories' => [
174 TagsModule::POST_META_CATEGORY,
175 TagsModule::URL_CATEGORY,
176 ],
177 ],
178 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ) . ' (Dailymotion)',
179 'default' => 'https://www.dailymotion.com/video/x6tqhqb',
180 'label_block' => true,
181 'condition' => [
182 'video_type' => 'dailymotion',
183 ],
184 ]
185 );
186
187 $this->add_control(
188 'insert_url',
189 [
190 'label' => esc_html__( 'External URL', 'elementor' ),
191 'type' => Controls_Manager::SWITCHER,
192 'condition' => [
193 'video_type' => 'hosted',
194 ],
195 ]
196 );
197
198 $this->add_control(
199 'hosted_url',
200 [
201 'label' => esc_html__( 'Choose File', 'elementor' ),
202 'type' => Controls_Manager::MEDIA,
203 'dynamic' => [
204 'active' => true,
205 'categories' => [
206 TagsModule::MEDIA_CATEGORY,
207 ],
208 ],
209 'media_type' => 'video',
210 'condition' => [
211 'video_type' => 'hosted',
212 'insert_url' => '',
213 ],
214 ]
215 );
216
217 $this->add_control(
218 'external_url',
219 [
220 'label' => esc_html__( 'URL', 'elementor' ),
221 'type' => Controls_Manager::URL,
222 'autocomplete' => false,
223 'options' => false,
224 'label_block' => true,
225 'show_label' => false,
226 'dynamic' => [
227 'active' => true,
228 'categories' => [
229 TagsModule::POST_META_CATEGORY,
230 TagsModule::URL_CATEGORY,
231 ],
232 ],
233 'media_type' => 'video',
234 'placeholder' => esc_html__( 'Enter your URL', 'elementor' ),
235 'condition' => [
236 'video_type' => 'hosted',
237 'insert_url' => 'yes',
238 ],
239 ]
240 );
241
242 $this->add_control(
243 'start',
244 [
245 'label' => esc_html__( 'Start Time', 'elementor' ),
246 'type' => Controls_Manager::NUMBER,
247 'description' => esc_html__( 'Specify a start time (in seconds)', 'elementor' ),
248 'frontend_available' => true,
249 ]
250 );
251
252 $this->add_control(
253 'end',
254 [
255 'label' => esc_html__( 'End Time', 'elementor' ),
256 'type' => Controls_Manager::NUMBER,
257 'description' => esc_html__( 'Specify an end time (in seconds)', 'elementor' ),
258 'condition' => [
259 'video_type' => [ 'youtube', 'hosted' ],
260 ],
261 'frontend_available' => true,
262 ]
263 );
264
265 $this->add_control(
266 'video_options',
267 [
268 'label' => esc_html__( 'Video Options', 'elementor' ),
269 'type' => Controls_Manager::HEADING,
270 'separator' => 'before',
271 ]
272 );
273
274 $this->add_control(
275 'autoplay',
276 [
277 'label' => esc_html__( 'Autoplay', 'elementor' ),
278 'type' => Controls_Manager::SWITCHER,
279 'frontend_available' => true,
280 'conditions' => [
281 'relation' => 'or',
282 'terms' => [
283 [
284 'name' => 'show_image_overlay',
285 'value' => '',
286 ],
287 [
288 'name' => 'image_overlay[url]',
289 'value' => '',
290 ],
291 ],
292 ],
293 ]
294 );
295
296 $this->add_control(
297 'play_on_mobile',
298 [
299 'label' => esc_html__( 'Play On Mobile', 'elementor' ),
300 'type' => Controls_Manager::SWITCHER,
301 'condition' => [
302 'autoplay' => 'yes',
303 ],
304 'frontend_available' => true,
305 ]
306 );
307
308 $this->add_control(
309 'mute',
310 [
311 'label' => esc_html__( 'Mute', 'elementor' ),
312 'type' => Controls_Manager::SWITCHER,
313 'frontend_available' => true,
314 ]
315 );
316
317 $this->add_control(
318 'loop',
319 [
320 'label' => esc_html__( 'Loop', 'elementor' ),
321 'type' => Controls_Manager::SWITCHER,
322 'condition' => [
323 'video_type!' => 'dailymotion',
324 ],
325 'frontend_available' => true,
326 ]
327 );
328
329 $this->add_control(
330 'controls',
331 [
332 'label' => esc_html__( 'Player Controls', 'elementor' ),
333 'type' => Controls_Manager::SWITCHER,
334 'label_off' => esc_html__( 'Hide', 'elementor' ),
335 'label_on' => esc_html__( 'Show', 'elementor' ),
336 'default' => 'yes',
337 'condition' => [
338 'video_type!' => 'vimeo',
339 ],
340 'frontend_available' => true,
341 ]
342 );
343
344 $this->add_control(
345 'showinfo',
346 [
347 'label' => esc_html__( 'Video Info', 'elementor' ),
348 'type' => Controls_Manager::SWITCHER,
349 'label_off' => esc_html__( 'Hide', 'elementor' ),
350 'label_on' => esc_html__( 'Show', 'elementor' ),
351 'default' => 'yes',
352 'condition' => [
353 'video_type' => [ 'dailymotion' ],
354 ],
355 ]
356 );
357
358 $this->add_control(
359 'modestbranding',
360 [
361 'label' => esc_html__( 'Modest Branding', 'elementor' ),
362 'type' => Controls_Manager::SWITCHER,
363 'condition' => [
364 'video_type' => [ 'youtube' ],
365 'controls' => 'yes',
366 ],
367 'frontend_available' => true,
368 ]
369 );
370
371 $this->add_control(
372 'logo',
373 [
374 'label' => esc_html__( 'Logo', 'elementor' ),
375 'type' => Controls_Manager::SWITCHER,
376 'label_off' => esc_html__( 'Hide', 'elementor' ),
377 'label_on' => esc_html__( 'Show', 'elementor' ),
378 'default' => 'yes',
379 'condition' => [
380 'video_type' => [ 'dailymotion' ],
381 ],
382 ]
383 );
384
385 // YouTube.
386 $this->add_control(
387 'yt_privacy',
388 [
389 'label' => esc_html__( 'Privacy Mode', 'elementor' ),
390 'type' => Controls_Manager::SWITCHER,
391 'description' => esc_html__( 'When you turn on privacy mode, YouTube/Vimeo won\'t store information about visitors on your website unless they play the video.', 'elementor' ),
392 'condition' => [
393 'video_type' => [ 'youtube', 'vimeo' ],
394 ],
395 'frontend_available' => true,
396 ]
397 );
398
399 $this->add_control(
400 'lazy_load',
401 [
402 'label' => esc_html__( 'Lazy Load', 'elementor' ),
403 'type' => Controls_Manager::SWITCHER,
404 'conditions' => [
405 'relation' => 'or',
406 'terms' => [
407 [
408 'name' => 'video_type',
409 'operator' => '===',
410 'value' => 'youtube',
411 ],
412 [
413 'relation' => 'and',
414 'terms' => [
415 [
416 'name' => 'show_image_overlay',
417 'operator' => '===',
418 'value' => 'yes',
419 ],
420 [
421 'name' => 'video_type',
422 'operator' => '!==',
423 'value' => 'hosted',
424 ],
425 ],
426 ],
427 ],
428 ],
429 'frontend_available' => true,
430 ]
431 );
432
433 $this->add_control(
434 'rel',
435 [
436 'label' => esc_html__( 'Suggested Videos', 'elementor' ),
437 'type' => Controls_Manager::SELECT,
438 'options' => [
439 '' => esc_html__( 'Current Video Channel', 'elementor' ),
440 'yes' => esc_html__( 'Any Video', 'elementor' ),
441 ],
442 'condition' => [
443 'video_type' => 'youtube',
444 ],
445 ]
446 );
447
448 // Vimeo.
449 $this->add_control(
450 'vimeo_title',
451 [
452 'label' => esc_html__( 'Intro Title', 'elementor' ),
453 'type' => Controls_Manager::SWITCHER,
454 'label_off' => esc_html__( 'Hide', 'elementor' ),
455 'label_on' => esc_html__( 'Show', 'elementor' ),
456 'default' => 'yes',
457 'condition' => [
458 'video_type' => 'vimeo',
459 ],
460 ]
461 );
462
463 $this->add_control(
464 'vimeo_portrait',
465 [
466 'label' => esc_html__( 'Intro Portrait', 'elementor' ),
467 'type' => Controls_Manager::SWITCHER,
468 'label_off' => esc_html__( 'Hide', 'elementor' ),
469 'label_on' => esc_html__( 'Show', 'elementor' ),
470 'default' => 'yes',
471 'condition' => [
472 'video_type' => 'vimeo',
473 ],
474 ]
475 );
476
477 $this->add_control(
478 'vimeo_byline',
479 [
480 'label' => esc_html__( 'Intro Byline', 'elementor' ),
481 'type' => Controls_Manager::SWITCHER,
482 'label_off' => esc_html__( 'Hide', 'elementor' ),
483 'label_on' => esc_html__( 'Show', 'elementor' ),
484 'default' => 'yes',
485 'condition' => [
486 'video_type' => 'vimeo',
487 ],
488 ]
489 );
490
491 $this->add_control(
492 'color',
493 [
494 'label' => esc_html__( 'Controls Color', 'elementor' ),
495 'type' => Controls_Manager::COLOR,
496 'default' => '',
497 'condition' => [
498 'video_type' => [ 'vimeo', 'dailymotion' ],
499 ],
500 ]
501 );
502
503 $this->add_control(
504 'download_button',
505 [
506 'label' => esc_html__( 'Download Button', 'elementor' ),
507 'type' => Controls_Manager::SWITCHER,
508 'label_off' => esc_html__( 'Hide', 'elementor' ),
509 'label_on' => esc_html__( 'Show', 'elementor' ),
510 'condition' => [
511 'video_type' => 'hosted',
512 ],
513 ]
514 );
515
516 $this->add_control(
517 'poster',
518 [
519 'label' => esc_html__( 'Poster', 'elementor' ),
520 'type' => Controls_Manager::MEDIA,
521 'dynamic' => [
522 'active' => true,
523 ],
524 'condition' => [
525 'video_type' => 'hosted',
526 ],
527 ]
528 );
529
530 $this->add_control(
531 'view',
532 [
533 'label' => esc_html__( 'View', 'elementor' ),
534 'type' => Controls_Manager::HIDDEN,
535 'default' => 'youtube',
536 ]
537 );
538
539 $this->end_controls_section();
540
541 $this->start_controls_section(
542 'section_image_overlay',
543 [
544 'label' => esc_html__( 'Image Overlay', 'elementor' ),
545 ]
546 );
547
548 $this->add_control(
549 'show_image_overlay',
550 [
551 'label' => esc_html__( 'Image Overlay', 'elementor' ),
552 'type' => Controls_Manager::SWITCHER,
553 'label_off' => esc_html__( 'Hide', 'elementor' ),
554 'label_on' => esc_html__( 'Show', 'elementor' ),
555 'frontend_available' => true,
556 ]
557 );
558
559 $this->add_control(
560 'image_overlay',
561 [
562 'label' => esc_html__( 'Choose Image', 'elementor' ),
563 'type' => Controls_Manager::MEDIA,
564 'default' => [
565 'url' => Utils::get_placeholder_image_src(),
566 ],
567 'dynamic' => [
568 'active' => true,
569 ],
570 'condition' => [
571 'show_image_overlay' => 'yes',
572 ],
573 'frontend_available' => true,
574 ]
575 );
576
577 $this->add_group_control(
578 Group_Control_Image_Size::get_type(),
579 [
580 'name' => 'image_overlay', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `image_overlay_size` and `image_overlay_custom_dimension`.
581 'default' => 'full',
582 'separator' => 'none',
583 'condition' => [
584 'show_image_overlay' => 'yes',
585 ],
586 ]
587 );
588
589 $this->add_control(
590 'show_play_icon',
591 [
592 'label' => esc_html__( 'Play Icon', 'elementor' ),
593 'type' => Controls_Manager::SWITCHER,
594 'default' => 'yes',
595 'condition' => [
596 'show_image_overlay' => 'yes',
597 'image_overlay[url]!' => '',
598 ],
599 ]
600 );
601
602 $this->add_control(
603 'play_icon',
604 [
605 'label' => esc_html__( 'Icon', 'elementor' ),
606 'type' => Controls_Manager::ICONS,
607 'fa4compatibility' => 'icon',
608 'skin' => 'inline',
609 'label_block' => false,
610 'skin_settings' => [
611 'inline' => [
612 'none' => [
613 'label' => 'Default',
614 'icon' => 'eicon-play',
615 ],
616 'icon' => [
617 'icon' => 'eicon-star',
618 ],
619 ],
620 ],
621 'recommended' => [
622 'fa-regular' => [
623 'play-circle',
624 ],
625 'fa-solid' => [
626 'play',
627 'play-circle',
628 ],
629 ],
630 'condition' => [
631 'show_image_overlay' => 'yes',
632 'show_play_icon!' => '',
633 ],
634 ]
635 );
636
637 $this->add_control(
638 'lightbox',
639 [
640 'label' => esc_html__( 'Lightbox', 'elementor' ),
641 'type' => Controls_Manager::SWITCHER,
642 'frontend_available' => true,
643 'label_off' => esc_html__( 'Off', 'elementor' ),
644 'label_on' => esc_html__( 'On', 'elementor' ),
645 'condition' => [
646 'show_image_overlay' => 'yes',
647 'image_overlay[url]!' => '',
648 ],
649 'separator' => 'before',
650 ]
651 );
652
653 $this->end_controls_section();
654
655 $this->start_controls_section(
656 'section_video_style',
657 [
658 'label' => esc_html__( 'Video', 'elementor' ),
659 'tab' => Controls_Manager::TAB_STYLE,
660 ]
661 );
662
663 $this->add_control(
664 'aspect_ratio',
665 [
666 'label' => esc_html__( 'Aspect Ratio', 'elementor' ),
667 'type' => Controls_Manager::SELECT,
668 'options' => [
669 '169' => '16:9',
670 '219' => '21:9',
671 '43' => '4:3',
672 '32' => '3:2',
673 '11' => '1:1',
674 '916' => '9:16',
675 ],
676 'default' => '169',
677 'prefix_class' => 'elementor-aspect-ratio-',
678 'frontend_available' => true,
679 ]
680 );
681
682 $this->add_group_control(
683 Group_Control_Css_Filter::get_type(),
684 [
685 'name' => 'css_filters',
686 'selector' => '{{WRAPPER}} .elementor-wrapper',
687 ]
688 );
689
690 $this->add_control(
691 'play_icon_title',
692 [
693 'label' => esc_html__( 'Play Icon', 'elementor' ),
694 'type' => Controls_Manager::HEADING,
695 'condition' => [
696 'show_image_overlay' => 'yes',
697 'show_play_icon' => 'yes',
698 ],
699 'separator' => 'before',
700 ]
701 );
702
703 $this->add_control(
704 'play_icon_color',
705 [
706 'label' => esc_html__( 'Color', 'elementor' ),
707 'type' => Controls_Manager::COLOR,
708 'selectors' => [
709 '{{WRAPPER}} .elementor-custom-embed-play i' => 'color: {{VALUE}}',
710 '{{WRAPPER}} .elementor-custom-embed-play svg' => 'fill: {{VALUE}}',
711 ],
712 'condition' => [
713 'show_image_overlay' => 'yes',
714 'show_play_icon' => 'yes',
715 ],
716 ]
717 );
718
719 $this->add_responsive_control(
720 'play_icon_size',
721 [
722 'label' => esc_html__( 'Size', 'elementor' ),
723 'type' => Controls_Manager::SLIDER,
724 'range' => [
725 'px' => [
726 'min' => 10,
727 'max' => 300,
728 ],
729 ],
730 'selectors' => [
731 // Not using a CSS vars because the default size value is coming from a global scss file.
732 '{{WRAPPER}} .elementor-custom-embed-play i' => 'font-size: {{SIZE}}{{UNIT}}',
733 '{{WRAPPER}} .elementor-custom-embed-play svg' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
734 ],
735 'condition' => [
736 'show_image_overlay' => 'yes',
737 'show_play_icon' => 'yes',
738 ],
739 ]
740 );
741
742 $this->add_group_control(
743 Group_Control_Text_Shadow::get_type(),
744 [
745 'name' => 'play_icon_text_shadow',
746 'selector' => '{{WRAPPER}} .elementor-custom-embed-play i',
747 'fields_options' => [
748 'text_shadow_type' => [
749 'label' => esc_html_x( 'Shadow', 'Text Shadow Control', 'elementor' ),
750 ],
751 ],
752 'condition' => [
753 'show_image_overlay' => 'yes',
754 'show_play_icon' => 'yes',
755 'play_icon[library]!' => 'svg',
756 ],
757 ]
758 );
759
760 $this->end_controls_section();
761
762 $this->start_controls_section(
763 'section_lightbox_style',
764 [
765 'label' => esc_html__( 'Lightbox', 'elementor' ),
766 'tab' => Controls_Manager::TAB_STYLE,
767 'condition' => [
768 'show_image_overlay' => 'yes',
769 'image_overlay[url]!' => '',
770 'lightbox' => 'yes',
771 ],
772 ]
773 );
774
775 $this->add_control(
776 'lightbox_color',
777 [
778 'label' => esc_html__( 'Background Color', 'elementor' ),
779 'type' => Controls_Manager::COLOR,
780 'selectors' => [
781 '#elementor-lightbox-{{ID}}' => 'background-color: {{VALUE}};',
782 ],
783 ]
784 );
785
786 $this->add_control(
787 'lightbox_ui_color',
788 [
789 'label' => esc_html__( 'UI Color', 'elementor' ),
790 'type' => Controls_Manager::COLOR,
791 'selectors' => [
792 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button' => 'color: {{VALUE}}',
793 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button svg' => 'fill: {{VALUE}}',
794 ],
795 ]
796 );
797
798 $this->add_control(
799 'lightbox_ui_color_hover',
800 [
801 'label' => esc_html__( 'UI Hover Color', 'elementor' ),
802 'type' => Controls_Manager::COLOR,
803 'selectors' => [
804 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover' => 'color: {{VALUE}}',
805 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover svg' => 'fill: {{VALUE}}',
806 ],
807 'separator' => 'after',
808 ]
809 );
810
811 $this->add_control(
812 'lightbox_video_width',
813 [
814 'label' => esc_html__( 'Content Width', 'elementor' ),
815 'type' => Controls_Manager::SLIDER,
816 'default' => [
817 'unit' => '%',
818 ],
819 'range' => [
820 '%' => [
821 'min' => 30,
822 ],
823 ],
824 'selectors' => [
825 '(desktop+)#elementor-lightbox-{{ID}} .elementor-video-container' => 'width: {{SIZE}}{{UNIT}};',
826 ],
827 ]
828 );
829
830 $this->add_control(
831 'lightbox_content_position',
832 [
833 'label' => esc_html__( 'Content Position', 'elementor' ),
834 'type' => Controls_Manager::SELECT,
835 'frontend_available' => true,
836 'options' => [
837 '' => esc_html__( 'Center', 'elementor' ),
838 'top' => esc_html__( 'Top', 'elementor' ),
839 ],
840 'selectors' => [
841 '#elementor-lightbox-{{ID}} .elementor-video-container' => '{{VALUE}}; transform: translateX(-50%);',
842 ],
843 'selectors_dictionary' => [
844 'top' => 'top: 60px',
845 ],
846 ]
847 );
848
849 $this->add_responsive_control(
850 'lightbox_content_animation',
851 [
852 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
853 'type' => Controls_Manager::ANIMATION,
854 'frontend_available' => true,
855 ]
856 );
857
858 $this->end_controls_section();
859 }
860
861 public function print_a11y_text( $image_overlay ) {
862 if ( empty( $image_overlay['alt'] ) ) {
863 echo esc_html__( 'Play Video', 'elementor' );
864 } else {
865 echo esc_html__( 'Play Video about', 'elementor' ) . ' ' . esc_attr( $image_overlay['alt'] );
866 }
867 }
868
869 /**
870 * Render video widget output on the frontend.
871 *
872 * Written in PHP and used to generate the final HTML.
873 *
874 * @since 1.0.0
875 * @access protected
876 */
877 protected function render() {
878 $settings = $this->get_settings_for_display();
879
880 $video_url = $settings[ $settings['video_type'] . '_url' ];
881
882 if ( 'hosted' === $settings['video_type'] ) {
883 $video_url = $this->get_hosted_video_url();
884 } else {
885 $embed_params = $this->get_embed_params();
886 $embed_options = $this->get_embed_options();
887 }
888
889 if ( empty( $video_url ) ) {
890 return;
891 }
892
893 if ( 'youtube' === $settings['video_type'] ) {
894 $video_html = '<div class="elementor-video"></div>';
895 }
896
897 if ( 'hosted' === $settings['video_type'] ) {
898 $this->add_render_attribute( 'video-wrapper', 'class', 'e-hosted-video' );
899
900 ob_start();
901
902 $this->render_hosted_video();
903
904 $video_html = ob_get_clean();
905 } else {
906 $is_static_render_mode = Plugin::$instance->frontend->is_static_render_mode();
907 $post_id = get_queried_object_id();
908
909 if ( $is_static_render_mode ) {
910 $video_html = Embed::get_embed_thumbnail_html( $video_url, $post_id );
911 // YouTube API requires a different markup which was set above.
912 } else if ( 'youtube' !== $settings['video_type'] ) {
913 $video_html = Embed::get_embed_html( $video_url, $embed_params, $embed_options );
914 }
915 }
916
917 if ( empty( $video_html ) ) {
918 echo esc_url( $video_url );
919
920 return;
921 }
922
923 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-wrapper' );
924
925 if ( ! $settings['lightbox'] ) {
926 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-fit-aspect-ratio' );
927 }
928
929 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-open-' . ( $settings['lightbox'] ? 'lightbox' : 'inline' ) );
930 ?>
931 <div <?php $this->print_render_attribute_string( 'video-wrapper' ); ?>>
932 <?php
933 if ( ! $settings['lightbox'] ) {
934 Utils::print_unescaped_internal_string( $video_html ); // XSS ok.
935 }
936
937 if ( $this->has_image_overlay() ) {
938 $this->add_render_attribute( 'image-overlay', 'class', 'elementor-custom-embed-image-overlay' );
939
940 if ( $settings['lightbox'] ) {
941 if ( 'hosted' === $settings['video_type'] ) {
942 $lightbox_url = $video_url;
943 } else {
944 $lightbox_url = Embed::get_embed_url( $video_url, $embed_params, $embed_options );
945 }
946
947 $lightbox_options = [
948 'type' => 'video',
949 'videoType' => $settings['video_type'],
950 'url' => $lightbox_url,
951 'modalOptions' => [
952 'id' => 'elementor-lightbox-' . $this->get_id(),
953 'entranceAnimation' => $settings['lightbox_content_animation'],
954 'entranceAnimation_tablet' => $settings['lightbox_content_animation_tablet'],
955 'entranceAnimation_mobile' => $settings['lightbox_content_animation_mobile'],
956 'videoAspectRatio' => $settings['aspect_ratio'],
957 ],
958 ];
959
960 if ( 'hosted' === $settings['video_type'] ) {
961 $lightbox_options['videoParams'] = $this->get_hosted_params();
962 }
963
964 $this->add_render_attribute( 'image-overlay', [
965 'data-elementor-open-lightbox' => 'yes',
966 'data-elementor-lightbox' => wp_json_encode( $lightbox_options ),
967 'e-action-hash' => Plugin::instance()->frontend->create_action_hash( 'lightbox', $lightbox_options ),
968 ] );
969
970 if ( Plugin::$instance->editor->is_edit_mode() ) {
971 $this->add_render_attribute( 'image-overlay', [
972 'class' => 'elementor-clickable',
973 ] );
974 }
975 } else {
976 // When there is an image URL but no ID, it means the overlay image is the placeholder. In this case, get the placeholder URL.
977 if ( empty( $settings['image_overlay']['id'] && ! empty( $settings['image_overlay']['url'] ) ) ) {
978 $image_url = $settings['image_overlay']['url'];
979 } else {
980 $image_url = Group_Control_Image_Size::get_attachment_image_src( $settings['image_overlay']['id'], 'image_overlay', $settings );
981 }
982
983 $this->add_render_attribute( 'image-overlay', 'style', 'background-image: url(' . $image_url . ');' );
984 }
985 ?>
986 <div <?php $this->print_render_attribute_string( 'image-overlay' ); ?>>
987 <?php if ( $settings['lightbox'] ) : ?>
988 <?php Group_Control_Image_Size::print_attachment_image_html( $settings, 'image_overlay' ); ?>
989 <?php endif; ?>
990 <?php if ( 'yes' === $settings['show_play_icon'] ) : ?>
991 <div class="elementor-custom-embed-play" role="button" aria-label="<?php $this->print_a11y_text( $settings['image_overlay'] ); ?>" tabindex="0">
992 <?php
993 if ( empty( $settings['play_icon']['value'] ) ) {
994 $settings['play_icon'] = [
995 'library' => 'eicons',
996 'value' => 'eicon-play',
997 ];
998 }
999 Icons_Manager::render_icon( $settings['play_icon'], [ 'aria-hidden' => 'true' ] );
1000 ?>
1001 <span class="elementor-screen-only"><?php $this->print_a11y_text( $settings['image_overlay'] ); ?></span>
1002 </div>
1003 <?php endif; ?>
1004 </div>
1005 <?php } ?>
1006 </div>
1007 <?php
1008 }
1009
1010 /**
1011 * Render video widget as plain content.
1012 *
1013 * Override the default behavior, by printing the video URL insted of rendering it.
1014 *
1015 * @since 1.4.5
1016 * @access public
1017 */
1018 public function render_plain_content() {
1019 $settings = $this->get_settings_for_display();
1020
1021 if ( 'hosted' !== $settings['video_type'] ) {
1022 $url = $settings[ $settings['video_type'] . '_url' ];
1023 } else {
1024 $url = $this->get_hosted_video_url();
1025 }
1026
1027 echo esc_url( $url );
1028 }
1029
1030 /**
1031 * Get embed params.
1032 *
1033 * Retrieve video widget embed parameters.
1034 *
1035 * @since 1.5.0
1036 * @access public
1037 *
1038 * @return array Video embed parameters.
1039 */
1040 public function get_embed_params() {
1041 $settings = $this->get_settings_for_display();
1042
1043 $params = [];
1044
1045 if ( $settings['autoplay'] && ! $this->has_image_overlay() ) {
1046 $params['autoplay'] = '1';
1047
1048 if ( $settings['play_on_mobile'] ) {
1049 $params['playsinline'] = '1';
1050 }
1051 }
1052
1053 $params_dictionary = [];
1054
1055 if ( 'youtube' === $settings['video_type'] ) {
1056 $params_dictionary = [
1057 'loop',
1058 'controls',
1059 'mute',
1060 'rel',
1061 'modestbranding',
1062 ];
1063
1064 if ( $settings['loop'] ) {
1065 $video_properties = Embed::get_video_properties( $settings['youtube_url'] );
1066
1067 $params['playlist'] = $video_properties['video_id'];
1068 }
1069
1070 $params['start'] = $settings['start'];
1071
1072 $params['end'] = $settings['end'];
1073
1074 $params['wmode'] = 'opaque';
1075 } elseif ( 'vimeo' === $settings['video_type'] ) {
1076 $params_dictionary = [
1077 'loop',
1078 'mute' => 'muted',
1079 'vimeo_title' => 'title',
1080 'vimeo_portrait' => 'portrait',
1081 'vimeo_byline' => 'byline',
1082 ];
1083
1084 $params['color'] = str_replace( '#', '', $settings['color'] );
1085
1086 $params['autopause'] = '0';
1087
1088 if ( ! empty( $settings['yt_privacy'] ) ) {
1089 $params['dnt'] = 'true';
1090 }
1091 } elseif ( 'dailymotion' === $settings['video_type'] ) {
1092 $params_dictionary = [
1093 'controls',
1094 'mute',
1095 'showinfo' => 'ui-start-screen-info',
1096 'logo' => 'ui-logo',
1097 ];
1098
1099 $params['ui-highlight'] = str_replace( '#', '', $settings['color'] );
1100
1101 $params['start'] = $settings['start'];
1102
1103 $params['endscreen-enable'] = '0';
1104 }
1105
1106 foreach ( $params_dictionary as $key => $param_name ) {
1107 $setting_name = $param_name;
1108
1109 if ( is_string( $key ) ) {
1110 $setting_name = $key;
1111 }
1112
1113 $setting_value = $settings[ $setting_name ] ? '1' : '0';
1114
1115 $params[ $param_name ] = $setting_value;
1116 }
1117
1118 return $params;
1119 }
1120
1121 /**
1122 * Whether the video widget has an overlay image or not.
1123 *
1124 * Used to determine whether an overlay image was set for the video.
1125 *
1126 * @since 1.0.0
1127 * @access protected
1128 *
1129 * @return bool Whether an image overlay was set for the video.
1130 */
1131 protected function has_image_overlay() {
1132 $settings = $this->get_settings_for_display();
1133
1134 return ! empty( $settings['image_overlay']['url'] ) && 'yes' === $settings['show_image_overlay'];
1135 }
1136
1137 /**
1138 * @since 2.1.0
1139 * @access private
1140 */
1141 private function get_embed_options() {
1142 $settings = $this->get_settings_for_display();
1143
1144 $embed_options = [];
1145
1146 if ( 'youtube' === $settings['video_type'] ) {
1147 $embed_options['privacy'] = $settings['yt_privacy'];
1148 } elseif ( 'vimeo' === $settings['video_type'] ) {
1149 $embed_options['start'] = $settings['start'];
1150 }
1151
1152 $embed_options['lazy_load'] = ! empty( $settings['lazy_load'] );
1153
1154 return $embed_options;
1155 }
1156
1157 /**
1158 * @since 2.1.0
1159 * @access private
1160 */
1161 private function get_hosted_params() {
1162 $settings = $this->get_settings_for_display();
1163
1164 $video_params = [];
1165
1166 foreach ( [ 'autoplay', 'loop', 'controls' ] as $option_name ) {
1167 if ( $settings[ $option_name ] ) {
1168 $video_params[ $option_name ] = '';
1169 }
1170 }
1171
1172 if ( $settings['mute'] ) {
1173 $video_params['muted'] = 'muted';
1174 }
1175
1176 if ( $settings['play_on_mobile'] ) {
1177 $video_params['playsinline'] = '';
1178 }
1179
1180 if ( ! $settings['download_button'] ) {
1181 $video_params['controlsList'] = 'nodownload';
1182 }
1183
1184 if ( $settings['poster']['url'] ) {
1185 $video_params['poster'] = $settings['poster']['url'];
1186 }
1187
1188 return $video_params;
1189 }
1190
1191 /**
1192 * @param bool $from_media
1193 *
1194 * @return string
1195 * @since 2.1.0
1196 * @access private
1197 */
1198 private function get_hosted_video_url() {
1199 $settings = $this->get_settings_for_display();
1200
1201 if ( ! empty( $settings['insert_url'] ) ) {
1202 $video_url = $settings['external_url']['url'];
1203 } else {
1204 $video_url = $settings['hosted_url']['url'];
1205 }
1206
1207 if ( empty( $video_url ) ) {
1208 return '';
1209 }
1210
1211 if ( $settings['start'] || $settings['end'] ) {
1212 $video_url .= '#t=';
1213 }
1214
1215 if ( $settings['start'] ) {
1216 $video_url .= $settings['start'];
1217 }
1218
1219 if ( $settings['end'] ) {
1220 $video_url .= ',' . $settings['end'];
1221 }
1222
1223 return $video_url;
1224 }
1225
1226 /**
1227 *
1228 * @since 2.1.0
1229 * @access private
1230 */
1231 private function render_hosted_video() {
1232 $video_url = $this->get_hosted_video_url();
1233 if ( empty( $video_url ) ) {
1234 return;
1235 }
1236
1237 $video_params = $this->get_hosted_params();
1238 /* Sometimes the video url is base64, therefore we use `esc_attr` in `src`. */
1239 ?>
1240 <video class="elementor-video" src="<?php echo esc_attr( $video_url ); ?>" <?php Utils::print_html_attributes( $video_params ); ?>></video>
1241 <?php
1242 }
1243 }
1244