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

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