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

1,381 lines 33.1 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->end_controls_section();
593
594 $this->start_controls_section(
595 'section_image_overlay',
596 [
597 'label' => esc_html__( 'Image Overlay', 'elementor' ),
598 ]
599 );
600
601 $this->add_control(
602 'show_image_overlay',
603 [
604 'label' => esc_html__( 'Image Overlay', 'elementor' ),
605 'type' => Controls_Manager::SWITCHER,
606 'label_off' => esc_html__( 'Hide', 'elementor' ),
607 'label_on' => esc_html__( 'Show', 'elementor' ),
608 'frontend_available' => true,
609 ]
610 );
611
612 $this->add_control(
613 'image_overlay',
614 [
615 'label' => esc_html__( 'Choose Image', 'elementor' ),
616 'type' => Controls_Manager::MEDIA,
617 'default' => [
618 'url' => Utils::get_placeholder_image_src(),
619 ],
620 'dynamic' => [
621 'active' => true,
622 ],
623 'condition' => [
624 'show_image_overlay' => 'yes',
625 ],
626 'frontend_available' => true,
627 ]
628 );
629
630 $this->add_group_control(
631 Group_Control_Image_Size::get_type(),
632 [
633 'name' => 'image_overlay', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `image_overlay_size` and `image_overlay_custom_dimension`.
634 'default' => 'full',
635 'separator' => 'none',
636 'condition' => [
637 'show_image_overlay' => 'yes',
638 ],
639 ]
640 );
641
642 $this->add_control(
643 'show_play_icon',
644 [
645 'label' => esc_html__( 'Play Icon', 'elementor' ),
646 'type' => Controls_Manager::SWITCHER,
647 'default' => 'yes',
648 'label_off' => esc_html__( 'Hide', 'elementor' ),
649 'label_on' => esc_html__( 'Show', 'elementor' ),
650 'separator' => 'before',
651 'condition' => [
652 'show_image_overlay' => 'yes',
653 'image_overlay[url]!' => '',
654 ],
655 ]
656 );
657
658 $this->add_control(
659 'play_icon',
660 [
661 'label' => esc_html__( 'Icon', 'elementor' ),
662 'type' => Controls_Manager::ICONS,
663 'fa4compatibility' => 'icon',
664 'skin' => 'inline',
665 'label_block' => false,
666 'skin_settings' => [
667 'inline' => [
668 'none' => [
669 'label' => 'Default',
670 'icon' => 'eicon-play',
671 ],
672 'icon' => [
673 'icon' => 'eicon-star',
674 ],
675 ],
676 ],
677 'recommended' => [
678 'fa-regular' => [
679 'play-circle',
680 ],
681 'fa-solid' => [
682 'play',
683 'play-circle',
684 ],
685 ],
686 'condition' => [
687 'show_image_overlay' => 'yes',
688 'show_play_icon!' => '',
689 ],
690 ]
691 );
692
693 $this->add_control(
694 'lightbox',
695 [
696 'label' => esc_html__( 'Lightbox', 'elementor' ),
697 'type' => Controls_Manager::SWITCHER,
698 'frontend_available' => true,
699 'label_off' => esc_html__( 'Off', 'elementor' ),
700 'label_on' => esc_html__( 'On', 'elementor' ),
701 'condition' => [
702 'show_image_overlay' => 'yes',
703 'image_overlay[url]!' => '',
704 ],
705 'separator' => 'before',
706 ]
707 );
708
709 $this->end_controls_section();
710
711 $this->start_controls_section(
712 'section_video_style',
713 [
714 'label' => esc_html__( 'Video', 'elementor' ),
715 'tab' => Controls_Manager::TAB_STYLE,
716 ]
717 );
718
719 $this->add_control(
720 'aspect_ratio',
721 [
722 'label' => esc_html__( 'Aspect Ratio', 'elementor' ),
723 'type' => Controls_Manager::SELECT,
724 'options' => [
725 '169' => '16:9',
726 '219' => '21:9',
727 '43' => '4:3',
728 '32' => '3:2',
729 '11' => '1:1',
730 '916' => '9:16',
731 ],
732 'selectors_dictionary' => [
733 '169' => '1.77777', // 16 / 9
734 '219' => '2.33333', // 21 / 9
735 '43' => '1.33333', // 4 / 3
736 '32' => '1.5', // 3 / 2
737 '11' => '1', // 1 / 1
738 '916' => '0.5625', // 9 / 16
739 ],
740 'default' => '169',
741 'selectors' => [
742 '{{WRAPPER}} .elementor-wrapper' => '--video-aspect-ratio: {{VALUE}}',
743 ],
744 ]
745 );
746
747 $this->add_group_control(
748 Group_Control_Css_Filter::get_type(),
749 [
750 'name' => 'css_filters',
751 'selector' => '{{WRAPPER}} .elementor-wrapper',
752 ]
753 );
754
755 $this->end_controls_section();
756
757 $this->start_controls_section(
758 'section_image_overlay_style',
759 [
760 'label' => esc_html__( 'Image Overlay', 'elementor' ),
761 'tab' => Controls_Manager::TAB_STYLE,
762 'condition' => [
763 'show_image_overlay' => 'yes',
764 'show_play_icon' => 'yes',
765 ],
766 ]
767 );
768
769 $this->add_control(
770 'play_icon_title',
771 [
772 'label' => esc_html__( 'Play Icon', 'elementor' ),
773 'type' => Controls_Manager::HEADING,
774 'condition' => [
775 'show_image_overlay' => 'yes',
776 'show_play_icon' => 'yes',
777 ],
778 ]
779 );
780
781 $this->add_control(
782 'play_icon_color',
783 [
784 'label' => esc_html__( 'Color', 'elementor' ),
785 'type' => Controls_Manager::COLOR,
786 'selectors' => [
787 '{{WRAPPER}} .elementor-custom-embed-play i' => 'color: {{VALUE}}',
788 '{{WRAPPER}} .elementor-custom-embed-play svg' => 'fill: {{VALUE}}',
789 ],
790 'condition' => [
791 'show_image_overlay' => 'yes',
792 'show_play_icon' => 'yes',
793 ],
794 ]
795 );
796
797 $this->add_responsive_control(
798 'play_icon_size',
799 [
800 'label' => esc_html__( 'Size', 'elementor' ),
801 'type' => Controls_Manager::SLIDER,
802 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
803 'range' => [
804 'px' => [
805 'min' => 10,
806 'max' => 300,
807 ],
808 ],
809 'selectors' => [
810 // Not using a CSS vars because the default size value is coming from a global scss file.
811 '{{WRAPPER}} .elementor-custom-embed-play i' => 'font-size: {{SIZE}}{{UNIT}}',
812 '{{WRAPPER}} .elementor-custom-embed-play svg' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
813 ],
814 'condition' => [
815 'show_image_overlay' => 'yes',
816 'show_play_icon' => 'yes',
817 ],
818 ]
819 );
820
821 $this->add_group_control(
822 Group_Control_Text_Shadow::get_type(),
823 [
824 'name' => 'play_icon_text_shadow',
825 'selector' => '{{WRAPPER}} .elementor-custom-embed-play i',
826 'fields_options' => [
827 'text_shadow_type' => [
828 'label' => esc_html__( 'Shadow', 'elementor' ),
829 ],
830 ],
831 'condition' => [
832 'show_image_overlay' => 'yes',
833 'show_play_icon' => 'yes',
834 'play_icon[library]!' => 'svg',
835 ],
836 ]
837 );
838
839 $this->end_controls_section();
840
841 $this->start_controls_section(
842 'section_lightbox_style',
843 [
844 'label' => esc_html__( 'Lightbox', 'elementor' ),
845 'tab' => Controls_Manager::TAB_STYLE,
846 'condition' => [
847 'show_image_overlay' => 'yes',
848 'image_overlay[url]!' => '',
849 'lightbox' => 'yes',
850 ],
851 ]
852 );
853
854 $this->add_control(
855 'lightbox_color',
856 [
857 'label' => esc_html__( 'Background Color', 'elementor' ),
858 'type' => Controls_Manager::COLOR,
859 'selectors' => [
860 '#elementor-lightbox-{{ID}}' => 'background-color: {{VALUE}};',
861 ],
862 ]
863 );
864
865 $this->add_control(
866 'lightbox_ui_color',
867 [
868 'label' => esc_html__( 'UI Color', 'elementor' ),
869 'type' => Controls_Manager::COLOR,
870 'selectors' => [
871 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button' => 'color: {{VALUE}}',
872 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button svg' => 'fill: {{VALUE}}',
873 ],
874 ]
875 );
876
877 $this->add_control(
878 'lightbox_ui_color_hover',
879 [
880 'label' => esc_html__( 'UI Hover Color', 'elementor' ),
881 'type' => Controls_Manager::COLOR,
882 'selectors' => [
883 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover' => 'color: {{VALUE}}',
884 '#elementor-lightbox-{{ID}} .dialog-lightbox-close-button:hover svg' => 'fill: {{VALUE}}',
885 ],
886 ]
887 );
888
889 $this->add_responsive_control(
890 'lightbox_content_animation',
891 [
892 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
893 'type' => Controls_Manager::ANIMATION,
894 'frontend_available' => true,
895 'separator' => 'before',
896 ]
897 );
898
899 $this->add_control(
900 'deprecation_warning',
901 [
902 'type' => Controls_Manager::RAW_HTML,
903 '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' ),
904 'content_classes' => 'elementor-panel-alert elementor-panel-alert-danger',
905 'separator' => 'before',
906 'condition' => [
907 'lightbox_video_width!' => '',
908 'lightbox_content_position!' => '',
909 ],
910 ]
911 );
912
913 // Deprecated control. Visible only if it was previously in use.
914 $this->add_control(
915 'lightbox_video_width',
916 [
917 'label' => esc_html__( 'Content Width', 'elementor' ),
918 'type' => Controls_Manager::SLIDER,
919 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
920 'default' => [
921 'unit' => '%',
922 ],
923 // 'selectors' => [
924 // '(desktop+)#elementor-lightbox-{{ID}} .elementor-video-container' => 'width: {{SIZE}}{{UNIT}};',
925 // ],
926 'condition' => [
927 'lightbox_video_width!' => '',
928 'lightbox_content_position!' => '',
929 ],
930 ]
931 );
932
933 // Deprecated control. Visible only if it was previously in use.
934 $this->add_control(
935 'lightbox_content_position',
936 [
937 'label' => esc_html__( 'Content Position', 'elementor' ),
938 'type' => Controls_Manager::SELECT,
939 'frontend_available' => true,
940 'options' => [
941 '' => esc_html__( 'Center', 'elementor' ),
942 'top' => esc_html__( 'Top', 'elementor' ),
943 ],
944 // 'selectors' => [
945 // '#elementor-lightbox-{{ID}} .elementor-video-container' => '{{VALUE}}; transform: translateX(-50%);',
946 // ],
947 'selectors_dictionary' => [
948 'top' => 'top: 60px',
949 ],
950 'condition' => [
951 'lightbox_video_width!' => '',
952 'lightbox_content_position!' => '',
953 ],
954 ]
955 );
956
957 $this->end_controls_section();
958 }
959
960 public function print_a11y_text( $image_overlay ) {
961 if ( empty( $image_overlay['alt'] ) ) {
962 echo esc_html__( 'Play Video', 'elementor' );
963 } else {
964 echo esc_html__( 'Play Video about', 'elementor' ) . ' ' . esc_attr( $image_overlay['alt'] );
965 }
966 }
967
968 /**
969 * Render video widget output on the frontend.
970 *
971 * Written in PHP and used to generate the final HTML.
972 *
973 * @since 1.0.0
974 * @access protected
975 */
976 protected function render() {
977 $settings = $this->get_settings_for_display();
978
979 $video_url = $settings[ $settings['video_type'] . '_url' ];
980
981 if ( 'hosted' === $settings['video_type'] ) {
982 $video_url = $this->get_hosted_video_url();
983 } else {
984 if ( 'videopress' === $settings['video_type'] ) {
985 $video_url = $this->get_videopress_video_url();
986 }
987
988 $embed_params = $this->get_embed_params();
989 $embed_options = $this->get_embed_options();
990 }
991
992 if ( empty( $video_url ) ) {
993 return;
994 }
995
996 if ( 'youtube' === $settings['video_type'] ) {
997 $video_html = '<div class="elementor-video"></div>';
998 }
999
1000 if ( 'hosted' === $settings['video_type'] ) {
1001 $this->add_render_attribute( 'video-wrapper', 'class', 'e-hosted-video' );
1002
1003 ob_start();
1004
1005 $this->render_hosted_video();
1006
1007 $video_html = ob_get_clean();
1008 } else {
1009 $is_static_render_mode = Plugin::$instance->frontend->is_static_render_mode();
1010 $post_id = get_queried_object_id();
1011
1012 if ( $is_static_render_mode ) {
1013 $video_html = Embed::get_embed_thumbnail_html( $video_url, $post_id );
1014 // YouTube API requires a different markup which was set above.
1015 } else if ( 'youtube' !== $settings['video_type'] ) {
1016 $video_html = Embed::get_embed_html( $video_url, $embed_params, $embed_options );
1017 }
1018 }
1019
1020 if ( empty( $video_html ) ) {
1021 echo esc_url( $video_url );
1022
1023 return;
1024 }
1025
1026 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-wrapper' );
1027
1028 $this->add_render_attribute( 'video-wrapper', 'class', 'elementor-open-' . ( $settings['lightbox'] ? 'lightbox' : 'inline' ) );
1029 ?>
1030 <div <?php $this->print_render_attribute_string( 'video-wrapper' ); ?>>
1031 <?php
1032 if ( ! $settings['lightbox'] ) {
1033 Utils::print_unescaped_internal_string( $video_html ); // XSS ok.
1034 }
1035
1036 if ( $this->has_image_overlay() ) {
1037 $this->add_render_attribute( 'image-overlay', 'class', 'elementor-custom-embed-image-overlay' );
1038
1039 if ( $settings['lightbox'] ) {
1040 if ( 'hosted' === $settings['video_type'] ) {
1041 $lightbox_url = $video_url;
1042 } else {
1043 $lightbox_url = Embed::get_embed_url( $video_url, $embed_params, $embed_options );
1044 }
1045
1046 $lightbox_options = [
1047 'type' => 'video',
1048 'videoType' => $settings['video_type'],
1049 'url' => $lightbox_url,
1050 'modalOptions' => [
1051 'id' => 'elementor-lightbox-' . $this->get_id(),
1052 'entranceAnimation' => $settings['lightbox_content_animation'],
1053 'entranceAnimation_tablet' => $settings['lightbox_content_animation_tablet'],
1054 'entranceAnimation_mobile' => $settings['lightbox_content_animation_mobile'],
1055 'videoAspectRatio' => $settings['aspect_ratio'],
1056 ],
1057 ];
1058
1059 if ( 'hosted' === $settings['video_type'] ) {
1060 $lightbox_options['videoParams'] = $this->get_hosted_params();
1061 }
1062
1063 $this->add_render_attribute( 'image-overlay', [
1064 'data-elementor-open-lightbox' => 'yes',
1065 'data-elementor-lightbox' => wp_json_encode( $lightbox_options ),
1066 'data-e-action-hash' => Plugin::instance()->frontend->create_action_hash( 'lightbox', $lightbox_options ),
1067 ] );
1068
1069 if ( Plugin::$instance->editor->is_edit_mode() ) {
1070 $this->add_render_attribute( 'image-overlay', [
1071 'class' => 'elementor-clickable',
1072 ] );
1073 }
1074 } else {
1075 // When there is an image URL but no ID, it means the overlay image is the placeholder. In this case, get the placeholder URL.
1076 if ( empty( $settings['image_overlay']['id'] && ! empty( $settings['image_overlay']['url'] ) ) ) {
1077 $image_url = $settings['image_overlay']['url'];
1078 } else {
1079 $image_url = Group_Control_Image_Size::get_attachment_image_src( $settings['image_overlay']['id'], 'image_overlay', $settings );
1080 }
1081
1082 $this->add_render_attribute( 'image-overlay', 'style', 'background-image: url(' . $image_url . ');' );
1083 }
1084 ?>
1085 <div <?php $this->print_render_attribute_string( 'image-overlay' ); ?>>
1086 <?php if ( $settings['lightbox'] ) : ?>
1087 <?php Group_Control_Image_Size::print_attachment_image_html( $settings, 'image_overlay' ); ?>
1088 <?php endif; ?>
1089 <?php if ( 'yes' === $settings['show_play_icon'] ) : ?>
1090 <div class="elementor-custom-embed-play" role="button" aria-label="<?php $this->print_a11y_text( $settings['image_overlay'] ); ?>" tabindex="0">
1091 <?php
1092 if ( empty( $settings['play_icon']['value'] ) ) {
1093 $settings['play_icon'] = [
1094 'library' => 'eicons',
1095 'value' => 'eicon-play',
1096 ];
1097 }
1098 Icons_Manager::render_icon( $settings['play_icon'], [ 'aria-hidden' => 'true' ] );
1099 ?>
1100 <span class="elementor-screen-only"><?php $this->print_a11y_text( $settings['image_overlay'] ); ?></span>
1101 </div>
1102 <?php endif; ?>
1103 </div>
1104 <?php } ?>
1105 </div>
1106 <?php
1107 }
1108
1109 /**
1110 * Render video widget as plain content.
1111 *
1112 * Override the default behavior, by printing the video URL insted of rendering it.
1113 *
1114 * @since 1.4.5
1115 * @access public
1116 */
1117 public function render_plain_content() {
1118 $settings = $this->get_settings_for_display();
1119
1120 if ( 'hosted' !== $settings['video_type'] ) {
1121 $url = $settings[ $settings['video_type'] . '_url' ];
1122 } else {
1123 $url = $this->get_hosted_video_url();
1124 }
1125
1126 echo esc_url( $url );
1127 }
1128
1129 /**
1130 * Get embed params.
1131 *
1132 * Retrieve video widget embed parameters.
1133 *
1134 * @since 1.5.0
1135 * @access public
1136 *
1137 * @return array Video embed parameters.
1138 */
1139 public function get_embed_params() {
1140 $settings = $this->get_settings_for_display();
1141
1142 $params = [];
1143
1144 if ( $settings['autoplay'] && ! $this->has_image_overlay() ) {
1145 $params['autoplay'] = '1';
1146
1147 if ( $settings['play_on_mobile'] ) {
1148 $params['playsinline'] = '1';
1149 }
1150 }
1151
1152 $params_dictionary = [];
1153
1154 if ( 'youtube' === $settings['video_type'] ) {
1155 $params_dictionary = [
1156 'loop',
1157 'controls',
1158 'mute',
1159 'rel',
1160 'modestbranding',
1161 ];
1162
1163 if ( $settings['loop'] ) {
1164 $video_properties = Embed::get_video_properties( $settings['youtube_url'] );
1165
1166 $params['playlist'] = $video_properties['video_id'];
1167 }
1168
1169 $params['start'] = $settings['start'];
1170
1171 $params['end'] = $settings['end'];
1172
1173 $params['wmode'] = 'opaque';
1174 } elseif ( 'vimeo' === $settings['video_type'] ) {
1175 $params_dictionary = [
1176 'loop',
1177 'mute' => 'muted',
1178 'vimeo_title' => 'title',
1179 'vimeo_portrait' => 'portrait',
1180 'vimeo_byline' => 'byline',
1181 ];
1182
1183 $params['color'] = str_replace( '#', '', $settings['color'] );
1184
1185 $params['autopause'] = '0';
1186
1187 if ( ! empty( $settings['yt_privacy'] ) ) {
1188 $params['dnt'] = 'true';
1189 }
1190 } elseif ( 'dailymotion' === $settings['video_type'] ) {
1191 $params_dictionary = [
1192 'controls',
1193 'mute',
1194 'showinfo' => 'ui-start-screen-info',
1195 'logo' => 'ui-logo',
1196 ];
1197
1198 $params['ui-highlight'] = str_replace( '#', '', $settings['color'] );
1199
1200 $params['start'] = $settings['start'];
1201
1202 $params['endscreen-enable'] = '0';
1203 } elseif ( 'videopress' === $settings['video_type'] ) {
1204 $params_dictionary = $this->get_params_dictionary_for_videopress();
1205
1206 $params['at'] = $settings['start'];
1207 }
1208
1209 foreach ( $params_dictionary as $key => $param_name ) {
1210 $setting_name = $param_name;
1211
1212 if ( is_string( $key ) ) {
1213 $setting_name = $key;
1214 }
1215
1216 $setting_value = $settings[ $setting_name ] ? '1' : '0';
1217
1218 $params[ $param_name ] = $setting_value;
1219 }
1220
1221 return $params;
1222 }
1223
1224 /**
1225 * Whether the video widget has an overlay image or not.
1226 *
1227 * Used to determine whether an overlay image was set for the video.
1228 *
1229 * @since 1.0.0
1230 * @access protected
1231 *
1232 * @return bool Whether an image overlay was set for the video.
1233 */
1234 protected function has_image_overlay() {
1235 $settings = $this->get_settings_for_display();
1236
1237 return ! empty( $settings['image_overlay']['url'] ) && 'yes' === $settings['show_image_overlay'];
1238 }
1239
1240 /**
1241 * @since 2.1.0
1242 * @access private
1243 */
1244 private function get_embed_options() {
1245 $settings = $this->get_settings_for_display();
1246
1247 $embed_options = [];
1248
1249 if ( 'youtube' === $settings['video_type'] ) {
1250 $embed_options['privacy'] = $settings['yt_privacy'];
1251 } elseif ( 'vimeo' === $settings['video_type'] ) {
1252 $embed_options['start'] = $settings['start'];
1253 }
1254
1255 $embed_options['lazy_load'] = ! empty( $settings['lazy_load'] );
1256
1257 return $embed_options;
1258 }
1259
1260 /**
1261 * @since 2.1.0
1262 * @access private
1263 */
1264 private function get_hosted_params() {
1265 $settings = $this->get_settings_for_display();
1266
1267 $video_params = [];
1268
1269 foreach ( [ 'autoplay', 'loop', 'controls' ] as $option_name ) {
1270 if ( $settings[ $option_name ] ) {
1271 $video_params[ $option_name ] = '';
1272 }
1273 }
1274
1275 if ( $settings['preload'] ) {
1276 $video_params['preload'] = $settings['preload'];
1277 }
1278
1279 if ( $settings['mute'] ) {
1280 $video_params['muted'] = 'muted';
1281 }
1282
1283 if ( $settings['play_on_mobile'] ) {
1284 $video_params['playsinline'] = '';
1285 }
1286
1287 if ( ! $settings['download_button'] ) {
1288 $video_params['controlsList'] = 'nodownload';
1289 }
1290
1291 if ( $settings['poster']['url'] ) {
1292 $video_params['poster'] = $settings['poster']['url'];
1293 }
1294
1295 return $video_params;
1296 }
1297
1298 /**
1299 * @param bool $from_media
1300 *
1301 * @return string
1302 * @since 2.1.0
1303 * @access private
1304 */
1305 private function get_hosted_video_url() {
1306 $settings = $this->get_settings_for_display();
1307
1308 if ( ! empty( $settings['insert_url'] ) ) {
1309 $video_url = $settings['external_url']['url'];
1310 } else {
1311 $video_url = $settings['hosted_url']['url'];
1312 }
1313
1314 if ( empty( $video_url ) ) {
1315 return '';
1316 }
1317
1318 if ( $settings['start'] || $settings['end'] ) {
1319 $video_url .= '#t=';
1320 }
1321
1322 if ( $settings['start'] ) {
1323 $video_url .= $settings['start'];
1324 }
1325
1326 if ( $settings['end'] ) {
1327 $video_url .= ',' . $settings['end'];
1328 }
1329
1330 return $video_url;
1331 }
1332
1333 /**
1334 * Get the VideoPress video URL from the current selected settings.
1335 *
1336 * @return string
1337 */
1338 private function get_videopress_video_url() {
1339 $settings = $this->get_settings_for_display();
1340
1341 if ( ! empty( $settings['insert_url'] ) ) {
1342 return $settings['videopress_url'];
1343 }
1344
1345 return $settings['hosted_url']['url'];
1346 }
1347
1348 /**
1349 * Get the params dictionary for VideoPress videos.
1350 *
1351 * @return array
1352 */
1353 private function get_params_dictionary_for_videopress() {
1354 return [
1355 'controls',
1356 'autoplay' => 'autoPlay',
1357 'mute' => 'muted',
1358 'loop',
1359 'play_on_mobile' => 'playsinline',
1360 ];
1361 }
1362
1363 /**
1364 *
1365 * @since 2.1.0
1366 * @access private
1367 */
1368 private function render_hosted_video() {
1369 $video_url = $this->get_hosted_video_url();
1370 if ( empty( $video_url ) ) {
1371 return;
1372 }
1373
1374 $video_params = $this->get_hosted_params();
1375 /* Sometimes the video url is base64, therefore we use `esc_attr` in `src`. */
1376 ?>
1377 <video class="elementor-video" src="<?php echo esc_attr( $video_url ); ?>" <?php Utils::print_html_attributes( $video_params ); ?>></video>
1378 <?php
1379 }
1380 }
1381