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

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