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

849 lines 17.8 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 __( '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' => __( 'Image', 'elementor' ),
105 ]
106 );
107
108 $this->add_control(
109 'image',
110 [
111 'label' => __( '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' => __( 'Alignment', 'elementor' ),
135 'type' => Controls_Manager::CHOOSE,
136 'options' => [
137 'left' => [
138 'title' => __( 'Left', 'elementor' ),
139 'icon' => 'eicon-text-align-left',
140 ],
141 'center' => [
142 'title' => __( 'Center', 'elementor' ),
143 'icon' => 'eicon-text-align-center',
144 ],
145 'right' => [
146 'title' => __( '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' => __( 'Caption', 'elementor' ),
160 'type' => Controls_Manager::SELECT,
161 'options' => [
162 'none' => __( 'None', 'elementor' ),
163 'attachment' => __( 'Attachment Caption', 'elementor' ),
164 'custom' => __( 'Custom Caption', 'elementor' ),
165 ],
166 'default' => 'none',
167 ]
168 );
169
170 $this->add_control(
171 'caption',
172 [
173 'label' => __( 'Custom Caption', 'elementor' ),
174 'type' => Controls_Manager::TEXT,
175 'default' => '',
176 'placeholder' => __( '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' => __( 'Link', 'elementor' ),
190 'type' => Controls_Manager::SELECT,
191 'default' => 'none',
192 'options' => [
193 'none' => __( 'None', 'elementor' ),
194 'file' => __( 'Media File', 'elementor' ),
195 'custom' => __( 'Custom URL', 'elementor' ),
196 ],
197 ]
198 );
199
200 $this->add_control(
201 'link',
202 [
203 'label' => __( 'Link', 'elementor' ),
204 'type' => Controls_Manager::URL,
205 'dynamic' => [
206 'active' => true,
207 ],
208 'placeholder' => __( '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' => __( 'Lightbox', 'elementor' ),
220 'type' => Controls_Manager::SELECT,
221 'default' => 'default',
222 'options' => [
223 'default' => __( 'Default', 'elementor' ),
224 'yes' => __( 'Yes', 'elementor' ),
225 'no' => __( 'No', 'elementor' ),
226 ],
227 'condition' => [
228 'link_to' => 'file',
229 ],
230 ]
231 );
232
233 $this->add_control(
234 'view',
235 [
236 'label' => __( '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' => __( 'Image', 'elementor' ),
248 'tab' => Controls_Manager::TAB_STYLE,
249 ]
250 );
251
252 $this->add_responsive_control(
253 'width',
254 [
255 'label' => __( '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' => __( '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' => __( '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' => __( 'Object Fit', 'elementor' ),
357 'type' => Controls_Manager::SELECT,
358 'condition' => [
359 'height[size]!' => '',
360 ],
361 'options' => [
362 '' => __( 'Default', 'elementor' ),
363 'fill' => __( 'Fill', 'elementor' ),
364 'cover' => __( 'Cover', 'elementor' ),
365 'contain' => __( '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' => __( 'Normal', 'elementor' ),
387 ]
388 );
389
390 $this->add_control(
391 'opacity',
392 [
393 'label' => __( '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' => __( 'Hover', 'elementor' ),
421 ]
422 );
423
424 $this->add_control(
425 'opacity_hover',
426 [
427 'label' => __( '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' => __( 'Transition Duration', 'elementor' ),
454 'type' => Controls_Manager::SLIDER,
455 'range' => [
456 'px' => [
457 'max' => 3,
458 'step' => 0.1,
459 ],
460 ],
461 'selectors' => [
462 '{{WRAPPER}} img' => 'transition-duration: {{SIZE}}s',
463 ],
464 ]
465 );
466
467 $this->add_control(
468 'hover_animation',
469 [
470 'label' => __( 'Hover Animation', 'elementor' ),
471 'type' => Controls_Manager::HOVER_ANIMATION,
472 ]
473 );
474
475 $this->end_controls_tab();
476
477 $this->end_controls_tabs();
478
479 $this->add_group_control(
480 Group_Control_Border::get_type(),
481 [
482 'name' => 'image_border',
483 'selector' => '{{WRAPPER}} img',
484 'separator' => 'before',
485 ]
486 );
487
488 $this->add_responsive_control(
489 'image_border_radius',
490 [
491 'label' => __( 'Border Radius', 'elementor' ),
492 'type' => Controls_Manager::DIMENSIONS,
493 'size_units' => [ 'px', '%' ],
494 'selectors' => [
495 '{{WRAPPER}} img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
496 ],
497 ]
498 );
499
500 $this->add_group_control(
501 Group_Control_Box_Shadow::get_type(),
502 [
503 'name' => 'image_box_shadow',
504 'exclude' => [
505 'box_shadow_position',
506 ],
507 'selector' => '{{WRAPPER}} img',
508 ]
509 );
510
511 $this->end_controls_section();
512
513 $this->start_controls_section(
514 'section_style_caption',
515 [
516 'label' => __( 'Caption', 'elementor' ),
517 'tab' => Controls_Manager::TAB_STYLE,
518 'condition' => [
519 'caption_source!' => 'none',
520 ],
521 ]
522 );
523
524 $this->add_control(
525 'caption_align',
526 [
527 'label' => __( 'Alignment', 'elementor' ),
528 'type' => Controls_Manager::CHOOSE,
529 'options' => [
530 'left' => [
531 'title' => __( 'Left', 'elementor' ),
532 'icon' => 'eicon-text-align-left',
533 ],
534 'center' => [
535 'title' => __( 'Center', 'elementor' ),
536 'icon' => 'eicon-text-align-center',
537 ],
538 'right' => [
539 'title' => __( 'Right', 'elementor' ),
540 'icon' => 'eicon-text-align-right',
541 ],
542 'justify' => [
543 'title' => __( 'Justified', 'elementor' ),
544 'icon' => 'eicon-text-align-justify',
545 ],
546 ],
547 'default' => '',
548 'selectors' => [
549 '{{WRAPPER}} .widget-image-caption' => 'text-align: {{VALUE}};',
550 ],
551 ]
552 );
553
554 $this->add_control(
555 'text_color',
556 [
557 'label' => __( 'Text Color', 'elementor' ),
558 'type' => Controls_Manager::COLOR,
559 'default' => '',
560 'selectors' => [
561 '{{WRAPPER}} .widget-image-caption' => 'color: {{VALUE}};',
562 ],
563 'global' => [
564 'default' => Global_Colors::COLOR_TEXT,
565 ],
566 ]
567 );
568
569 $this->add_control(
570 'caption_background_color',
571 [
572 'label' => __( 'Background Color', 'elementor' ),
573 'type' => Controls_Manager::COLOR,
574 'selectors' => [
575 '{{WRAPPER}} .widget-image-caption' => 'background-color: {{VALUE}};',
576 ],
577 ]
578 );
579
580 $this->add_group_control(
581 Group_Control_Typography::get_type(),
582 [
583 'name' => 'caption_typography',
584 'selector' => '{{WRAPPER}} .widget-image-caption',
585 'global' => [
586 'default' => Global_Typography::TYPOGRAPHY_TEXT,
587 ],
588 ]
589 );
590
591 $this->add_group_control(
592 Group_Control_Text_Shadow::get_type(),
593 [
594 'name' => 'caption_text_shadow',
595 'selector' => '{{WRAPPER}} .widget-image-caption',
596 ]
597 );
598
599 $this->add_responsive_control(
600 'caption_space',
601 [
602 'label' => __( 'Spacing', 'elementor' ),
603 'type' => Controls_Manager::SLIDER,
604 'range' => [
605 'px' => [
606 'min' => 0,
607 'max' => 100,
608 ],
609 ],
610 'selectors' => [
611 '{{WRAPPER}} .widget-image-caption' => 'margin-top: {{SIZE}}{{UNIT}};',
612 ],
613 ]
614 );
615
616 $this->end_controls_section();
617 }
618
619 /**
620 * Check if the current widget has caption
621 *
622 * @access private
623 * @since 2.3.0
624 *
625 * @param array $settings
626 *
627 * @return boolean
628 */
629 private function has_caption( $settings ) {
630 return ( ! empty( $settings['caption_source'] ) && 'none' !== $settings['caption_source'] );
631 }
632
633 /**
634 * Get the caption for current widget.
635 *
636 * @access private
637 * @since 2.3.0
638 * @param $settings
639 *
640 * @return string
641 */
642 private function get_caption( $settings ) {
643 $caption = '';
644 if ( ! empty( $settings['caption_source'] ) ) {
645 switch ( $settings['caption_source'] ) {
646 case 'attachment':
647 $caption = wp_get_attachment_caption( $settings['image']['id'] );
648 break;
649 case 'custom':
650 $caption = ! Utils::is_empty( $settings['caption'] ) ? $settings['caption'] : '';
651 }
652 }
653 return $caption;
654 }
655
656 /**
657 * Render image widget output on the frontend.
658 *
659 * Written in PHP and used to generate the final HTML.
660 *
661 * @since 1.0.0
662 * @access protected
663 */
664 protected function render() {
665 $settings = $this->get_settings_for_display();
666
667 if ( empty( $settings['image']['url'] ) ) {
668 return;
669 }
670
671 if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) {
672 $this->add_render_attribute( 'wrapper', 'class', 'elementor-image' );
673 }
674
675 $has_caption = $this->has_caption( $settings );
676
677 $link = $this->get_link_url( $settings );
678
679 if ( $link ) {
680 $this->add_link_attributes( 'link', $link );
681
682 if ( Plugin::$instance->editor->is_edit_mode() ) {
683 $this->add_render_attribute( 'link', [
684 'class' => 'elementor-clickable',
685 ] );
686 }
687
688 if ( 'custom' !== $settings['link_to'] ) {
689 $this->add_lightbox_data_attributes( 'link', $settings['image']['id'], $settings['open_lightbox'] );
690 }
691 } ?>
692 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
693 <div <?php echo $this->get_render_attribute_string( 'wrapper' ); ?>>
694 <?php } ?>
695 <?php if ( $has_caption ) : ?>
696 <figure class="wp-caption">
697 <?php endif; ?>
698 <?php if ( $link ) : ?>
699 <a <?php echo $this->get_render_attribute_string( 'link' ); ?>>
700 <?php endif; ?>
701 <?php echo Group_Control_Image_Size::get_attachment_image_html( $settings ); ?>
702 <?php if ( $link ) : ?>
703 </a>
704 <?php endif; ?>
705 <?php if ( $has_caption ) : ?>
706 <figcaption class="widget-image-caption wp-caption-text"><?php echo $this->get_caption( $settings ); ?></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