PluginProbe
Elementor Website Builder – more than just a page builder / 3.25.4
Elementor Website Builder – more than just a page builder v3.25.4
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 / heading.php

heading.php in Elementor Website Builder – more than just a page builder 3.25.4, at includes/widgets/heading.php

428 lines 10.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 use Elementor\Modules\ContentSanitizer\Interfaces\Sanitizable;
11
12 /**
13 * Elementor heading widget.
14 *
15 * Elementor widget that displays an eye-catching headlines.
16 *
17 * @since 1.0.0
18 */
19 class Widget_Heading extends Widget_Base implements Sanitizable {
20
21 /**
22 * Get widget name.
23 *
24 * Retrieve heading 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 'heading';
33 }
34
35 /**
36 * Get widget title.
37 *
38 * Retrieve heading 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__( 'Heading', 'elementor' );
47 }
48
49 /**
50 * Get widget icon.
51 *
52 * Retrieve heading 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-t-letter';
61 }
62
63 /**
64 * Get widget categories.
65 *
66 * Retrieve the list of categories the heading 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 [ 'heading', 'title', 'text' ];
91 }
92
93 protected function is_dynamic_content(): bool {
94 return false;
95 }
96
97 /**
98 * Get style dependencies.
99 *
100 * Retrieve the list of style dependencies the widget requires.
101 *
102 * @since 3.24.0
103 * @access public
104 *
105 * @return array Widget style dependencies.
106 */
107 public function get_style_depends(): array {
108 return [ 'widget-heading' ];
109 }
110
111 /**
112 * Remove data attributes from the html.
113 *
114 * @param string $content Heading title
115 * @return string
116 */
117 public function sanitize( $content ): string {
118 $allowed_tags = wp_kses_allowed_html( 'post' );
119 $allowed_tags_for_heading = [];
120 $non_allowed_tags = [ 'img' ];
121
122 foreach ( $allowed_tags as $tag => $attributes ) {
123 if ( in_array( $tag, $non_allowed_tags, true ) ) {
124 continue;
125 }
126
127 $filtered_attributes = array_filter( $attributes, function( $attribute ) {
128 return ! substr( $attribute, 0, 5 ) === 'data-';
129 }, ARRAY_FILTER_USE_KEY );
130
131 $allowed_tags_for_heading[ $tag ] = $filtered_attributes;
132 }
133
134 return wp_kses( $content, $allowed_tags_for_heading );
135 }
136
137 /**
138 * Get widget upsale data.
139 *
140 * Retrieve the widget promotion data.
141 *
142 * @since 3.18.0
143 * @access protected
144 *
145 * @return array Widget promotion data.
146 */
147 protected function get_upsale_data() {
148 return [
149 'condition' => ! Utils::has_pro(),
150 'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ),
151 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ),
152 'description' => esc_html__( 'Create captivating headings that rotate with the Animated Headline Widget.', 'elementor' ),
153 'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-heading-widget/' ),
154 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ),
155 ];
156 }
157
158 /**
159 * Register heading widget controls.
160 *
161 * Adds different input fields to allow the user to change and customize the widget settings.
162 *
163 * @since 3.1.0
164 * @access protected
165 */
166 protected function register_controls() {
167 $this->start_controls_section(
168 'section_title',
169 [
170 'label' => esc_html__( 'Heading', 'elementor' ),
171 ]
172 );
173
174 $this->add_control(
175 'title',
176 [
177 'label' => esc_html__( 'Title', 'elementor' ),
178 'type' => Controls_Manager::TEXTAREA,
179 'ai' => [
180 'type' => 'text',
181 ],
182 'dynamic' => [
183 'active' => true,
184 ],
185 'placeholder' => esc_html__( 'Enter your title', 'elementor' ),
186 'default' => esc_html__( 'Add Your Heading Text Here', 'elementor' ),
187 ]
188 );
189
190 $this->add_control(
191 'link',
192 [
193 'label' => esc_html__( 'Link', 'elementor' ),
194 'type' => Controls_Manager::URL,
195 'dynamic' => [
196 'active' => true,
197 ],
198 'default' => [
199 'url' => '',
200 ],
201 ]
202 );
203
204 $this->add_control(
205 'size',
206 [
207 'label' => esc_html__( 'Size', 'elementor' ),
208 'type' => Controls_Manager::SELECT,
209 'options' => [
210 'default' => esc_html__( 'Default', 'elementor' ),
211 'small' => esc_html__( 'Small', 'elementor' ),
212 'medium' => esc_html__( 'Medium', 'elementor' ),
213 'large' => esc_html__( 'Large', 'elementor' ),
214 'xl' => esc_html__( 'XL', 'elementor' ),
215 'xxl' => esc_html__( 'XXL', 'elementor' ),
216 ],
217 'default' => 'default',
218 'condition' => [
219 'size!' => 'default', // a workaround to hide the control, unless it's in use (not default).
220 ],
221 ]
222 );
223
224 $this->add_control(
225 'header_size',
226 [
227 'label' => esc_html__( 'HTML Tag', 'elementor' ),
228 'type' => Controls_Manager::SELECT,
229 'options' => [
230 'h1' => 'H1',
231 'h2' => 'H2',
232 'h3' => 'H3',
233 'h4' => 'H4',
234 'h5' => 'H5',
235 'h6' => 'H6',
236 'div' => 'div',
237 'span' => 'span',
238 'p' => 'p',
239 ],
240 'default' => 'h2',
241 ]
242 );
243
244 $this->end_controls_section();
245
246 $this->start_controls_section(
247 'section_title_style',
248 [
249 'label' => esc_html__( 'Heading', 'elementor' ),
250 'tab' => Controls_Manager::TAB_STYLE,
251 ]
252 );
253
254 $this->add_responsive_control(
255 'align',
256 [
257 'label' => esc_html__( 'Alignment', 'elementor' ),
258 'type' => Controls_Manager::CHOOSE,
259 'options' => [
260 'left' => [
261 'title' => esc_html__( 'Left', 'elementor' ),
262 'icon' => 'eicon-text-align-left',
263 ],
264 'center' => [
265 'title' => esc_html__( 'Center', 'elementor' ),
266 'icon' => 'eicon-text-align-center',
267 ],
268 'right' => [
269 'title' => esc_html__( 'Right', 'elementor' ),
270 'icon' => 'eicon-text-align-right',
271 ],
272 'justify' => [
273 'title' => esc_html__( 'Justified', 'elementor' ),
274 'icon' => 'eicon-text-align-justify',
275 ],
276 ],
277 'default' => '',
278 'selectors' => [
279 '{{WRAPPER}}' => 'text-align: {{VALUE}};',
280 ],
281 ]
282 );
283
284 $this->add_control(
285 'title_color',
286 [
287 'label' => esc_html__( 'Text Color', 'elementor' ),
288 'type' => Controls_Manager::COLOR,
289 'global' => [
290 'default' => Global_Colors::COLOR_PRIMARY,
291 ],
292 'selectors' => [
293 '{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
294 ],
295 ]
296 );
297
298 $this->add_group_control(
299 Group_Control_Typography::get_type(),
300 [
301 'name' => 'typography',
302 'global' => [
303 'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
304 ],
305 'selector' => '{{WRAPPER}} .elementor-heading-title',
306 ]
307 );
308
309 $this->add_group_control(
310 Group_Control_Text_Stroke::get_type(),
311 [
312 'name' => 'text_stroke',
313 'selector' => '{{WRAPPER}} .elementor-heading-title',
314 ]
315 );
316
317 $this->add_group_control(
318 Group_Control_Text_Shadow::get_type(),
319 [
320 'name' => 'text_shadow',
321 'selector' => '{{WRAPPER}} .elementor-heading-title',
322 ]
323 );
324
325 $this->add_control(
326 'blend_mode',
327 [
328 'label' => esc_html__( 'Blend Mode', 'elementor' ),
329 'type' => Controls_Manager::SELECT,
330 'options' => [
331 '' => esc_html__( 'Normal', 'elementor' ),
332 'multiply' => esc_html__( 'Multiply', 'elementor' ),
333 'screen' => esc_html__( 'Screen', 'elementor' ),
334 'overlay' => esc_html__( 'Overlay', 'elementor' ),
335 'darken' => esc_html__( 'Darken', 'elementor' ),
336 'lighten' => esc_html__( 'Lighten', 'elementor' ),
337 'color-dodge' => esc_html__( 'Color Dodge', 'elementor' ),
338 'saturation' => esc_html__( 'Saturation', 'elementor' ),
339 'color' => esc_html__( 'Color', 'elementor' ),
340 'difference' => esc_html__( 'Difference', 'elementor' ),
341 'exclusion' => esc_html__( 'Exclusion', 'elementor' ),
342 'hue' => esc_html__( 'Hue', 'elementor' ),
343 'luminosity' => esc_html__( 'Luminosity', 'elementor' ),
344 ],
345 'selectors' => [
346 '{{WRAPPER}} .elementor-heading-title' => 'mix-blend-mode: {{VALUE}}',
347 ],
348 ]
349 );
350
351 $this->end_controls_section();
352 }
353
354 /**
355 * Render heading widget output on the frontend.
356 *
357 * Written in PHP and used to generate the final HTML.
358 *
359 * @since 1.0.0
360 * @access protected
361 */
362 protected function render() {
363 $settings = $this->get_settings_for_display();
364
365 if ( '' === $settings['title'] ) {
366 return;
367 }
368
369 $this->add_render_attribute( 'title', 'class', 'elementor-heading-title' );
370
371 if ( ! empty( $settings['size'] ) ) {
372 $this->add_render_attribute( 'title', 'class', 'elementor-size-' . $settings['size'] );
373 } else {
374 $this->add_render_attribute( 'title', 'class', 'elementor-size-default' );
375 }
376
377 $this->add_inline_editing_attributes( 'title' );
378
379 $title = wp_kses_post( $settings['title'] );
380
381 if ( ! empty( $settings['link']['url'] ) ) {
382 $this->add_link_attributes( 'url', $settings['link'] );
383
384 $title = sprintf( '<a %1$s>%2$s</a>', $this->get_render_attribute_string( 'url' ), $title );
385 }
386
387 $title_html = sprintf( '<%1$s %2$s>%3$s</%1$s>', Utils::validate_html_tag( $settings['header_size'] ), $this->get_render_attribute_string( 'title' ), $title );
388
389 // PHPCS - the variable $title_html holds safe data.
390 echo $title_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
391 }
392
393 /**
394 * Render heading widget output in the editor.
395 *
396 * Written as a Backbone JavaScript template and used to generate the live preview.
397 *
398 * @since 2.9.0
399 * @access protected
400 */
401 protected function content_template() {
402 ?>
403 <#
404 let title = elementor.helpers.sanitize( settings.title, { ALLOW_DATA_ATTR: false } );
405
406 if ( '' !== settings.link.url ) {
407 title = '<a href="' + elementor.helpers.sanitizeUrl( settings.link.url ) + '">' + title + '</a>';
408 }
409
410 view.addRenderAttribute( 'title', 'class', [ 'elementor-heading-title' ] );
411
412 if ( '' !== settings.size ) {
413 view.addRenderAttribute( 'title', 'class', [ 'elementor-size-' + settings.size ] );
414 } else {
415 view.addRenderAttribute( 'title', 'class', [ 'elementor-size-default' ] );
416 }
417
418 view.addInlineEditingAttributes( 'title' );
419
420 var headerSizeTag = elementor.helpers.validateHTMLTag( settings.header_size ),
421 title_html = '<' + headerSizeTag + ' ' + view.getRenderAttributeString( 'title' ) + '>' + title + '</' + headerSizeTag + '>';
422
423 print( title_html );
424 #>
425 <?php
426 }
427 }
428