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

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

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