PluginProbe
Elementor Website Builder – more than just a page builder / 3.28.0-dev2
Elementor Website Builder – more than just a page builder v3.28.0-dev2
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 / text-editor.php

text-editor.php in Elementor Website Builder – more than just a page builder 3.28.0-dev2, at includes/widgets/text-editor.php

660 lines 14.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 text editor widget.
13 *
14 * Elementor widget that displays a WYSIWYG text editor, just like the WordPress
15 * editor.
16 *
17 * @since 1.0.0
18 */
19 class Widget_Text_Editor extends Widget_Base {
20
21 /**
22 * Get widget name.
23 *
24 * Retrieve text editor widget name.
25 *
26 * @since 1.0.0
27 * @access public
28 *
29 * @return string Widget name.
30 */
31 public function get_name() {
32 return 'text-editor';
33 }
34
35 /**
36 * Get widget title.
37 *
38 * Retrieve text editor widget title.
39 *
40 * @since 1.0.0
41 * @access public
42 *
43 * @return string Widget title.
44 */
45 public function get_title() {
46 return esc_html__( 'Text Editor', 'elementor' );
47 }
48
49 /**
50 * Get widget icon.
51 *
52 * Retrieve text editor widget icon.
53 *
54 * @since 1.0.0
55 * @access public
56 *
57 * @return string Widget icon.
58 */
59 public function get_icon() {
60 return 'eicon-text';
61 }
62
63 /**
64 * Get widget categories.
65 *
66 * Retrieve the list of categories the text editor widget belongs to.
67 *
68 * Used to determine where to display the widget in the editor.
69 *
70 * @since 2.0.0
71 * @access public
72 *
73 * @return array Widget categories.
74 */
75 public function get_categories() {
76 return [ 'basic' ];
77 }
78
79 /**
80 * Get widget keywords.
81 *
82 * Retrieve the list of keywords the widget belongs to.
83 *
84 * @since 2.1.0
85 * @access public
86 *
87 * @return array Widget keywords.
88 */
89 public function get_keywords() {
90 return [ 'text', 'editor' ];
91 }
92
93 /**
94 * Get style dependencies.
95 *
96 * Retrieve the list of style dependencies the widget requires.
97 *
98 * The 'widget-text-editor' style is required only when the drop cap is used.
99 * Therefor, style should not be loaded on the widget level, rather only on
100 * control level when the drop cap is active.
101 *
102 * Only in the Editor, these style should be loaded on the widget level.
103 *
104 * @since 3.24.0
105 * @access public
106 *
107 * @return array Widget style dependencies.
108 */
109 public function get_style_depends(): array {
110 $style_dependencies = Plugin::$instance->editor->is_edit_mode() || Plugin::$instance->preview->is_preview_mode()
111 ? [ 'widget-text-editor' ]
112 : [];
113
114 return $style_dependencies;
115 }
116
117 public function has_widget_inner_wrapper(): bool {
118 return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' );
119 }
120
121 /**
122 * Register text editor widget controls.
123 *
124 * Adds different input fields to allow the user to change and customize the widget settings.
125 *
126 * @since 3.1.0
127 * @access protected
128 */
129 protected function register_controls() {
130 $this->start_controls_section(
131 'section_editor',
132 [
133 'label' => esc_html__( 'Text Editor', 'elementor' ),
134 ]
135 );
136
137 $this->add_control(
138 'editor',
139 [
140 'label' => '',
141 'type' => Controls_Manager::WYSIWYG,
142 'default' => '<p>' . esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ) . '</p>',
143 ]
144 );
145
146 $this->add_control(
147 'drop_cap', [
148 'label' => esc_html__( 'Drop Cap', 'elementor' ),
149 'type' => Controls_Manager::SWITCHER,
150 'label_off' => esc_html__( 'Off', 'elementor' ),
151 'label_on' => esc_html__( 'On', 'elementor' ),
152 'prefix_class' => 'elementor-drop-cap-',
153 'frontend_available' => true,
154 'assets' => [
155 'styles' => [
156 [
157 'name' => 'widget-text-editor',
158 'conditions' => [
159 'terms' => [
160 [
161 'name' => 'drop_cap',
162 'operator' => '===',
163 'value' => 'yes',
164 ],
165 ],
166 ],
167 ],
168 ],
169
170 ],
171 ]
172 );
173
174 $this->add_responsive_control(
175 'text_columns',
176 [
177 'label' => esc_html__( 'Columns', 'elementor' ),
178 'type' => Controls_Manager::SELECT,
179 'separator' => 'before',
180 'options' => [
181 '' => esc_html__( 'Default', 'elementor' ),
182 '1' => esc_html__( '1', 'elementor' ),
183 '2' => esc_html__( '2', 'elementor' ),
184 '3' => esc_html__( '3', 'elementor' ),
185 '4' => esc_html__( '4', 'elementor' ),
186 '5' => esc_html__( '5', 'elementor' ),
187 '6' => esc_html__( '6', 'elementor' ),
188 '7' => esc_html__( '7', 'elementor' ),
189 '8' => esc_html__( '8', 'elementor' ),
190 '9' => esc_html__( '9', 'elementor' ),
191 '10' => esc_html__( '10', 'elementor' ),
192 ],
193 'selectors' => [
194 '{{WRAPPER}}' => 'columns: {{VALUE}};',
195 ],
196 ]
197 );
198
199 $this->add_responsive_control(
200 'column_gap',
201 [
202 'label' => esc_html__( 'Columns Gap', 'elementor' ),
203 'type' => Controls_Manager::SLIDER,
204 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
205 'range' => [
206 'px' => [
207 'max' => 100,
208 ],
209 '%' => [
210 'max' => 10,
211 'step' => 0.1,
212 ],
213 'vw' => [
214 'max' => 10,
215 'step' => 0.1,
216 ],
217 'em' => [
218 'max' => 10,
219 ],
220 'rem' => [
221 'max' => 10,
222 ],
223 ],
224 'selectors' => [
225 '{{WRAPPER}}' => 'column-gap: {{SIZE}}{{UNIT}};',
226 ],
227 'conditions' => [
228 'relation' => 'or',
229 'terms' => [
230 [
231 'name' => 'text_columns',
232 'operator' => '>',
233 'value' => 1,
234 ],
235 [
236 'name' => 'text_columns',
237 'operator' => '===',
238 'value' => '',
239 ],
240 ],
241 ],
242 ]
243 );
244
245 $this->end_controls_section();
246
247 $this->start_controls_section(
248 'section_style',
249 [
250 'label' => esc_html__( 'Text Editor', 'elementor' ),
251 'tab' => Controls_Manager::TAB_STYLE,
252 ]
253 );
254
255 $this->add_responsive_control(
256 'align',
257 [
258 'label' => esc_html__( 'Alignment', 'elementor' ),
259 'type' => Controls_Manager::CHOOSE,
260 'options' => [
261 'left' => [
262 'title' => esc_html__( 'Left', 'elementor' ),
263 'icon' => 'eicon-text-align-left',
264 ],
265 'center' => [
266 'title' => esc_html__( 'Center', 'elementor' ),
267 'icon' => 'eicon-text-align-center',
268 ],
269 'right' => [
270 'title' => esc_html__( 'Right', 'elementor' ),
271 'icon' => 'eicon-text-align-right',
272 ],
273 'justify' => [
274 'title' => esc_html__( 'Justified', 'elementor' ),
275 'icon' => 'eicon-text-align-justify',
276 ],
277 ],
278 'selectors' => [
279 '{{WRAPPER}}' => 'text-align: {{VALUE}};',
280 ],
281 'separator' => 'after',
282 ]
283 );
284
285 $this->add_group_control(
286 Group_Control_Typography::get_type(),
287 [
288 'name' => 'typography',
289 'global' => [
290 'default' => Global_Typography::TYPOGRAPHY_TEXT,
291 ],
292 ]
293 );
294
295 $this->add_group_control(
296 Group_Control_Text_Shadow::get_type(),
297 [
298 'name' => 'text_shadow',
299 'selector' => '{{WRAPPER}}',
300 ]
301 );
302
303 $this->add_responsive_control(
304 'paragraph_spacing',
305 [
306 'label' => esc_html__( 'Paragraph Spacing', 'elementor' ),
307 'type' => Controls_Manager::SLIDER,
308 'size_units' => [ 'px', 'em', 'rem', 'vh', 'custom' ],
309 'range' => [
310 'px' => [
311 'max' => 100,
312 ],
313 'em' => [
314 'min' => 0.1,
315 'max' => 20,
316 ],
317 ],
318 'selectors' => [
319 '{{WRAPPER}} p' => 'margin-bottom: {{SIZE}}{{UNIT}}',
320 ],
321 ]
322 );
323
324 $this->add_control(
325 'separator',
326 [
327 'type' => Controls_Manager::DIVIDER,
328 ]
329 );
330
331 $this->start_controls_tabs( 'link_colors' );
332
333 $this->start_controls_tab(
334 'colors_normal',
335 [
336 'label' => esc_html__( 'Normal', 'elementor' ),
337 ]
338 );
339
340 $this->add_control(
341 'text_color',
342 [
343 'label' => esc_html__( 'Text Color', 'elementor' ),
344 'type' => Controls_Manager::COLOR,
345 'default' => '',
346 'selectors' => [
347 '{{WRAPPER}}' => 'color: {{VALUE}};',
348 ],
349 'global' => [
350 'default' => Global_Colors::COLOR_TEXT,
351 ],
352 ]
353 );
354
355 $this->add_control(
356 'link_color',
357 [
358 'label' => esc_html__( 'Link Color', 'elementor' ),
359 'type' => Controls_Manager::COLOR,
360 'selectors' => [
361 '{{WRAPPER}} a' => 'color: {{VALUE}};',
362 ],
363 ]
364 );
365
366 $this->end_controls_tab();
367
368 $this->start_controls_tab(
369 'colors_hover',
370 [
371 'label' => esc_html__( 'Hover', 'elementor' ),
372 ]
373 );
374
375 $this->add_control(
376 'link_hover_color',
377 [
378 'label' => esc_html__( 'Link Color', 'elementor' ),
379 'type' => Controls_Manager::COLOR,
380 'selectors' => [
381 '{{WRAPPER}} a:hover, {{WRAPPER}} a:focus' => 'color: {{VALUE}};',
382 ],
383 ]
384 );
385
386 $this->add_control(
387 'link_hover_color_transition_duration',
388 [
389 'label' => esc_html__( 'Transition Duration', 'elementor' ),
390 'type' => Controls_Manager::SLIDER,
391 'size_units' => [ 's', 'ms', 'custom' ],
392 'default' => [
393 'unit' => 's',
394 ],
395 'selectors' => [
396 '{{WRAPPER}} a' => 'transition-duration: {{SIZE}}{{UNIT}};',
397 ],
398 ]
399 );
400
401 $this->end_controls_tab();
402
403 $this->end_controls_tabs();
404
405 $this->end_controls_section();
406
407 $this->start_controls_section(
408 'section_drop_cap',
409 [
410 'label' => esc_html__( 'Drop Cap', 'elementor' ),
411 'tab' => Controls_Manager::TAB_STYLE,
412 'condition' => [
413 'drop_cap' => 'yes',
414 ],
415 ]
416 );
417
418 $this->add_control(
419 'drop_cap_view',
420 [
421 'label' => esc_html__( 'View', 'elementor' ),
422 'type' => Controls_Manager::SELECT,
423 'options' => [
424 'default' => esc_html__( 'Default', 'elementor' ),
425 'stacked' => esc_html__( 'Stacked', 'elementor' ),
426 'framed' => esc_html__( 'Framed', 'elementor' ),
427 ],
428 'default' => 'default',
429 'prefix_class' => 'elementor-drop-cap-view-',
430 ]
431 );
432
433 $this->add_control(
434 'drop_cap_primary_color',
435 [
436 'label' => esc_html__( 'Primary Color', 'elementor' ),
437 'type' => Controls_Manager::COLOR,
438 'selectors' => [
439 '{{WRAPPER}}.elementor-drop-cap-view-stacked .elementor-drop-cap' => 'background-color: {{VALUE}};',
440 '{{WRAPPER}}.elementor-drop-cap-view-framed .elementor-drop-cap, {{WRAPPER}}.elementor-drop-cap-view-default .elementor-drop-cap' => 'color: {{VALUE}}; border-color: {{VALUE}};',
441 ],
442 'global' => [
443 'default' => Global_Colors::COLOR_PRIMARY,
444 ],
445 ]
446 );
447
448 $this->add_control(
449 'drop_cap_secondary_color',
450 [
451 'label' => esc_html__( 'Secondary Color', 'elementor' ),
452 'type' => Controls_Manager::COLOR,
453 'selectors' => [
454 '{{WRAPPER}}.elementor-drop-cap-view-framed .elementor-drop-cap' => 'background-color: {{VALUE}};',
455 '{{WRAPPER}}.elementor-drop-cap-view-stacked .elementor-drop-cap' => 'color: {{VALUE}};',
456 ],
457 'condition' => [
458 'drop_cap_view!' => 'default',
459 ],
460 ]
461 );
462
463 $this->add_group_control(
464 Group_Control_Text_Shadow::get_type(),
465 [
466 'name' => 'drop_cap_shadow',
467 'selector' => '{{WRAPPER}} .elementor-drop-cap',
468 ]
469 );
470
471 $this->add_control(
472 'drop_cap_size',
473 [
474 'label' => esc_html__( 'Size', 'elementor' ),
475 'type' => Controls_Manager::SLIDER,
476 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
477 'default' => [
478 'size' => 5,
479 ],
480 'range' => [
481 'px' => [
482 'max' => 30,
483 ],
484 'em' => [
485 'max' => 3,
486 ],
487 'rem' => [
488 'max' => 3,
489 ],
490 ],
491 'selectors' => [
492 '{{WRAPPER}} .elementor-drop-cap' => 'padding: {{SIZE}}{{UNIT}};',
493 ],
494 'condition' => [
495 'drop_cap_view!' => 'default',
496 ],
497 ]
498 );
499
500 $this->add_control(
501 'drop_cap_space',
502 [
503 'label' => esc_html__( 'Space', 'elementor' ),
504 'type' => Controls_Manager::SLIDER,
505 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
506 'default' => [
507 'size' => 10,
508 ],
509 'range' => [
510 'px' => [
511 'max' => 50,
512 ],
513 'em' => [
514 'max' => 5,
515 ],
516 'rem' => [
517 'max' => 5,
518 ],
519 ],
520 'selectors' => [
521 '{{WRAPPER}} .elementor-drop-cap' => 'margin-inline-end: {{SIZE}}{{UNIT}};',
522 ],
523 ]
524 );
525
526 $this->add_control(
527 'drop_cap_border_radius',
528 [
529 'label' => esc_html__( 'Border Radius', 'elementor' ),
530 'type' => Controls_Manager::SLIDER,
531 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
532 'default' => [
533 'unit' => '%',
534 ],
535 'range' => [
536 '%' => [
537 'max' => 50,
538 ],
539 ],
540 'selectors' => [
541 '{{WRAPPER}} .elementor-drop-cap' => 'border-radius: {{SIZE}}{{UNIT}};',
542 ],
543 'condition' => [
544 'drop_cap_view!' => 'default',
545 ],
546 ]
547 );
548
549 $this->add_control(
550 'drop_cap_border_width', [
551 'label' => esc_html__( 'Border Width', 'elementor' ),
552 'type' => Controls_Manager::DIMENSIONS,
553 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
554 'selectors' => [
555 '{{WRAPPER}} .elementor-drop-cap' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
556 ],
557 'condition' => [
558 'drop_cap_view' => 'framed',
559 ],
560 ]
561 );
562
563 $this->add_group_control(
564 Group_Control_Typography::get_type(),
565 [
566 'name' => 'drop_cap_typography',
567 'selector' => '{{WRAPPER}} .elementor-drop-cap-letter',
568 'exclude' => [
569 'letter_spacing',
570 ],
571 ]
572 );
573
574 $this->end_controls_section();
575 }
576
577 /**
578 * Render text editor widget output on the frontend.
579 *
580 * Written in PHP and used to generate the final HTML.
581 *
582 * @since 1.0.0
583 * @access protected
584 */
585 protected function render() {
586 $should_render_inline_editing = Plugin::$instance->editor->is_edit_mode();
587
588 $editor_content = $this->get_settings_for_display( 'editor' );
589 $editor_content = $this->parse_text_editor( $editor_content );
590
591 if ( empty( $editor_content ) ) {
592 return;
593 }
594
595 if ( $should_render_inline_editing ) {
596 $this->add_render_attribute( 'editor', 'class', [ 'elementor-text-editor', 'elementor-clearfix' ] );
597 }
598
599 $this->add_inline_editing_attributes( 'editor', 'advanced' );
600 ?>
601 <?php if ( $should_render_inline_editing ) { ?>
602 <div <?php $this->print_render_attribute_string( 'editor' ); ?>>
603 <?php } ?>
604 <?php // PHPCS - the main text of a widget should not be escaped.
605 echo $editor_content; // phpcs:ignore WordPress.Security.EscapeOutput ?>
606 <?php if ( $should_render_inline_editing ) { ?>
607 </div>
608 <?php } ?>
609 <?php
610 }
611
612 /**
613 * Render text editor widget as plain content.
614 *
615 * Override the default behavior by printing the content without rendering it.
616 *
617 * @since 1.0.0
618 * @access public
619 */
620 public function render_plain_content() {
621 // In plain mode, render without shortcode
622 $this->print_unescaped_setting( 'editor' );
623 }
624
625 /**
626 * Render text editor widget output in the editor.
627 *
628 * Written as a Backbone JavaScript template and used to generate the live preview.
629 *
630 * @since 2.9.0
631 * @access protected
632 */
633 protected function content_template() {
634 ?>
635 <#
636 if ( '' === settings.editor ) {
637 return;
638 }
639
640 const shouldRenderInlineEditing = elementorFrontend.isEditMode();
641
642 if ( shouldRenderInlineEditing ) {
643 view.addRenderAttribute( 'editor', 'class', [ 'elementor-text-editor', 'elementor-clearfix' ] );
644 }
645
646 view.addInlineEditingAttributes( 'editor', 'advanced' );
647
648 if ( shouldRenderInlineEditing ) { #>
649 <div {{{ view.getRenderAttributeString( 'editor' ) }}}>
650 <# } #>
651
652 {{{ settings.editor }}}
653
654 <# if ( shouldRenderInlineEditing ) { #>
655 </div>
656 <# } #>
657 <?php
658 }
659 }
660