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

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