How to add style formats to WordPress wp_editor() - php

I am trying to apply styles to all images that are inserted into my wp_editor() textarea using PHP. I have tried the following but had no success:
<?php
$settings = array(
'style_formats' => array(
array(
'block' => 'img',
'styles' => array(
'width' => '100%'
)
)
)
);
echo wp_editor('', 'email-content', $settings);
?>
What is the correct syntax to do this?
I have used the following docs to try complete this task:
https://developer.wordpress.org/reference/functions/wp_editor/
https://www.tiny.cloud/docs/configure/content-formatting/

If you only want to make all images 100%, then it might be more appropriate to just do it in your CSS stylesheet.
If you need to customise the WP Editor (which uses the TinyMCE editor), there are a few ways to do it, depending on what you want. The description and the code in your question don't match so I've given both options below:
1. Add a "Custom Styles" dropdown to the editor toolbar
The code in your question is what you would use to add a custom styles dropdown, similar to the default styles (Paragraph, Heading 1 etc). You can do this using the following code to your functions.php.
This adds a dropdown called "Formats" with 2 options - one to add the style directly on the image and one that adds a custom class to the image (which is preferable because it gives you more flexibility):
1. Set up the custom styles in the TinyMCE Editor settings
function my_mce_insert_custom_styles( $settings) {
// Create your array of custom styles to add
$style_formats = array(
// 1. OPTION TO ADD STYLE DIRECTLY TO THE IMAGE
array(
'title' => '100% Width Image Style',
'selector' => 'img',
'styles' => array( 'width' => '100%' )
),
// 2. OPTION TO ADD A CLASS TO THE IMAGE
array(
'title' => 'Add My Class to Image',
'selector' => 'img',
'classes' => 'my_image_class',
)
);
// Add the array the 'style_formats' setting
$init_array['style_formats'] = json_encode( $style_formats );
return $init_array;
}
add_filter( 'tiny_mce_before_init', 'my_mce_insert_custom_styles' );
// 2. Add custom styles to the 2nd toolbar of your Wordpress editor
function my_mce_buttons_2($buttons) {
array_unshift($buttons, 'styleselect');
return $buttons;
}
add_filter('mce_buttons_2', 'my_mce_buttons_2');
Now will have an extra "Formats" drop down in the 2nd toolbar on the editor. When you select an image, you can choose either of the formats above to apply to the image.
2. Automatically add a style / class to the inserted image
Even though you were using the code above, your description sounds like you want to automatically apply styling.
You can do this by adding the the following to your functions.php. Again, I have given options for adding the style directly to the image, or adding a class - you can remove the option you don't need:
function my_custom_image_styling($html, $id, $caption, $title, $align, $url, $size, $alt) {
$doc = new DOMDocument();
$doc->loadHTML($html);
$imgs = $doc->getElementsByTagName('img');
foreach($imgs as $img){
// 1. ADD THE STYLE ATTRIBUTE DIRECTLY TO THE IMAGE
$styles = $img->getAttribute("style");
$img->setAttribute("style", $styles."width:100%;");
// OR 2. ADD A CLASS TO THE IMAGE
$classes = $img->getAttribute("class");
$img->setAttribute("class", $classes." my_image_class");
}
$html = $doc->saveHTML();
return $html;
}
add_filter('image_send_to_editor', 'my_custom_image_styling', 1, 8);
Now, depending on which lines you use, the style or class will automatically be added to the image when it is being inserted into the editor.
References
tiny_mce_before_init hook
image_send_to_editor hook

