PluginProbe
Elementor Website Builder – more than just a page builder / 3.10.0-dev1
Elementor Website Builder – more than just a page builder v3.10.0-dev1
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 / image.php

image.php in Elementor Website Builder – more than just a page builder 3.10.0-dev1, at includes/widgets/image.php

849 lines 18.3 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 if ( ! defined( 'ABSPATH' ) ) {
5 exit; // Exit if accessed directly.
6 }
7
8 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
9 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
10
11 /**
12 * Elementor image widget.
13 *
14 * Elementor widget that displays an image into the page.
15 *
16 * @since 1.0.0
17 */
18 class Widget_Image extends Widget_Base {
19
20 /**
21 * Get widget name.
22 *
23 * Retrieve image widget name.
24 *
25 * @since 1.0.0
26 * @access public
27 *
28 * @return string Widget name.
29 */
30 public function get_name() {
31 return 'image';
32 }
33
34 /**
35 * Get widget title.
36 *
37 * Retrieve image widget title.
38 *
39 * @since 1.0.0
40 * @access public
41 *
42 * @return string Widget title.
43 */
44 public function get_title() {
45 return esc_html__( 'Image', 'elementor' );
46 }
47
48 /**
49 * Get widget icon.
50 *
51 * Retrieve image widget icon.
52 *
53 * @since 1.0.0
54 * @access public
55 *
56 * @return string Widget icon.
57 */
58 public function get_icon() {
59 return 'eicon-image';
60 }
61
62 /**
63 * Get widget categories.
64 *
65 * Retrieve the list of categories the image widget belongs to.
66 *
67 * Used to determine where to display the widget in the editor.
68 *
69 * @since 2.0.0
70 * @access public
71 *
72 * @return array Widget categories.
73 */
74 public function get_categories() {
75 return [ 'basic' ];
76 }
77
78 /**
79 * Get widget keywords.
80 *
81 * Retrieve the list of keywords the widget belongs to.
82 *
83 * @since 2.1.0
84 * @access public
85 *
86 * @return array Widget keywords.
87 */
88 public function get_keywords() {
89 return [ 'image', 'photo', 'visual' ];
90 }
91
92 /**
93 * Register image widget controls.
94 *
95 * Adds different input fields to allow the user to change and customize the widget settings.
96 *
97 * @since 3.1.0
98 * @access protected
99 */
100 protected function register_controls() {
101 $this->start_controls_section(
102 'section_image',
103 [
104 'label' => esc_html__( 'Image', 'elementor' ),
105 ]
106 );
107
108 $this->add_control(
109 'image',
110 [
111 'label' => esc_html__( 'Choose Image', 'elementor' ),
112 'type' => Controls_Manager::MEDIA,
113 'dynamic' => [
114 'active' => true,
115 ],
116 'default' => [
117 'url' => Utils::get_placeholder_image_src(),
118 ],
119 ]
120 );
121
122 $this->add_group_control(
123 Group_Control_Image_Size::get_type(),
124 [
125 'name' => 'image', // Usage: `{name}_size` and `{name}_custom_dimension`, in this case `image_size` and `image_custom_dimension`.
126 'default' => 'large',
127 'separator' => 'none',
128 ]
129 );
130
131 $this->add_responsive_control(
132 'align',
133 [
134 'label' => esc_html__( 'Alignment', 'elementor' ),
135 'type' => Controls_Manager::CHOOSE,
136 'options' => [
137 'left' => [
138 'title' => esc_html__( 'Left', 'elementor' ),
139 'icon' => 'eicon-text-align-left',
140 ],
141 'center' => [
142 'title' => esc_html__( 'Center', 'elementor' ),
143 'icon' => 'eicon-text-align-center',
144 ],
145 'right' => [
146 'title' => esc_html__( 'Right', 'elementor' ),
147 'icon' => 'eicon-text-align-right',
148 ],
149 ],
150 'selectors' => [
151 '{{WRAPPER}}' => 'text-align: {{VALUE}};',
152 ],
153 ]
154 );
155
156 $this->add_control(
157 'caption_source',
158 [
159 'label' => esc_html__( 'Caption', 'elementor' ),
160 'type' => Controls_Manager::SELECT,
161 'options' => [
162 'none' => esc_html__( 'None', 'elementor' ),
163 'attachment' => esc_html__( 'Attachment Caption', 'elementor' ),
164 'custom' => esc_html__( 'Custom Caption', 'elementor' ),
165 ],
166 'default' => 'none',
167 ]
168 );
169
170 $this->add_control(
171 'caption',
172 [
173 'label' => esc_html__( 'Custom Caption', 'elementor' ),
174 'type' => Controls_Manager::TEXT,
175 'default' => '',
176 'placeholder' => esc_html__( 'Enter your image caption', 'elementor' ),
177 'condition' => [
178 'caption_source' => 'custom',
179 ],
180 'dynamic' => [
181 'active' => true,
182 ],
183 ]
184 );
185
186 $this->add_control(
187 'link_to',
188 [
189 'label' => esc_html__( 'Link', 'elementor' ),
190 'type' => Controls_Manager::SELECT,
191 'default' => 'none',
192 'options' => [
193 'none' => esc_html__( 'None', 'elementor' ),
194 'file' => esc_html__( 'Media File', 'elementor' ),
195 'custom' => esc_html__( 'Custom URL', 'elementor' ),
196 ],
197 ]
198 );
199
200 $this->add_control(
201 'link',
202 [
203 'label' => esc_html__( 'Link', 'elementor' ),
204 'type' => Controls_Manager::URL,
205 'dynamic' => [
206 'active' => true,
207 ],
208 'placeholder' => esc_html__( 'https://your-link.com', 'elementor' ),
209 'condition' => [
210 'link_to' => 'custom',
211 ],
212 'show_label' => false,
213 ]
214 );
215
216 $this->add_control(
217 'open_lightbox',
218 [
219 'label' => esc_html__( 'Lightbox', 'elementor' ),
220 'type' => Controls_Manager::SELECT,
221 'default' => 'default',
222 'options' => [
223 'default' => esc_html__( 'Default', 'elementor' ),
224 'yes' => esc_html__( 'Yes', 'elementor' ),
225 'no' => esc_html__( 'No', 'elementor' ),
226 ],
227 'condition' => [
228 'link_to' => 'file',
229 ],
230 ]
231 );
232
233 $this->add_control(
234 'view',
235 [
236 'label' => esc_html__( 'View', 'elementor' ),
237 'type' => Controls_Manager::HIDDEN,
238 'default' => 'traditional',
239 ]
240 );
241
242 $this->end_controls_section();
243
244 $this->start_controls_section(
245 'section_style_image',
246 [
247 'label' => esc_html__( 'Image', 'elementor' ),
248 'tab' => Controls_Manager::TAB_STYLE,
249 ]
250 );
251
252 $this->add_responsive_control(
253 'width',
254 [
255 'label' => esc_html__( 'Width', 'elementor' ),
256 'type' => Controls_Manager::SLIDER,
257 'default' => [
258 'unit' => '%',
259 ],
260 'tablet_default' => [
261 'unit' => '%',
262 ],
263 'mobile_default' => [
264 'unit' => '%',
265 ],
266 'size_units' => [ '%', 'px', 'vw' ],
267 'range' => [
268 '%' => [
269 'min' => 1,
270 'max' => 100,
271 ],
272 'px' => [
273 'min' => 1,
274 'max' => 1000,
275 ],
276 'vw' => [
277 'min' => 1,
278 'max' => 100,
279 ],
280 ],
281 'selectors' => [
282 '{{WRAPPER}} img' => 'width: {{SIZE}}{{UNIT}};',
283 ],
284 ]
285 );
286
287 $this->add_responsive_control(
288 'space',
289 [
290 'label' => esc_html__( 'Max Width', 'elementor' ),
291 'type' => Controls_Manager::SLIDER,
292 'default' => [
293 'unit' => '%',
294 ],
295 'tablet_default' => [
296 'unit' => '%',
297 ],
298 'mobile_default' => [
299 'unit' => '%',
300 ],
301 'size_units' => [ '%', 'px', 'vw' ],
302 'range' => [
303 '%' => [
304 'min' => 1,
305 'max' => 100,
306 ],
307 'px' => [
308 'min' => 1,
309 'max' => 1000,
310 ],
311 'vw' => [
312 'min' => 1,
313 'max' => 100,
314 ],
315 ],
316 'selectors' => [
317 '{{WRAPPER}} img' => 'max-width: {{SIZE}}{{UNIT}};',
318 ],
319 ]
320 );
321
322 $this->add_responsive_control(
323 'height',
324 [
325 'label' => esc_html__( 'Height', 'elementor' ),
326 'type' => Controls_Manager::SLIDER,
327 'default' => [
328 'unit' => 'px',
329 ],
330 'tablet_default' => [
331 'unit' => 'px',
332 ],
333 'mobile_default' => [
334 'unit' => 'px',
335 ],
336 'size_units' => [ 'px', 'vh' ],
337 'range' => [
338 'px' => [
339 'min' => 1,
340 'max' => 500,
341 ],
342 'vh' => [
343 'min' => 1,
344 'max' => 100,
345 ],
346 ],
347 'selectors' => [
348 '{{WRAPPER}} img' => 'height: {{SIZE}}{{UNIT}};',
349 ],
350 ]
351 );
352
353 $this->add_responsive_control(
354 'object-fit',
355 [
356 'label' => esc_html__( 'Object Fit', 'elementor' ),
357 'type' => Controls_Manager::SELECT,
358 'condition' => [
359 'height[size]!' => '',
360 ],
361 'options' => [
362 '' => esc_html__( 'Default', 'elementor' ),
363 'fill' => esc_html__( 'Fill', 'elementor' ),
364 'cover' => esc_html__( 'Cover', 'elementor' ),
365 'contain' => esc_html__( 'Contain', 'elementor' ),
366 ],
367 'default' => '',
368 'selectors' => [
369 '{{WRAPPER}} img' => 'object-fit: {{VALUE}};',
370 ],
371 ]
372 );
373
374 $this->add_control(
375 'separator_panel_style',
376 [
377 'type' => Controls_Manager::DIVIDER,
378 'style' => 'thick',
379 ]
380 );
381
382 $this->start_controls_tabs( 'image_effects' );
383
384 $this->start_controls_tab( 'normal',
385 [
386 'label' => esc_html__( 'Normal', 'elementor' ),
387 ]
388 );
389
390 $this->add_control(
391 'opacity',
392 [
393 'label' => esc_html__( 'Opacity', 'elementor' ),
394 'type' => Controls_Manager::SLIDER,
395 'range' => [
396 'px' => [
397 'max' => 1,
398 'min' => 0.10,
399 'step' => 0.01,
400 ],
401 ],
402 'selectors' => [
403 '{{WRAPPER}} img' => 'opacity: {{SIZE}};',
404 ],
405 ]
406 );
407
408 $this->add_group_control(
409 Group_Control_Css_Filter::get_type(),
410 [
411 'name' => 'css_filters',
412 'selector' => '{{WRAPPER}} img',
413 ]
414 );
415
416 $this->end_controls_tab();
417
418 $this->start_controls_tab( 'hover',
419 [
420 'label' => esc_html__( 'Hover', 'elementor' ),
421 ]
422 );
423
424 $this->add_control(
425 'opacity_hover',
426 [
427 'label' => esc_html__( 'Opacity', 'elementor' ),
428 'type' => Controls_Manager::SLIDER,
429 'range' => [
430 'px' => [
431 'max' => 1,
432 'min' => 0.10,
433 'step' => 0.01,
434 ],
435 ],
436 'selectors' => [
437 '{{WRAPPER}}:hover img' => 'opacity: {{SIZE}};',
438 ],
439 ]
440 );
441
442 $this->add_group_control(
443 Group_Control_Css_Filter::get_type(),
444 [
445 'name' => 'css_filters_hover',
446 'selector' => '{{WRAPPER}}:hover img',
447 ]
448 );
449
450 $this->add_control(
451 'background_hover_transition',
452 [
453 'label' => esc_html__( 'Transition Duration', 'elementor' ),
454 'type' => Controls_Manager::SLIDER,
455 'size_units' => [ 's', 'ms' ],
456 'default' => [
457 'unit' => 's',
458 ],
459 'selectors' => [
460 '{{WRAPPER}} img' => 'transition-duration: {{SIZE}}{{UNIT}}',
461 ],
462 ]
463 );
464
465 $this->add_control(
466 'hover_animation',
467 [
468 'label' => esc_html__( 'Hover Animation', 'elementor' ),
469 'type' => Controls_Manager::HOVER_ANIMATION,
470 ]
471 );
472
473 $this->end_controls_tab();
474
475 $this->end_controls_tabs();
476
477 $this->add_group_control(
478 Group_Control_Border::get_type(),
479 [
480 'name' => 'image_border',
481 'selector' => '{{WRAPPER}} img',
482 'separator' => 'before',
483 ]
484 );
485
486 $this->add_responsive_control(
487 'image_border_radius',
488 [
489 'label' => esc_html__( 'Border Radius', 'elementor' ),
490 'type' => Controls_Manager::DIMENSIONS,
491 'size_units' => [ 'px', '%', 'em' ],
492 'selectors' => [
493 '{{WRAPPER}} img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
494 ],
495 ]
496 );
497
498 $this->add_group_control(
499 Group_Control_Box_Shadow::get_type(),
500 [
501 'name' => 'image_box_shadow',
502 'exclude' => [
503 'box_shadow_position',
504 ],
505 'selector' => '{{WRAPPER}} img',
506 ]
507 );
508
509 $this->end_controls_section();
510
511 $this->start_controls_section(
512 'section_style_caption',
513 [
514 'label' => esc_html__( 'Caption', 'elementor' ),
515 'tab' => Controls_Manager::TAB_STYLE,
516 'condition' => [
517 'caption_source!' => 'none',
518 ],
519 ]
520 );
521
522 $this->add_responsive_control(
523 'caption_align',
524 [
525 'label' => esc_html__( 'Alignment', 'elementor' ),
526 'type' => Controls_Manager::CHOOSE,
527 'options' => [
528 'left' => [
529 'title' => esc_html__( 'Left', 'elementor' ),
530 'icon' => 'eicon-text-align-left',
531 ],
532 'center' => [
533 'title' => esc_html__( 'Center', 'elementor' ),
534 'icon' => 'eicon-text-align-center',
535 ],
536 'right' => [
537 'title' => esc_html__( 'Right', 'elementor' ),
538 'icon' => 'eicon-text-align-right',
539 ],
540 'justify' => [
541 'title' => esc_html__( 'Justified', 'elementor' ),
542 'icon' => 'eicon-text-align-justify',
543 ],
544 ],
545 'default' => '',
546 'selectors' => [
547 '{{WRAPPER}} .widget-image-caption' => 'text-align: {{VALUE}};',
548 ],
549 ]
550 );
551
552 $this->add_control(
553 'text_color',
554 [
555 'label' => esc_html__( 'Text Color', 'elementor' ),
556 'type' => Controls_Manager::COLOR,
557 'default' => '',
558 'selectors' => [
559 '{{WRAPPER}} .widget-image-caption' => 'color: {{VALUE}};',
560 ],
561 'global' => [
562 'default' => Global_Colors::COLOR_TEXT,
563 ],
564 ]
565 );
566
567 $this->add_control(
568 'caption_background_color',
569 [
570 'label' => esc_html__( 'Background Color', 'elementor' ),
571 'type' => Controls_Manager::COLOR,
572 'selectors' => [
573 '{{WRAPPER}} .widget-image-caption' => 'background-color: {{VALUE}};',
574 ],
575 ]
576 );
577
578 $this->add_group_control(
579 Group_Control_Typography::get_type(),
580 [
581 'name' => 'caption_typography',
582 'selector' => '{{WRAPPER}} .widget-image-caption',
583 'global' => [
584 'default' => Global_Typography::TYPOGRAPHY_TEXT,
585 ],
586 ]
587 );
588
589 $this->add_group_control(
590 Group_Control_Text_Shadow::get_type(),
591 [
592 'name' => 'caption_text_shadow',
593 'selector' => '{{WRAPPER}} .widget-image-caption',
594 ]
595 );
596
597 $this->add_responsive_control(
598 'caption_space',
599 [
600 'label' => esc_html__( 'Spacing', 'elementor' ),
601 'type' => Controls_Manager::SLIDER,
602 'range' => [
603 'px' => [
604 'min' => 0,
605 'max' => 100,
606 ],
607 ],
608 'selectors' => [
609 '{{WRAPPER}} .widget-image-caption' => 'margin-top: {{SIZE}}{{UNIT}};',
610 ],
611 ]
612 );
613
614 $this->end_controls_section();
615 }
616
617 /**
618 * Check if the current widget has caption
619 *
620 * @access private
621 * @since 2.3.0
622 *
623 * @param array $settings
624 *
625 * @return boolean
626 */
627 private function has_caption( $settings ) {
628 return ( ! empty( $settings['caption_source'] ) && 'none' !== $settings['caption_source'] );
629 }
630
631 /**
632 * Get the caption for current widget.
633 *
634 * @access private
635 * @since 2.3.0
636 * @param $settings
637 *
638 * @return string
639 */
640 private function get_caption( $settings ) {
641 $caption = '';
642 if ( ! empty( $settings['caption_source'] ) ) {
643 switch ( $settings['caption_source'] ) {
644 case 'attachment':
645 $caption = wp_get_attachment_caption( $settings['image']['id'] );
646 break;
647 case 'custom':
648 $caption = ! Utils::is_empty( $settings['caption'] ) ? $settings['caption'] : '';
649 }
650 }
651 return $caption;
652 }
653
654 /**
655 * Render image widget output on the frontend.
656 *
657 * Written in PHP and used to generate the final HTML.
658 *
659 * @since 1.0.0
660 * @access protected
661 */
662 protected function render() {
663 $settings = $this->get_settings_for_display();
664
665 if ( empty( $settings['image']['url'] ) ) {
666 return;
667 }
668
669 if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) {
670 $this->add_render_attribute( 'wrapper', 'class', 'elementor-image' );
671 }
672
673 $has_caption = $this->has_caption( $settings );
674
675 $link = $this->get_link_url( $settings );
676
677 if ( $link ) {
678 $this->add_link_attributes( 'link', $link );
679
680 if ( Plugin::$instance->editor->is_edit_mode() ) {
681 $this->add_render_attribute( 'link', [
682 'class' => 'elementor-clickable',
683 ] );
684 }
685
686 if ( 'custom' !== $settings['link_to'] ) {
687 $this->add_lightbox_data_attributes( 'link', $settings['image']['id'], $settings['open_lightbox'] );
688 }
689 } ?>
690 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
691 <div <?php $this->print_render_attribute_string( 'wrapper' ); ?>>
692 <?php } ?>
693 <?php if ( $has_caption ) : ?>
694 <figure class="wp-caption">
695 <?php endif; ?>
696 <?php if ( $link ) : ?>
697 <a <?php $this->print_render_attribute_string( 'link' ); ?>>
698 <?php endif; ?>
699 <?php Group_Control_Image_Size::print_attachment_image_html( $settings ); ?>
700 <?php if ( $link ) : ?>
701 </a>
702 <?php endif; ?>
703 <?php if ( $has_caption ) : ?>
704 <figcaption class="widget-image-caption wp-caption-text"><?php
705 echo wp_kses_post( $this->get_caption( $settings ) );
706 ?></figcaption>
707 <?php endif; ?>
708 <?php if ( $has_caption ) : ?>
709 </figure>
710 <?php endif; ?>
711 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
712 </div>
713 <?php } ?>
714 <?php
715 }
716
717 /**
718 * Render image widget output in the editor.
719 *
720 * Written as a Backbone JavaScript template and used to generate the live preview.
721 *
722 * @since 2.9.0
723 * @access protected
724 */
725 protected function content_template() {
726 ?>
727 <# if ( settings.image.url ) {
728 var image = {
729 id: settings.image.id,
730 url: settings.image.url,
731 size: settings.image_size,
732 dimension: settings.image_custom_dimension,
733 model: view.getEditModel()
734 };
735
736 var image_url = elementor.imagesManager.getImageUrl( image );
737
738 if ( ! image_url ) {
739 return;
740 }
741
742 var hasCaption = function() {
743 if( ! settings.caption_source || 'none' === settings.caption_source ) {
744 return false;
745 }
746 return true;
747 }
748
749 var ensureAttachmentData = function( id ) {
750 if ( 'undefined' === typeof wp.media.attachment( id ).get( 'caption' ) ) {
751 wp.media.attachment( id ).fetch().then( function( data ) {
752 view.render();
753 } );
754 }
755 }
756
757 var getAttachmentCaption = function( id ) {
758 if ( ! id ) {
759 return '';
760 }
761 ensureAttachmentData( id );
762 return wp.media.attachment( id ).get( 'caption' );
763 }
764
765 var getCaption = function() {
766 if ( ! hasCaption() ) {
767 return '';
768 }
769 return 'custom' === settings.caption_source ? settings.caption : getAttachmentCaption( settings.image.id );
770 }
771
772 var link_url;
773
774 if ( 'custom' === settings.link_to ) {
775 link_url = settings.link.url;
776 }
777
778 if ( 'file' === settings.link_to ) {
779 link_url = settings.image.url;
780 }
781
782 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
783 #><div class="elementor-image{{ settings.shape ? ' elementor-image-shape-' + settings.shape : '' }}"><#
784 <?php } ?>
785
786 var imgClass = '';
787
788 if ( '' !== settings.hover_animation ) {
789 imgClass = 'elementor-animation-' + settings.hover_animation;
790 }
791
792 if ( hasCaption() ) {
793 #><figure class="wp-caption"><#
794 }
795
796 if ( link_url ) {
797 #><a class="elementor-clickable" data-elementor-open-lightbox="{{ settings.open_lightbox }}" href="{{ link_url }}"><#
798 }
799 #><img src="{{ image_url }}" class="{{ imgClass }}" /><#
800
801 if ( link_url ) {
802 #></a><#
803 }
804
805 if ( hasCaption() ) {
806 #><figcaption class="widget-image-caption wp-caption-text">{{{ getCaption() }}}</figcaption><#
807 }
808
809 if ( hasCaption() ) {
810 #></figure><#
811 }
812
813 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
814 #></div><#
815 <?php } ?>
816
817 } #>
818 <?php
819 }
820
821 /**
822 * Retrieve image widget link URL.
823 *
824 * @since 1.0.0
825 * @access private
826 *
827 * @param array $settings
828 *
829 * @return array|string|false An array/string containing the link URL, or false if no link.
830 */
831 private function get_link_url( $settings ) {
832 if ( 'none' === $settings['link_to'] ) {
833 return false;
834 }
835
836 if ( 'custom' === $settings['link_to'] ) {
837 if ( empty( $settings['link']['url'] ) ) {
838 return false;
839 }
840
841 return $settings['link'];
842 }
843
844 return [
845 'url' => $settings['image']['url'],
846 ];
847 }
848 }
849