PluginProbe
Elementor Website Builder – more than just a page builder / 3.13.1
Elementor Website Builder – more than just a page builder v3.13.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.13.1, at includes/widgets/video.php

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