I'm unsure about your request but if you're trying to inject css into the admin panel this is the way:
<?php function theme_admin_css() {
echo '
<style media="screen">
/* ... Your custom css goes here ... */
</style>
'; }
add_action( 'admin_head', 'theme_admin_css' ); ?>

Related

Disable lazy load in lagest contentful paint in WordPress

I found this 2 year old solution that essentially counts the and removes the loading attribute where the count =1 and implimented via snippets plugin for Wordpress.
Unfortunately GTMetrix is still flagging "don't lazy load LCP" and when I inspect the image in my browsers I still see the attribute loading="lazy" for the 1st (and every) image on every post.
I suspected it was counting the site logo in the header as the 1st image but it too has loading="lazy" so it seems that the code isn't working at all.
Wordpress 6.0.1
Theme: Hello Elementor Child
Elementor + Elementor Pro
JetEngine for custom post type
Imagify for webP conversion & optimization
I'm not running any lazy-loading plugin and don't want to disable wordpress's global lazy load for all images, just the one above the fold in the LCP.
Snippet I'm running:
/* Remove lazy load first image */
function add_responsive_class($content)
{
if ( is_single() || is_page() || is_front_page() || is_home() )
{
$content = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
$document = new DOMDocument();
libxml_use_internal_errors(true);
$document->loadHTML(utf8_decode($content));
$imgs = $document->getElementsByTagName('img');
$img = $imgs[0];
if ($imgs[0] == 1)
{ // Check first if it is the first image
$img->removeAttribute( 'loading' );
$html = $document->saveHTML();
return $html;
}
else
{
return $content;
}
}
else
{
return $content;
}
}
add_filter ('the_content', 'add_responsive_class');
If anyone can help me understand why this doesn't work on my site or has a different solution I'd appreciate the help.
Better if you give a higher priority to your filter. It could be that you try to remove something that still doesn't exist.
Elementor is responsible for the output of the image, and it may filter the content after your filter and add the loading parameter after your filter.
As a side note, you can't know if all the first images are always visible. Imagine for example an accordion, or something similar. I don't say that your script is not useful, but that it doesn't always guarantee the best results. Be sure you don't have hidden images. This may also be the cause of the failure of your script. Maybe you are removing the loading parameter to the first hidden images.
In the case of a hidden image, it would be better if they are lazy-loaded.
But if in your specific case, you are sure, then you should not have issues. In that case, check the priority of the filter.
You can also give the possibility in the Elementor editor to remove the lazy load. You can use this code:
add_action( 'elementor/element/image/section_image/before_section_end', function( $element, $args ) {
$element->start_injection( [
'at' => 'after',
'of' => 'link',
] );
$element->add_control(
'my_image_lazy_loading',
[
'label' => __( 'Lazy Loading','lazy-load-control-for-elementor' ),
'type' => \Elementor\Controls_Manager::SELECT,
'default' => 'lazy',
'options' => [
'lazy' => __( 'Lazy load','lazy-load-control-for-elementor' ),
'no_lazy' => __( 'Do not lazy load','lazy-load-control-for-elementor' ),
],
]
);
$element->end_injection();
}, 10, 2 );
add_action( 'elementor/widget/render_content', function( $content, $widget ){
if( $widget->get_name() === 'image' ){
$settings = $widget->get_settings();
if( isset( $settings['my_image_lazy_loading'] ) && 'no_lazy' === sanitize_text_field( $settings['my_image_lazy_loading'] ) ){
$content = str_replace( ' loading="lazy"','',$content );
}
}
return $content;
}, 10, 2 );
Then the user can decide which images should not be lazy loaded.

Add the custom widget value to the array on wordpress website

We have a home page banner in our WordPress website. Added a logic to show different images on page refresh.
The code for the images are placed in the help_functions.php, updated the file and it worked as expected.
$images = array( "https://images.pexels.com/photos/325185/pexels-photo-325185.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260", "https://images.pexels.com/photos/3787839/pexels-photo-3787839.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "https://images.pexels.com/photos/3769312/pexels-photo-3769312.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940")
$rand_img = array_rand($images, 1);
$image =$images[$rand_img];
Instead of hardcoding, I register a new custom widget by adding below code in the functions.php
register_sidebar(array(
'name' => esc_html__('Splash images Widget', 'wpresidence'),
'id' => 'splashimage-widget-area',
'description' => esc_html__('The splash image widget area', 'wpresidence'),
'before_widget' => ' ',
'after_widget' => ' ',
'before_title' => ' ',
'after_title' => ' ',
));
add_action( 'widgets_init', 'register_my_widgets' );
and I added the custom html to the widget and added the below code
array( "https://images.pexels.com/photos/325185/pexels-photo-325185.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260", "https://images.pexels.com/photos/3787839/pexels-photo-3787839.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "https://images.pexels.com/photos/3769312/pexels-photo-3769312.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940")
And tried updating the code in help_functions.php file as below
$images = dynamic_sidebar( 'splashimage-widget-area' );
$rand_img = array_rand($images, 1);
$header_type=20;
$image =$images[$rand_img];
Its not working as expected.
Expected result, Add images link in the widget and update the help_functions.php file to show the different images on refresh.
I register a new custom widget
You are registering an area for the widgets using register_sidebar(), not the widget itself.
This widget area allows you to assign widgets (custom HTML, image, recent posts etc) into that area and specify where you want them to appear in your template files.
To register a widget you need to use register_widget() function and class, see this tutorial on how to create your first widget.
However, if you don't want to register new widget you can register shortcode that outputs what you want, then add it via a custom html/text widget.
Registering shortcode is very easy using add_shortcode() function, especially if you plan to hardcode an array of images and not pass any attributes.
More on registering shortcode here.

How to add a second custom header element to WooCommerce Storefront Powerpack

I am using the following code for adding an extra custom text element to the Powerpack Header Customization:
// Adds the text element to the powerpack header components
function sp_header_components_custom_text( $components ) {
$components['text'] = array(
'title' => __( 'Custom Text', 'storefront-powerpack' ),
'hook' => 'sp_header_custom_text_output'
);
return $components;
}
add_filter( 'sp_header_components', 'sp_header_components_custom_text' );
// Adds text area output to the Storefront header
function sp_header_custom_text_output() {
echo '<div class="custom-text">';
echo 'Some custom text added to header in Storefront Powerpack';
echo '</div>';
}
add_action( 'storefront_header', 'sp_header_custom_text_output' );
But I am wondering how to add a second custom text element? Copying the code and adding a “_two” to the function names doesn’t work unfortunately.
Looking forward for some help and advice!
Kind regards Abidin

Theme Customizer - Allowing users to change background image of multiple divs

I'm trying to have a feature where users can change the background image of certain divs via the theme customizer. I've tried many different ways but can't seem to get it to work.
As of right now I have it to where I'm able to change the background of one div but not able to get more than that one.
Function.php file
function meraki_custom_background_cb() {
ob_start();
_custom_background_cb(); // Default handler
$style = ob_get_clean();
$style = str_replace( 'body.custom-background', '#featured-home-image', $style );
echo $style;
}
add_theme_support( 'custom-background',
array(
'wp-head-callback' => 'meraki_custom_background_cb',
'default-color' => '000000',
'default-image' => '%1$s/images/background.jpg',
)
);
header.php file
<style type="text/css" id="custom-background-css">
body.custom-background { background-color: #bdd96e; }
</style>
I'm pretty sure what this is doing is just replacing the string 'body.custom-background' with the ID #featured-homeimage', which works great, but only for one div.
Is there a way to make this possible for multiple divs? Thanks in advance for your help.

My custom TinyMCE format to clear formatting is disabled unless the targeted selector is the only thing highlighted

I created a simple WordPress plugin (copied below) to add a custom button to TinyMCE that removes certain formatting, in this case span tags. I tested it out on a post whose content is as follows:
a <span style="color: red;">test</span>
But the button only works if I highlight the targeted selector only. In this case, if I highlight "test" and then click my "Remove spans" button under the "Formats" button, it works. But if I highlight "a test", the "Remove spans" option becomes disabled and does not work.
This seems like it should be doable, since TinyMCE's built-in "Clear formatting" button works in this situation.
My goal is to make a plugin (either by modifying the "Clear formatting" functionality or making a similar custom button) that clears certain kinds of formatting but not others. I want to remove colors but keep strong tags, for example.
Here is my full plugin code:
<?php
// Callback function to insert 'styleselect' into the $buttons array
function my_mce_buttons_2( $buttons ) {
array_unshift( $buttons, 'styleselect' );
return $buttons;
}
// Register our callback to the appropriate filter
add_filter('mce_buttons_2', 'my_mce_buttons_2');
// Callback function to filter the MCE settings
function my_mce_before_init_insert_formats( $init_array ) {
// Define the style_formats array
$style_formats = array(
// Each array child is a format with it's own settings
array(
'title' => 'Remove spans',
'selector' => 'span',
'remove' => 'all'
),
);
// Insert the array, JSON ENCODED, into 'style_formats'
$init_array['style_formats'] = json_encode( $style_formats );
return $init_array;
}
// Attach callback to 'tiny_mce_before_init'
add_filter( 'tiny_mce_before_init', 'my_mce_before_init_insert_formats' );
?>

Categories