PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.0-dev1
Elementor Website Builder – more than just a page builder v3.6.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 / trunk / includes / elements / section.php

section.php in Elementor Website Builder – more than just a page builder 3.6.0-dev1, at trunk/includes/elements/section.php

1,582 lines 38.2 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 /**
9 * Elementor section element.
10 *
11 * Elementor section handler class is responsible for initializing the section
12 * element.
13 *
14 * @since 1.0.0
15 */
16 class Element_Section extends Element_Base {
17
18 /**
19 * Section predefined columns presets.
20 *
21 * Holds the predefined columns width for each columns count available by
22 * default by Elementor. Default is an empty array.
23 *
24 * Note that when the user creates a section he can define custom sizes for
25 * the columns. But Elementor sets default values for predefined columns.
26 *
27 * For example two columns 50% width each one, or three columns 33.33% each
28 * one. This property hold the data for those preset values.
29 *
30 * @since 1.0.0
31 * @access private
32 * @static
33 *
34 * @var array Section presets.
35 */
36 private static $presets = [];
37
38 /**
39 * Get element type.
40 *
41 * Retrieve the element type, in this case `section`.
42 *
43 * @since 2.1.0
44 * @access public
45 * @static
46 *
47 * @return string The type.
48 */
49 public static function get_type() {
50 return 'section';
51 }
52
53 /**
54 * Get section name.
55 *
56 * Retrieve the section name.
57 *
58 * @since 1.0.0
59 * @access public
60 *
61 * @return string Section name.
62 */
63 public function get_name() {
64 return 'section';
65 }
66
67 /**
68 * Get section title.
69 *
70 * Retrieve the section title.
71 *
72 * @since 1.0.0
73 * @access public
74 *
75 * @return string Section title.
76 */
77 public function get_title() {
78 return esc_html__( 'Section', 'elementor' );
79 }
80
81 /**
82 * Get section icon.
83 *
84 * Retrieve the section icon.
85 *
86 * @since 1.0.0
87 * @access public
88 *
89 * @return string Section icon.
90 */
91 public function get_icon() {
92 return 'eicon-columns';
93 }
94
95 /**
96 * Get presets.
97 *
98 * Retrieve a specific preset columns for a given columns count, or a list
99 * of all the preset if no parameters passed.
100 *
101 * @since 1.0.0
102 * @access public
103 * @static
104 *
105 * @param int $columns_count Optional. Columns count. Default is null.
106 * @param int $preset_index Optional. Preset index. Default is null.
107 *
108 * @return array Section presets.
109 */
110 public static function get_presets( $columns_count = null, $preset_index = null ) {
111 if ( ! self::$presets ) {
112 self::init_presets();
113 }
114
115 $presets = self::$presets;
116
117 if ( null !== $columns_count ) {
118 $presets = $presets[ $columns_count ];
119 }
120
121 if ( null !== $preset_index ) {
122 $presets = $presets[ $preset_index ];
123 }
124
125 return $presets;
126 }
127
128 /**
129 * Initialize presets.
130 *
131 * Initializing the section presets and set the number of columns the
132 * section can have by default. For example a column can have two columns
133 * 50% width each one, or three columns 33.33% each one.
134 *
135 * Note that Elementor sections have default section presets but the user
136 * can set custom number of columns and define custom sizes for each column.
137
138 * @since 1.0.0
139 * @access public
140 * @static
141 */
142 public static function init_presets() {
143 $additional_presets = [
144 2 => [
145 [
146 'preset' => [ 33, 66 ],
147 ],
148 [
149 'preset' => [ 66, 33 ],
150 ],
151 ],
152 3 => [
153 [
154 'preset' => [ 25, 25, 50 ],
155 ],
156 [
157 'preset' => [ 50, 25, 25 ],
158 ],
159 [
160 'preset' => [ 25, 50, 25 ],
161 ],
162 [
163 'preset' => [ 16, 66, 16 ],
164 ],
165 ],
166 ];
167
168 foreach ( range( 1, 10 ) as $columns_count ) {
169 self::$presets[ $columns_count ] = [
170 [
171 'preset' => [],
172 ],
173 ];
174
175 $preset_unit = floor( 1 / $columns_count * 100 );
176
177 for ( $i = 0; $i < $columns_count; $i++ ) {
178 self::$presets[ $columns_count ][0]['preset'][] = $preset_unit;
179 }
180
181 if ( ! empty( $additional_presets[ $columns_count ] ) ) {
182 self::$presets[ $columns_count ] = array_merge( self::$presets[ $columns_count ], $additional_presets[ $columns_count ] );
183 }
184
185 foreach ( self::$presets[ $columns_count ] as $preset_index => & $preset ) {
186 $preset['key'] = $columns_count . $preset_index;
187 }
188 }
189 }
190
191 /**
192 * Get initial config.
193 *
194 * Retrieve the current section initial configuration.
195 *
196 * Adds more configuration on top of the controls list, the tabs assigned to
197 * the control, element name, type, icon and more. This method also adds
198 * section presets.
199 *
200 * @since 2.9.0
201 * @access protected
202 *
203 * @return array The initial config.
204 */
205 protected function get_initial_config() {
206 $config = parent::get_initial_config();
207
208 $config['presets'] = self::get_presets();
209 $config['controls'] = $this->get_controls();
210 $config['tabs_controls'] = $this->get_tabs_controls();
211
212 return $config;
213 }
214
215 /**
216 * Register section controls.
217 *
218 * Used to add new controls to the section element.
219 *
220 * @since 3.1.0
221 * @access protected
222 */
223 protected function register_controls() {
224 $this->start_controls_section(
225 'section_layout',
226 [
227 'label' => esc_html__( 'Layout', 'elementor' ),
228 'tab' => Controls_Manager::TAB_LAYOUT,
229 ]
230 );
231
232 // Element Name for the Navigator
233 $this->add_control(
234 '_title',
235 [
236 'label' => esc_html__( 'Title', 'elementor' ),
237 'type' => Controls_Manager::HIDDEN,
238 'render_type' => 'none',
239 ]
240 );
241
242 $this->add_control(
243 'layout',
244 [
245 'label' => esc_html__( 'Content Width', 'elementor' ),
246 'type' => Controls_Manager::SELECT,
247 'default' => 'boxed',
248 'options' => [
249 'boxed' => esc_html__( 'Boxed', 'elementor' ),
250 'full_width' => esc_html__( 'Full Width', 'elementor' ),
251 ],
252 'prefix_class' => 'elementor-section-',
253 ]
254 );
255
256 $this->add_responsive_control(
257 'content_width',
258 [
259 'label' => esc_html__( 'Width', 'elementor' ),
260 'type' => Controls_Manager::SLIDER,
261 'range' => [
262 'px' => [
263 'min' => 500,
264 'max' => 1600,
265 ],
266 ],
267 'selectors' => [
268 '{{WRAPPER}} > .elementor-container' => 'max-width: {{SIZE}}{{UNIT}};',
269 ],
270 'condition' => [
271 'layout' => [ 'boxed' ],
272 ],
273 'separator' => 'none',
274 ]
275 );
276
277 $this->add_control(
278 'gap',
279 [
280 'label' => esc_html__( 'Columns Gap', 'elementor' ),
281 'type' => Controls_Manager::SELECT,
282 'default' => 'default',
283 'options' => [
284 'default' => esc_html__( 'Default', 'elementor' ),
285 'no' => esc_html__( 'No Gap', 'elementor' ),
286 'narrow' => esc_html__( 'Narrow', 'elementor' ),
287 'extended' => esc_html__( 'Extended', 'elementor' ),
288 'wide' => esc_html__( 'Wide', 'elementor' ),
289 'wider' => esc_html__( 'Wider', 'elementor' ),
290 'custom' => esc_html__( 'Custom', 'elementor' ),
291 ],
292 ]
293 );
294
295 $this->add_responsive_control(
296 'gap_columns_custom',
297 [
298 'label' => esc_html__( 'Custom Columns Gap', 'elementor' ),
299 'type' => Controls_Manager::SLIDER,
300 'range' => [
301 'px' => [
302 'min' => 0,
303 'max' => 500,
304 ],
305 '%' => [
306 'min' => 0,
307 'max' => 100,
308 ],
309 'vh' => [
310 'min' => 0,
311 'max' => 100,
312 ],
313 'vw' => [
314 'min' => 0,
315 'max' => 100,
316 ],
317 ],
318 'size_units' => [ 'px', '%', 'vh', 'vw' ],
319 'selectors' => [
320 '{{WRAPPER}} .elementor-column-gap-custom .elementor-column > .elementor-element-populated' => 'padding: {{SIZE}}{{UNIT}};',
321 ],
322 'condition' => [
323 'gap' => 'custom',
324 ],
325 ]
326 );
327
328 $this->add_control(
329 'height',
330 [
331 'label' => esc_html__( 'Height', 'elementor' ),
332 'type' => Controls_Manager::SELECT,
333 'default' => 'default',
334 'options' => [
335 'default' => esc_html__( 'Default', 'elementor' ),
336 'full' => esc_html__( 'Fit To Screen', 'elementor' ),
337 'min-height' => esc_html__( 'Min Height', 'elementor' ),
338 ],
339 'prefix_class' => 'elementor-section-height-',
340 'hide_in_inner' => true,
341 ]
342 );
343
344 $this->add_responsive_control(
345 'custom_height',
346 [
347 'label' => esc_html__( 'Minimum Height', 'elementor' ),
348 'type' => Controls_Manager::SLIDER,
349 'default' => [
350 'size' => 400,
351 ],
352 'range' => [
353 'px' => [
354 'min' => 0,
355 'max' => 1440,
356 ],
357 'vh' => [
358 'min' => 0,
359 'max' => 100,
360 ],
361 'vw' => [
362 'min' => 0,
363 'max' => 100,
364 ],
365 ],
366 'size_units' => [ 'px', 'vh', 'vw' ],
367 'selectors' => [
368 '{{WRAPPER}} > .elementor-container' => 'min-height: {{SIZE}}{{UNIT}};',
369 ],
370 'condition' => [
371 'height' => [ 'min-height' ],
372 ],
373 'hide_in_inner' => true,
374 ]
375 );
376
377 $this->add_control(
378 'height_inner',
379 [
380 'label' => esc_html__( 'Height', 'elementor' ),
381 'type' => Controls_Manager::SELECT,
382 'default' => 'default',
383 'options' => [
384 'default' => esc_html__( 'Default', 'elementor' ),
385 'full' => esc_html__( 'Fit To Screen', 'elementor' ),
386 'min-height' => esc_html__( 'Min Height', 'elementor' ),
387 ],
388 'prefix_class' => 'elementor-section-height-',
389 'hide_in_top' => true,
390 ]
391 );
392
393 $this->add_responsive_control(
394 'custom_height_inner',
395 [
396 'label' => esc_html__( 'Minimum Height', 'elementor' ),
397 'type' => Controls_Manager::SLIDER,
398 'default' => [
399 'size' => 400,
400 ],
401 'range' => [
402 'px' => [
403 'min' => 0,
404 'max' => 1440,
405 ],
406 ],
407 'selectors' => [
408 '{{WRAPPER}} > .elementor-container' => 'min-height: {{SIZE}}{{UNIT}};',
409 ],
410 'condition' => [
411 'height_inner' => [ 'min-height' ],
412 ],
413 'size_units' => [ 'px', 'vh', 'vw' ],
414 'hide_in_top' => true,
415 ]
416 );
417
418 $this->add_control(
419 'column_position',
420 [
421 'label' => esc_html__( 'Column Position', 'elementor' ),
422 'type' => Controls_Manager::SELECT,
423 'default' => 'middle',
424 'options' => [
425 'stretch' => esc_html__( 'Stretch', 'elementor' ),
426 'top' => esc_html__( 'Top', 'elementor' ),
427 'middle' => esc_html__( 'Middle', 'elementor' ),
428 'bottom' => esc_html__( 'Bottom', 'elementor' ),
429 ],
430 'prefix_class' => 'elementor-section-items-',
431 'condition' => [
432 'height' => [ 'full', 'min-height' ],
433 ],
434 ]
435 );
436
437 $content_position_selector = Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ?
438 '{{WRAPPER}} > .elementor-container > .elementor-column > .elementor-widget-wrap' :
439 '{{WRAPPER}} > .elementor-container > .elementor-row > .elementor-column > .elementor-column-wrap > .elementor-widget-wrap';
440
441 $this->add_control(
442 'content_position',
443 [
444 'label' => esc_html__( 'Vertical Align', 'elementor' ),
445 'type' => Controls_Manager::SELECT,
446 'default' => '',
447 'options' => [
448 '' => esc_html__( 'Default', 'elementor' ),
449 'top' => esc_html__( 'Top', 'elementor' ),
450 'middle' => esc_html__( 'Middle', 'elementor' ),
451 'bottom' => esc_html__( 'Bottom', 'elementor' ),
452 'space-between' => esc_html__( 'Space Between', 'elementor' ),
453 'space-around' => esc_html__( 'Space Around', 'elementor' ),
454 'space-evenly' => esc_html__( 'Space Evenly', 'elementor' ),
455 ],
456 'selectors_dictionary' => [
457 'top' => 'flex-start',
458 'middle' => 'center',
459 'bottom' => 'flex-end',
460 ],
461 'selectors' => [
462 $content_position_selector => 'align-content: {{VALUE}}; align-items: {{VALUE}};',
463 ],
464 // TODO: The following line is for BC since 2.7.0
465 'prefix_class' => 'elementor-section-content-',
466 ]
467 );
468
469 $this->add_control(
470 'overflow',
471 [
472 'label' => esc_html__( 'Overflow', 'elementor' ),
473 'type' => Controls_Manager::SELECT,
474 'default' => '',
475 'options' => [
476 '' => esc_html__( 'Default', 'elementor' ),
477 'hidden' => esc_html__( 'Hidden', 'elementor' ),
478 ],
479 'selectors' => [
480 '{{WRAPPER}}' => 'overflow: {{VALUE}}',
481 ],
482 ]
483 );
484
485 $this->add_control(
486 'stretch_section',
487 [
488 'label' => esc_html__( 'Stretch Section', 'elementor' ),
489 'type' => Controls_Manager::SWITCHER,
490 'default' => '',
491 'return_value' => 'section-stretched',
492 'prefix_class' => 'elementor-',
493 'hide_in_inner' => true,
494 'description' => esc_html__( 'Stretch the section to the full width of the page using JS.', 'elementor' ) . sprintf( ' <a href="%1$s" target="_blank">%2$s</a>', 'https://go.elementor.com/stretch-section/', esc_html__( 'Learn more.', 'elementor' ) ),
495 'render_type' => 'none',
496 'frontend_available' => true,
497 ]
498 );
499
500 $possible_tags = [
501 'div',
502 'header',
503 'footer',
504 'main',
505 'article',
506 'section',
507 'aside',
508 'nav',
509 ];
510
511 $options = [
512 '' => esc_html__( 'Default', 'elementor' ),
513 ] + array_combine( $possible_tags, $possible_tags );
514
515 $this->add_control(
516 'html_tag',
517 [
518 'label' => esc_html__( 'HTML Tag', 'elementor' ),
519 'type' => Controls_Manager::SELECT,
520 'options' => $options,
521 'separator' => 'before',
522 ]
523 );
524
525 $this->end_controls_section();
526
527 // Section Structure
528 $this->start_controls_section(
529 'section_structure',
530 [
531 'label' => esc_html__( 'Structure', 'elementor' ),
532 'tab' => Controls_Manager::TAB_LAYOUT,
533 ]
534 );
535
536 $this->add_control(
537 'structure',
538 [
539 'label' => esc_html__( 'Structure', 'elementor' ),
540 'type' => Controls_Manager::STRUCTURE,
541 'default' => '10',
542 'render_type' => 'none',
543 'style_transfer' => false,
544 ]
545 );
546
547 $this->end_controls_section();
548
549 // Section background
550 $this->start_controls_section(
551 'section_background',
552 [
553 'label' => esc_html__( 'Background', 'elementor' ),
554 'tab' => Controls_Manager::TAB_STYLE,
555 ]
556 );
557
558 $this->start_controls_tabs( 'tabs_background' );
559
560 $this->start_controls_tab(
561 'tab_background_normal',
562 [
563 'label' => esc_html__( 'Normal', 'elementor' ),
564 ]
565 );
566
567 $this->add_group_control(
568 Group_Control_Background::get_type(),
569 [
570 'name' => 'background',
571 'types' => [ 'classic', 'gradient', 'video', 'slideshow' ],
572 'fields_options' => [
573 'background' => [
574 'frontend_available' => true,
575 ],
576 ],
577 ]
578 );
579
580 $this->end_controls_tab();
581
582 $this->start_controls_tab(
583 'tab_background_hover',
584 [
585 'label' => esc_html__( 'Hover', 'elementor' ),
586 ]
587 );
588
589 $this->add_group_control(
590 Group_Control_Background::get_type(),
591 [
592 'name' => 'background_hover',
593 'selector' => '{{WRAPPER}}:hover',
594 ]
595 );
596
597 $this->add_control(
598 'background_hover_transition',
599 [
600 'label' => esc_html__( 'Transition Duration', 'elementor' ),
601 'type' => Controls_Manager::SLIDER,
602 'default' => [
603 'size' => 0.3,
604 ],
605 'range' => [
606 'px' => [
607 'max' => 3,
608 'step' => 0.1,
609 ],
610 ],
611 'render_type' => 'ui',
612 'separator' => 'before',
613 ]
614 );
615
616 $this->end_controls_tab();
617
618 $this->end_controls_tabs();
619
620 $this->end_controls_section();
621
622 // Background Overlay
623 $this->start_controls_section(
624 'section_background_overlay',
625 [
626 'label' => esc_html__( 'Background Overlay', 'elementor' ),
627 'tab' => Controls_Manager::TAB_STYLE,
628 ]
629 );
630
631 $this->start_controls_tabs( 'tabs_background_overlay' );
632
633 $this->start_controls_tab(
634 'tab_background_overlay_normal',
635 [
636 'label' => esc_html__( 'Normal', 'elementor' ),
637 ]
638 );
639
640 $this->add_group_control(
641 Group_Control_Background::get_type(),
642 [
643 'name' => 'background_overlay',
644 'selector' => '{{WRAPPER}} > .elementor-background-overlay',
645 ]
646 );
647
648 $this->add_control(
649 'background_overlay_opacity',
650 [
651 'label' => esc_html__( 'Opacity', 'elementor' ),
652 'type' => Controls_Manager::SLIDER,
653 'default' => [
654 'size' => .5,
655 ],
656 'range' => [
657 'px' => [
658 'max' => 1,
659 'step' => 0.01,
660 ],
661 ],
662 'selectors' => [
663 '{{WRAPPER}} > .elementor-background-overlay' => 'opacity: {{SIZE}};',
664 ],
665 'condition' => [
666 'background_overlay_background' => [ 'classic', 'gradient' ],
667 ],
668 ]
669 );
670
671 $this->add_group_control(
672 Group_Control_Css_Filter::get_type(),
673 [
674 'name' => 'css_filters',
675 'selector' => '{{WRAPPER}} .elementor-background-overlay',
676 'conditions' => [
677 'relation' => 'or',
678 'terms' => [
679 [
680 'name' => 'background_overlay_image[url]',
681 'operator' => '!==',
682 'value' => '',
683 ],
684 [
685 'name' => 'background_overlay_color',
686 'operator' => '!==',
687 'value' => '',
688 ],
689 ],
690 ],
691 ]
692 );
693
694 $this->add_control(
695 'overlay_blend_mode',
696 [
697 'label' => esc_html__( 'Blend Mode', 'elementor' ),
698 'type' => Controls_Manager::SELECT,
699 'options' => [
700 '' => esc_html__( 'Normal', 'elementor' ),
701 'multiply' => esc_html__( 'Multiply', 'elementor' ),
702 'screen' => esc_html__( 'Screen', 'elementor' ),
703 'overlay' => esc_html__( 'Overlay', 'elementor' ),
704 'darken' => esc_html__( 'Darken', 'elementor' ),
705 'lighten' => esc_html__( 'Lighten', 'elementor' ),
706 'color-dodge' => esc_html__( 'Color Dodge', 'elementor' ),
707 'saturation' => esc_html__( 'Saturation', 'elementor' ),
708 'color' => esc_html__( 'Color', 'elementor' ),
709 'luminosity' => esc_html__( 'Luminosity', 'elementor' ),
710 'difference' => esc_html__( 'Difference', 'elementor' ),
711 'exclusion' => esc_html__( 'Exclusion', 'elementor' ),
712 'hue' => esc_html__( 'Hue', 'elementor' ),
713 ],
714 'selectors' => [
715 '{{WRAPPER}} > .elementor-background-overlay' => 'mix-blend-mode: {{VALUE}}',
716 ],
717 'conditions' => [
718 'relation' => 'or',
719 'terms' => [
720 [
721 'name' => 'background_overlay_image[url]',
722 'operator' => '!==',
723 'value' => '',
724 ],
725 [
726 'name' => 'background_overlay_color',
727 'operator' => '!==',
728 'value' => '',
729 ],
730 ],
731 ],
732 ]
733 );
734
735 $this->end_controls_tab();
736
737 $this->start_controls_tab(
738 'tab_background_overlay_hover',
739 [
740 'label' => esc_html__( 'Hover', 'elementor' ),
741 ]
742 );
743
744 $this->add_group_control(
745 Group_Control_Background::get_type(),
746 [
747 'name' => 'background_overlay_hover',
748 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
749 ]
750 );
751
752 $this->add_control(
753 'background_overlay_hover_opacity',
754 [
755 'label' => esc_html__( 'Opacity', 'elementor' ),
756 'type' => Controls_Manager::SLIDER,
757 'default' => [
758 'size' => .5,
759 ],
760 'range' => [
761 'px' => [
762 'max' => 1,
763 'step' => 0.01,
764 ],
765 ],
766 'selectors' => [
767 '{{WRAPPER}}:hover > .elementor-background-overlay' => 'opacity: {{SIZE}};',
768 ],
769 'condition' => [
770 'background_overlay_hover_background' => [ 'classic', 'gradient' ],
771 ],
772 ]
773 );
774
775 $this->add_group_control(
776 Group_Control_Css_Filter::get_type(),
777 [
778 'name' => 'css_filters_hover',
779 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
780 ]
781 );
782
783 $this->add_control(
784 'background_overlay_hover_transition',
785 [
786 'label' => esc_html__( 'Transition Duration', 'elementor' ),
787 'type' => Controls_Manager::SLIDER,
788 'default' => [
789 'size' => 0.3,
790 ],
791 'range' => [
792 'px' => [
793 'max' => 3,
794 'step' => 0.1,
795 ],
796 ],
797 'render_type' => 'ui',
798 'separator' => 'before',
799 ]
800 );
801
802 $this->end_controls_tab();
803
804 $this->end_controls_tabs();
805
806 $this->end_controls_section();
807
808 // Section border
809 $this->start_controls_section(
810 'section_border',
811 [
812 'label' => esc_html__( 'Border', 'elementor' ),
813 'tab' => Controls_Manager::TAB_STYLE,
814 ]
815 );
816
817 $this->start_controls_tabs( 'tabs_border' );
818
819 $this->start_controls_tab(
820 'tab_border_normal',
821 [
822 'label' => esc_html__( 'Normal', 'elementor' ),
823 ]
824 );
825
826 $this->add_group_control(
827 Group_Control_Border::get_type(),
828 [
829 'name' => 'border',
830 ]
831 );
832
833 $this->add_responsive_control(
834 'border_radius',
835 [
836 'label' => esc_html__( 'Border Radius', 'elementor' ),
837 'type' => Controls_Manager::DIMENSIONS,
838 'size_units' => [ 'px', '%' ],
839 'selectors' => [
840 '{{WRAPPER}}, {{WRAPPER}} > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
841 ],
842 ]
843 );
844
845 $this->add_group_control(
846 Group_Control_Box_Shadow::get_type(),
847 [
848 'name' => 'box_shadow',
849 ]
850 );
851
852 $this->end_controls_tab();
853
854 $this->start_controls_tab(
855 'tab_border_hover',
856 [
857 'label' => esc_html__( 'Hover', 'elementor' ),
858 ]
859 );
860
861 $this->add_group_control(
862 Group_Control_Border::get_type(),
863 [
864 'name' => 'border_hover',
865 'selector' => '{{WRAPPER}}:hover',
866 ]
867 );
868
869 $this->add_responsive_control(
870 'border_radius_hover',
871 [
872 'label' => esc_html__( 'Border Radius', 'elementor' ),
873 'type' => Controls_Manager::DIMENSIONS,
874 'size_units' => [ 'px', '%' ],
875 'selectors' => [
876 '{{WRAPPER}}:hover, {{WRAPPER}}:hover > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
877 ],
878 ]
879 );
880
881 $this->add_group_control(
882 Group_Control_Box_Shadow::get_type(),
883 [
884 'name' => 'box_shadow_hover',
885 'selector' => '{{WRAPPER}}:hover',
886 ]
887 );
888
889 $this->add_control(
890 'border_hover_transition',
891 [
892 'label' => esc_html__( 'Transition Duration', 'elementor' ),
893 'type' => Controls_Manager::SLIDER,
894 'separator' => 'before',
895 'default' => [
896 'size' => 0.3,
897 ],
898 'range' => [
899 'px' => [
900 'max' => 3,
901 'step' => 0.1,
902 ],
903 ],
904 'conditions' => [
905 'relation' => 'or',
906 'terms' => [
907 [
908 'name' => 'background_background',
909 'operator' => '!==',
910 'value' => '',
911 ],
912 [
913 'name' => 'border_border',
914 'operator' => '!==',
915 'value' => '',
916 ],
917 ],
918 ],
919 'selectors' => [
920 '{{WRAPPER}}' => 'transition: background {{background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s',
921 '{{WRAPPER}} > .elementor-background-overlay' => 'transition: background {{background_overlay_hover_transition.SIZE}}s, border-radius {{SIZE}}s, opacity {{background_overlay_hover_transition.SIZE}}s',
922 ],
923 ]
924 );
925
926 $this->end_controls_tab();
927
928 $this->end_controls_tabs();
929
930 $this->end_controls_section();
931
932 // Section Shape Divider
933 $this->start_controls_section(
934 'section_shape_divider',
935 [
936 'label' => esc_html__( 'Shape Divider', 'elementor' ),
937 'tab' => Controls_Manager::TAB_STYLE,
938 ]
939 );
940
941 $this->start_controls_tabs( 'tabs_shape_dividers' );
942
943 $shapes_options = [
944 '' => esc_html__( 'None', 'elementor' ),
945 ];
946
947 foreach ( Shapes::get_shapes() as $shape_name => $shape_props ) {
948 $shapes_options[ $shape_name ] = $shape_props['title'];
949 }
950
951 foreach ( [
952 'top' => esc_html__( 'Top', 'elementor' ),
953 'bottom' => esc_html__( 'Bottom', 'elementor' ),
954 ] as $side => $side_label ) {
955 $base_control_key = "shape_divider_$side";
956
957 $this->start_controls_tab(
958 "tab_$base_control_key",
959 [
960 'label' => $side_label,
961 ]
962 );
963
964 $this->add_control(
965 $base_control_key,
966 [
967 'label' => esc_html__( 'Type', 'elementor' ),
968 'type' => Controls_Manager::SELECT,
969 'options' => $shapes_options,
970 'render_type' => 'none',
971 'frontend_available' => true,
972 ]
973 );
974
975 $this->add_control(
976 $base_control_key . '_color',
977 [
978 'label' => esc_html__( 'Color', 'elementor' ),
979 'type' => Controls_Manager::COLOR,
980 'condition' => [
981 "shape_divider_$side!" => '',
982 ],
983 'selectors' => [
984 "{{WRAPPER}} > .elementor-shape-$side .elementor-shape-fill" => 'fill: {{UNIT}};',
985 ],
986 ]
987 );
988
989 $this->add_responsive_control(
990 $base_control_key . '_width',
991 [
992 'label' => esc_html__( 'Width', 'elementor' ),
993 'type' => Controls_Manager::SLIDER,
994 'default' => [
995 'unit' => '%',
996 ],
997 'tablet_default' => [
998 'unit' => '%',
999 ],
1000 'mobile_default' => [
1001 'unit' => '%',
1002 ],
1003 'range' => [
1004 '%' => [
1005 'min' => 100,
1006 'max' => 300,
1007 ],
1008 ],
1009 'condition' => [
1010 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'height_only', Shapes::FILTER_EXCLUDE ) ),
1011 ],
1012 'selectors' => [
1013 "{{WRAPPER}} > .elementor-shape-$side svg" => 'width: calc({{SIZE}}{{UNIT}} + 1.3px)',
1014 ],
1015 ]
1016 );
1017
1018 $this->add_responsive_control(
1019 $base_control_key . '_height',
1020 [
1021 'label' => esc_html__( 'Height', 'elementor' ),
1022 'type' => Controls_Manager::SLIDER,
1023 'range' => [
1024 'px' => [
1025 'max' => 500,
1026 ],
1027 ],
1028 'condition' => [
1029 "shape_divider_$side!" => '',
1030 ],
1031 'selectors' => [
1032 "{{WRAPPER}} > .elementor-shape-$side svg" => 'height: {{SIZE}}{{UNIT}};',
1033 ],
1034 ]
1035 );
1036
1037 $this->add_control(
1038 $base_control_key . '_flip',
1039 [
1040 'label' => esc_html__( 'Flip', 'elementor' ),
1041 'type' => Controls_Manager::SWITCHER,
1042 'condition' => [
1043 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_flip' ) ),
1044 ],
1045 'selectors' => [
1046 "{{WRAPPER}} > .elementor-shape-$side svg" => 'transform: translateX(-50%) rotateY(180deg)',
1047 ],
1048 ]
1049 );
1050
1051 $this->add_control(
1052 $base_control_key . '_negative',
1053 [
1054 'label' => esc_html__( 'Invert', 'elementor' ),
1055 'type' => Controls_Manager::SWITCHER,
1056 'frontend_available' => true,
1057 'condition' => [
1058 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_negative' ) ),
1059 ],
1060 'render_type' => 'none',
1061 ]
1062 );
1063
1064 $this->add_control(
1065 $base_control_key . '_above_content',
1066 [
1067 'label' => esc_html__( 'Bring to Front', 'elementor' ),
1068 'type' => Controls_Manager::SWITCHER,
1069 'selectors' => [
1070 "{{WRAPPER}} > .elementor-shape-$side" => 'z-index: 2; pointer-events: none',
1071 ],
1072 'condition' => [
1073 "shape_divider_$side!" => '',
1074 ],
1075 ]
1076 );
1077
1078 $this->end_controls_tab();
1079 }
1080
1081 $this->end_controls_tabs();
1082
1083 $this->end_controls_section();
1084
1085 // Section Typography
1086 $this->start_controls_section(
1087 'section_typo',
1088 [
1089 'label' => esc_html__( 'Typography', 'elementor' ),
1090 'tab' => Controls_Manager::TAB_STYLE,
1091 ]
1092 );
1093
1094 $this->add_control(
1095 'heading_color',
1096 [
1097 'label' => esc_html__( 'Heading Color', 'elementor' ),
1098 'type' => Controls_Manager::COLOR,
1099 'default' => '',
1100 'selectors' => [
1101 '{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
1102 ],
1103 'separator' => 'none',
1104 ]
1105 );
1106
1107 $this->add_control(
1108 'color_text',
1109 [
1110 'label' => esc_html__( 'Text Color', 'elementor' ),
1111 'type' => Controls_Manager::COLOR,
1112 'default' => '',
1113 'selectors' => [
1114 '{{WRAPPER}}' => 'color: {{VALUE}};',
1115 ],
1116 ]
1117 );
1118
1119 $this->add_control(
1120 'color_link',
1121 [
1122 'label' => esc_html__( 'Link Color', 'elementor' ),
1123 'type' => Controls_Manager::COLOR,
1124 'default' => '',
1125 'selectors' => [
1126 '{{WRAPPER}} a' => 'color: {{VALUE}};',
1127 ],
1128 ]
1129 );
1130
1131 $this->add_control(
1132 'color_link_hover',
1133 [
1134 'label' => esc_html__( 'Link Hover Color', 'elementor' ),
1135 'type' => Controls_Manager::COLOR,
1136 'default' => '',
1137 'selectors' => [
1138 '{{WRAPPER}} a:hover' => 'color: {{VALUE}};',
1139 ],
1140 ]
1141 );
1142
1143 $this->add_control(
1144 'text_align',
1145 [
1146 'label' => esc_html__( 'Text Align', 'elementor' ),
1147 'type' => Controls_Manager::CHOOSE,
1148 'options' => [
1149 'left' => [
1150 'title' => esc_html__( 'Left', 'elementor' ),
1151 'icon' => 'eicon-text-align-left',
1152 ],
1153 'center' => [
1154 'title' => esc_html__( 'Center', 'elementor' ),
1155 'icon' => 'eicon-text-align-center',
1156 ],
1157 'right' => [
1158 'title' => esc_html__( 'Right', 'elementor' ),
1159 'icon' => 'eicon-text-align-right',
1160 ],
1161 'justify' => [
1162 'title' => __( 'Justified', 'elementor' ),
1163 'icon' => 'eicon-text-align-justify',
1164 ],
1165 ],
1166 'selectors' => [
1167 '{{WRAPPER}} > .elementor-container' => 'text-align: {{VALUE}};',
1168 ],
1169 ]
1170 );
1171
1172 $this->end_controls_section();
1173
1174 // Section Advanced
1175 $this->start_controls_section(
1176 'section_advanced',
1177 [
1178 'label' => esc_html__( 'Advanced', 'elementor' ),
1179 'tab' => Controls_Manager::TAB_ADVANCED,
1180 ]
1181 );
1182
1183 $this->add_responsive_control(
1184 'margin',
1185 [
1186 'label' => esc_html__( 'Margin', 'elementor' ),
1187 'type' => Controls_Manager::DIMENSIONS,
1188 'size_units' => [ 'px', 'em', '%', 'rem' ],
1189 'allowed_dimensions' => 'vertical',
1190 'placeholder' => [
1191 'top' => '',
1192 'right' => 'auto',
1193 'bottom' => '',
1194 'left' => 'auto',
1195 ],
1196 'selectors' => [
1197 '{{WRAPPER}}' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};',
1198 ],
1199 ]
1200 );
1201
1202 $this->add_responsive_control(
1203 'padding',
1204 [
1205 'label' => esc_html__( 'Padding', 'elementor' ),
1206 'type' => Controls_Manager::DIMENSIONS,
1207 'size_units' => [ 'px', 'em', '%', 'rem' ],
1208 'selectors' => [
1209 '{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1210 ],
1211 ]
1212 );
1213
1214 $this->add_responsive_control(
1215 'z_index',
1216 [
1217 'label' => esc_html__( 'Z-Index', 'elementor' ),
1218 'type' => Controls_Manager::NUMBER,
1219 'min' => 0,
1220 'selectors' => [
1221 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
1222 ],
1223 ]
1224 );
1225
1226 $this->add_control(
1227 '_element_id',
1228 [
1229 'label' => esc_html__( 'CSS ID', 'elementor' ),
1230 'type' => Controls_Manager::TEXT,
1231 'default' => '',
1232 'dynamic' => [
1233 'active' => true,
1234 ],
1235 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
1236 'style_transfer' => false,
1237 'classes' => 'elementor-control-direction-ltr',
1238 ]
1239 );
1240
1241 $this->add_control(
1242 'css_classes',
1243 [
1244 'label' => esc_html__( 'CSS Classes', 'elementor' ),
1245 'type' => Controls_Manager::TEXT,
1246 'default' => '',
1247 'dynamic' => [
1248 'active' => true,
1249 ],
1250 'prefix_class' => '',
1251 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
1252 'classes' => 'elementor-control-direction-ltr',
1253 ]
1254 );
1255
1256 $this->end_controls_section();
1257
1258 $this->start_controls_section(
1259 'section_effects',
1260 [
1261 'label' => esc_html__( 'Motion Effects', 'elementor' ),
1262 'tab' => Controls_Manager::TAB_ADVANCED,
1263 ]
1264 );
1265
1266 $this->add_responsive_control(
1267 'animation',
1268 [
1269 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
1270 'type' => Controls_Manager::ANIMATION,
1271 'frontend_available' => true,
1272 ]
1273 );
1274
1275 $this->add_control(
1276 'animation_duration',
1277 [
1278 'label' => esc_html__( 'Animation Duration', 'elementor' ),
1279 'type' => Controls_Manager::SELECT,
1280 'default' => '',
1281 'options' => [
1282 'slow' => esc_html__( 'Slow', 'elementor' ),
1283 '' => esc_html__( 'Normal', 'elementor' ),
1284 'fast' => esc_html__( 'Fast', 'elementor' ),
1285 ],
1286 'prefix_class' => 'animated-',
1287 'condition' => [
1288 'animation!' => '',
1289 ],
1290 ]
1291 );
1292
1293 $this->add_control(
1294 'animation_delay',
1295 [
1296 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
1297 'type' => Controls_Manager::NUMBER,
1298 'default' => '',
1299 'min' => 0,
1300 'step' => 100,
1301 'condition' => [
1302 'animation!' => '',
1303 ],
1304 'render_type' => 'none',
1305 'frontend_available' => true,
1306 ]
1307 );
1308
1309 $this->end_controls_section();
1310
1311 // Section Responsive
1312 $this->start_controls_section(
1313 '_section_responsive',
1314 [
1315 'label' => esc_html__( 'Responsive', 'elementor' ),
1316 'tab' => Controls_Manager::TAB_ADVANCED,
1317 ]
1318 );
1319
1320 // The controls should be displayed from largest to smallest breakpoint, so we reverse the array.
1321 $active_breakpoints = array_reverse( Plugin::$instance->breakpoints->get_active_breakpoints() );
1322
1323 foreach ( $active_breakpoints as $breakpoint_key => $breakpoint ) {
1324 $this->add_control(
1325 'reverse_order_' . $breakpoint_key,
1326 [
1327 'label' => esc_html__( 'Reverse Columns', 'elementor' ) . ' (' . $breakpoint->get_label() . ')',
1328 'type' => Controls_Manager::SWITCHER,
1329 'default' => '',
1330 'prefix_class' => 'elementor-',
1331 'return_value' => 'reverse-' . $breakpoint_key,
1332 ]
1333 );
1334 }
1335
1336 $this->add_control(
1337 'heading_visibility',
1338 [
1339 'label' => esc_html__( 'Visibility', 'elementor' ),
1340 'type' => Controls_Manager::HEADING,
1341 'separator' => 'before',
1342 ]
1343 );
1344
1345 $this->add_control(
1346 'responsive_description',
1347 [
1348 'raw' => esc_html__( 'Responsive visibility will take effect only on preview or live page, and not while editing in Elementor.', 'elementor' ),
1349 'type' => Controls_Manager::RAW_HTML,
1350 'content_classes' => 'elementor-descriptor',
1351 ]
1352 );
1353
1354 $this->add_hidden_device_controls();
1355
1356 $this->end_controls_section();
1357
1358 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1359
1360 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1361 }
1362
1363 /**
1364 * Render section output in the editor.
1365 *
1366 * Used to generate the live preview, using a Backbone JavaScript template.
1367 *
1368 * @since 2.9.0
1369 * @access protected
1370 */
1371 protected function content_template() {
1372 ?>
1373 <#
1374 if ( settings.background_video_link ) {
1375 let videoAttributes = 'autoplay muted playsinline';
1376
1377 if ( ! settings.background_play_once ) {
1378 videoAttributes += ' loop';
1379 }
1380
1381 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-background-video-container' );
1382
1383 if ( ! settings.background_play_on_mobile ) {
1384 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-hidden-mobile' );
1385 }
1386 #>
1387 <div {{{ view.getRenderAttributeString( 'background-video-container' ) }}}>
1388 <div class="elementor-background-video-embed"></div>
1389 <video class="elementor-background-video-hosted elementor-html5-video" {{ videoAttributes }}></video>
1390 </div>
1391 <# } #>
1392 <div class="elementor-background-overlay"></div>
1393 <div class="elementor-shape elementor-shape-top"></div>
1394 <div class="elementor-shape elementor-shape-bottom"></div>
1395 <div class="elementor-container elementor-column-gap-{{ settings.gap }}">
1396 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
1397 <div class="elementor-row"></div>
1398 <?php } ?>
1399 </div>
1400 <?php
1401 }
1402
1403 /**
1404 * Before section rendering.
1405 *
1406 * Used to add stuff before the section element.
1407 *
1408 * @since 1.0.0
1409 * @access public
1410 */
1411 public function before_render() {
1412 $settings = $this->get_settings_for_display();
1413 ?>
1414 <<?php
1415 // PHPCS - the method get_html_tag is safe.
1416 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1417 ?> <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
1418 <?php
1419 if ( 'video' === $settings['background_background'] ) :
1420 if ( $settings['background_video_link'] ) :
1421 $video_properties = Embed::get_video_properties( $settings['background_video_link'] );
1422
1423 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-background-video-container' );
1424
1425 if ( ! $settings['background_play_on_mobile'] ) {
1426 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-hidden-phone' );
1427 }
1428 ?>
1429 <div <?php $this->print_render_attribute_string( 'background-video-container' ); ?>>
1430 <?php if ( $video_properties ) : ?>
1431 <div class="elementor-background-video-embed"></div>
1432 <?php
1433 else :
1434 $video_tag_attributes = 'autoplay muted playsinline';
1435 if ( 'yes' !== $settings['background_play_once'] ) :
1436 $video_tag_attributes .= ' loop';
1437 endif;
1438 ?>
1439 <video class="elementor-background-video-hosted elementor-html5-video" <?php
1440 // PHPCS - the variable $video_tag_attributes is a plain string.
1441 echo $video_tag_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1442 ?>></video>
1443 <?php endif; ?>
1444 </div>
1445 <?php
1446 endif;
1447 endif;
1448
1449 $has_background_overlay = in_array( $settings['background_overlay_background'], [ 'classic', 'gradient' ], true ) ||
1450 in_array( $settings['background_overlay_hover_background'], [ 'classic', 'gradient' ], true );
1451
1452 if ( $has_background_overlay ) :
1453 ?>
1454 <div class="elementor-background-overlay"></div>
1455 <?php
1456 endif;
1457
1458 if ( $settings['shape_divider_top'] ) {
1459 $this->print_shape_divider( 'top' );
1460 }
1461
1462 if ( $settings['shape_divider_bottom'] ) {
1463 $this->print_shape_divider( 'bottom' );
1464 }
1465 ?>
1466 <div class="elementor-container elementor-column-gap-<?php echo esc_attr( $settings['gap'] ); ?>">
1467 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
1468 <div class="elementor-row">
1469 <?php }
1470 }
1471
1472 /**
1473 * After section rendering.
1474 *
1475 * Used to add stuff after the section element.
1476 *
1477 * @since 1.0.0
1478 * @access public
1479 */
1480 public function after_render() {
1481 ?>
1482 <?php if ( ! Plugin::$instance->experiments->is_feature_active( 'e_dom_optimization' ) ) { ?>
1483 </div>
1484 <?php } ?>
1485 </div>
1486 </<?php
1487 // PHPCS - the method get_html_tag is safe.
1488 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1489 ?>>
1490 <?php
1491 }
1492
1493 /**
1494 * Add section render attributes.
1495 *
1496 * Used to add attributes to the current section wrapper HTML tag.
1497 *
1498 * @since 1.3.0
1499 * @access protected
1500 */
1501 protected function add_render_attributes() {
1502
1503 $section_type = $this->get_data( 'isInner' ) ? 'inner' : 'top';
1504
1505 $this->add_render_attribute(
1506 '_wrapper', 'class', [
1507 'elementor-section',
1508 'elementor-' . $section_type . '-section',
1509 ]
1510 );
1511
1512 parent::add_render_attributes();
1513 }
1514
1515 /**
1516 * Get default child type.
1517 *
1518 * Retrieve the section child type based on element data.
1519 *
1520 * @since 1.0.0
1521 * @access protected
1522 *
1523 * @param array $element_data Element ID.
1524 *
1525 * @return Element_Base Section default child type.
1526 */
1527 protected function _get_default_child_type( array $element_data ) {
1528 return Plugin::$instance->elements_manager->get_element_types( 'column' );
1529 }
1530
1531 /**
1532 * Get HTML tag.
1533 *
1534 * Retrieve the section element HTML tag.
1535 *
1536 * @since 1.5.3
1537 * @access private
1538 *
1539 * @return string Section HTML tag.
1540 */
1541 protected function get_html_tag() {
1542 $html_tag = $this->get_settings( 'html_tag' );
1543
1544 if ( empty( $html_tag ) ) {
1545 $html_tag = 'section';
1546 }
1547
1548 return Utils::validate_html_tag( $html_tag );
1549 }
1550
1551 /**
1552 * Print section shape divider.
1553 *
1554 * Used to generate the shape dividers HTML.
1555 *
1556 * @since 1.3.0
1557 * @access private
1558 *
1559 * @param string $side Shape divider side, used to set the shape key.
1560 */
1561 protected function print_shape_divider( $side ) {
1562 $settings = $this->get_active_settings();
1563 $base_setting_key = "shape_divider_$side";
1564 $negative = ! empty( $settings[ $base_setting_key . '_negative' ] );
1565 $shape_path = Shapes::get_shape_path( $settings[ $base_setting_key ], $negative );
1566 if ( ! is_file( $shape_path ) || ! is_readable( $shape_path ) ) {
1567 return;
1568 }
1569 ?>
1570 <div class="elementor-shape elementor-shape-<?php echo esc_attr( $side ); ?>" data-negative="<?php
1571 // PHPCS - the variable $negative is getting a setting value with a strict structure.
1572 echo var_export( $negative ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1573 ?>">
1574 <?php
1575 // PHPCS - The file content is being read from a strict file path structure.
1576 echo file_get_contents( $shape_path ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1577 ?>
1578 </div>
1579 <?php
1580 }
1581 }
1582